(filename)
| 99 | // ident checked is true in our global. |
| 100 | // Also handles #include x.js (similar to C #include <file>) |
| 101 | export function preprocess(filename) { |
| 102 | let text = readFile(filename); |
| 103 | // Remove windows line endings, if any |
| 104 | text = text.replace(/\r\n/g, '\n'); |
| 105 | |
| 106 | const IGNORE = 0; |
| 107 | const SHOW = 1; |
| 108 | // This state is entered after we have shown one of the block of an if/elif/else sequence. |
| 109 | // Once we enter this state we don't show any blocks or evaluate any |
| 110 | // conditions until the sequence ends. |
| 111 | const IGNORE_ALL = 2; |
| 112 | const showStack = []; |
| 113 | const showCurrentLine = () => showStack.every((x) => x == SHOW); |
| 114 | |
| 115 | const fileExt = filename.split('.').pop().toLowerCase(); |
| 116 | const isHtml = fileExt === 'html' || fileExt === 'htm' ? true : false; |
| 117 | let inStyle = false; |
| 118 | const lines = text.split('\n'); |
| 119 | // text.split yields an extra empty element at the end if text itself ends with a newline. |
| 120 | if (!lines[lines.length - 1]) { |
| 121 | lines.pop(); |
| 122 | } |
| 123 | |
| 124 | let ret = ''; |
| 125 | let emptyLine = false; |
| 126 | |
| 127 | pushCurrentFile(filename); |
| 128 | try { |
| 129 | for (const [i, line] of lines.entries()) { |
| 130 | if (isHtml) { |
| 131 | if (line.includes('<style') && !inStyle) { |
| 132 | inStyle = true; |
| 133 | } |
| 134 | if (line.includes('</style') && inStyle) { |
| 135 | inStyle = false; |
| 136 | } |
| 137 | if (inStyle) { |
| 138 | if (showCurrentLine()) { |
| 139 | ret += line + '\n'; |
| 140 | } |
| 141 | continue; |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | const trimmed = line.trim(); |
| 146 | if (trimmed.startsWith('#')) { |
| 147 | const first = trimmed.split(' ', 1)[0]; |
| 148 | if (first == '#if' || first == '#ifdef' || first == '#elif') { |
| 149 | if (first == '#ifdef') { |
| 150 | warn('use of #ifdef in js library. Use #if instead.'); |
| 151 | } |
| 152 | if (first == '#elif') { |
| 153 | const curr = showStack.pop(); |
| 154 | if (curr == SHOW || curr == IGNORE_ALL) { |
| 155 | // If we showed to previous block we enter the IGNORE_ALL state |
| 156 | // and stay there until endif is seen |
| 157 | showStack.push(IGNORE_ALL); |
| 158 | continue; |
no test coverage detected