| 11 | } |
| 12 | |
| 13 | pub fn preprocess(content: &str) -> (String, BladeSourceMap) { |
| 14 | let mut virtual_php = String::with_capacity(content.len() + 512); |
| 15 | let mut source_map = BladeSourceMap::default(); |
| 16 | |
| 17 | // ── Prologue (5 lines) ── |
| 18 | virtual_php.push_str("<?php if (!function_exists('blade_directive')) { function blade_directive(...$args) {} function blade_view_directive(...$args) {} }\n"); |
| 19 | virtual_php.push_str("/** @var \\Illuminate\\Support\\ViewErrorBag $errors */\n"); |
| 20 | virtual_php.push_str("$errors = new \\Illuminate\\Support\\ViewErrorBag();\n"); |
| 21 | virtual_php.push_str("/** @var \\Illuminate\\View\\Factory $__env */\n"); |
| 22 | virtual_php.push_str("$__env = new \\Illuminate\\View\\Factory();\n"); |
| 23 | // Wrap the template body in a function so that diagnostic |
| 24 | // collectors (which only analyse function/method bodies) treat |
| 25 | // the Blade content as analysable code. The closing brace is |
| 26 | // appended after the main loop. |
| 27 | virtual_php.push_str("function __blade_template() {\n"); |
| 28 | |
| 29 | let mut in_php_directive_block = false; |
| 30 | let mut mode = Mode::Html; |
| 31 | let mut paren_depth = 0; |
| 32 | let mut in_string: Option<char> = None; |
| 33 | let mut is_escaped = false; |
| 34 | |
| 35 | for line in content.lines() { |
| 36 | let mut processed = String::new(); |
| 37 | let mut adjustments = vec![(0, 0)]; // (blade_utf16_col, php_utf16_col) |
| 38 | |
| 39 | let mut current_utf16_col = 0; |
| 40 | let line_chars: Vec<char> = line.chars().collect(); |
| 41 | let mut buffer = String::new(); |
| 42 | |
| 43 | if mode == Mode::Html && in_php_directive_block { |
| 44 | mode = Mode::Php; |
| 45 | } |
| 46 | |
| 47 | let mut char_idx = 0; |
| 48 | while char_idx < line_chars.len() { |
| 49 | let ch = line_chars[char_idx]; |
| 50 | |
| 51 | if mode != Mode::Html { |
| 52 | if let Some(quote) = in_string { |
| 53 | if is_escaped { |
| 54 | is_escaped = false; |
| 55 | } else if ch == '\\' { |
| 56 | is_escaped = true; |
| 57 | } else if ch == quote { |
| 58 | in_string = None; |
| 59 | } |
| 60 | buffer.push(ch); |
| 61 | char_idx += 1; |
| 62 | current_utf16_col += ch.len_utf16() as u32; |
| 63 | continue; |
| 64 | } else if ch == '\'' || ch == '"' { |
| 65 | in_string = Some(ch); |
| 66 | buffer.push(ch); |
| 67 | char_idx += 1; |
| 68 | current_utf16_col += ch.len_utf16() as u32; |
| 69 | continue; |
| 70 | } |