| Index: lib/snippets.js |
| =================================================================== |
| --- a/lib/snippets.js |
| +++ b/lib/snippets.js |
| @@ -18,16 +18,20 @@ |
| "use strict"; |
| /** |
| * @fileOverview Snippets implementation. |
| */ |
| const {Filter} = require("./filterClasses"); |
| +const singleCharacterEscapes = new Map([ |
| + ["n", "\n"], ["r", "\r"], ["t", "\t"] |
| +]); |
| + |
| let filters = new Set(); |
| /** |
| * Container for snippet filters |
| * @class |
| */ |
| let Snippets = { |
| /** |
| @@ -70,8 +74,92 @@ |
| if (filter.isActiveOnDomain(domain)) |
| result.push(filter.script); |
| } |
| return result; |
| } |
| }; |
| exports.Snippets = Snippets; |
| + |
| +/** |
| + * Parses a script and returns a list of all its commands and their arguments |
| + * @param {string} script |
| + * @return {Array.<string[]>} |
| + */ |
| +function parseScript(script) |
| +{ |
| + let tree = []; |
| + |
| + // Whether the next character should be treated as an escape sequence. |
|
kzar
2018/07/12 10:30:37
I don't these new comments add much, and they are
Manish Jethani
2018/07/12 10:57:49
Well I'm glad you think so, because I don't like t
|
| + let escape = false; |
| + |
| + // Whether we are within a quoted sequence. |
| + let withinQuotes = false; |
| + |
| + // The Unicode code point following a "\u" |
| + let unicodeEscape = null; |
| + |
| + let call = []; |
| + let argument = ""; |
| + |
| + // The terminating semicolon for the last command is optional; we add one |
| + // here to make our loop consistent. |
| + for (let character of script.trim() + ";") |
| + { |
| + if (unicodeEscape != null) |
| + { |
| + unicodeEscape += character; |
| + |
| + if (unicodeEscape.length == 4) |
| + { |
| + // Consider the Unicode escape only if it parses as a valid code point. |
| + let codePoint = parseInt(unicodeEscape, 16); |
| + if (!isNaN(codePoint)) |
| + argument += String.fromCodePoint(codePoint); |
| + |
| + unicodeEscape = null; |
| + } |
| + } |
| + else if (escape) |
| + { |
| + escape = false; |
| + |
| + if (character == "u") |
| + unicodeEscape = ""; |
| + else |
| + argument += singleCharacterEscapes.get(character) || character; |
| + } |
| + else if (character == "\\") |
| + { |
| + escape = true; |
| + } |
| + else if (character == "'") |
| + { |
| + withinQuotes = !withinQuotes; |
|
kzar
2018/07/12 10:30:37
Nice, I think this variable name is an improvement
|
| + } |
| + // Normally a semicolon or a whitespace character marks the end of an |
| + // argument, but within quotes these characters are taken literally and |
| + // included in the argument. |
| + else if (withinQuotes || character != ";" && !/\s/u.test(character)) |
| + { |
| + argument += character; |
| + } |
| + else |
| + { |
| + if (argument) |
| + { |
| + call.push(argument); |
| + argument = ""; |
| + } |
| + |
| + if (character == ";" && call.length > 0) |
| + { |
| + tree.push(call); |
| + call = []; |
| + } |
| + } |
| + } |
| + |
| + return tree; |
| +} |
| + |
| +exports.parseScript = parseScript; |