| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- 'use strict';
- const acorn = require('acorn');
- function _stripLiteralAcorn(code, options) {
- const FILL = options?.fillChar ?? " ";
- const FILL_COMMENT = " ";
- let result = "";
- const filter = options?.filter ?? (() => true);
- function fillupTo(index) {
- if (index > result.length)
- result += code.slice(result.length, index).replace(/[^\n]/g, FILL_COMMENT);
- }
- const tokens = [];
- const pasers = acorn.tokenizer(code, {
- ecmaVersion: "latest",
- sourceType: "module",
- allowHashBang: true,
- allowAwaitOutsideFunction: true,
- allowImportExportEverywhere: true
- });
- const iter = pasers[Symbol.iterator]();
- let error;
- try {
- while (true) {
- const { done, value: token } = iter.next();
- if (done)
- break;
- tokens.push(token);
- fillupTo(token.start);
- if (token.type.label === "string") {
- const body = code.slice(token.start + 1, token.end - 1);
- if (filter(body)) {
- result += code[token.start] + FILL.repeat(token.end - token.start - 2) + code[token.end - 1];
- continue;
- }
- } else if (token.type.label === "template") {
- const body = code.slice(token.start, token.end);
- if (filter(body)) {
- result += FILL.repeat(token.end - token.start);
- continue;
- }
- } else if (token.type.label === "regexp") {
- const body = code.slice(token.start, token.end);
- if (filter(body)) {
- result += body.replace(/\/(.*)\/(\w?)$/g, (_, $1, $2) => `/${FILL.repeat($1.length)}/${$2}`);
- continue;
- }
- }
- result += code.slice(token.start, token.end);
- }
- fillupTo(code.length);
- } catch (e) {
- error = e;
- }
- return {
- error,
- result,
- tokens
- };
- }
- function stripLiteralAcorn(code, options) {
- const result = _stripLiteralAcorn(code, options);
- if (result.error)
- throw result.error;
- return result.result;
- }
- function createIsLiteralPositionAcorn(code) {
- const positionList = [];
- const tokens = acorn.tokenizer(code, {
- ecmaVersion: "latest",
- sourceType: "module",
- allowHashBang: true,
- allowAwaitOutsideFunction: true,
- allowImportExportEverywhere: true,
- onComment(_isBlock, _text, start, end) {
- positionList.push(start);
- positionList.push(end);
- }
- });
- const inter = tokens[Symbol.iterator]();
- while (true) {
- const { done, value: token } = inter.next();
- if (done)
- break;
- if (token.type.label === "string") {
- positionList.push(token.start + 1);
- positionList.push(token.end - 1);
- } else if (token.type.label === "template") {
- positionList.push(token.start);
- positionList.push(token.end);
- }
- }
- return (position) => {
- const i = binarySearch(positionList, (v) => position < v);
- return (i - 1) % 2 === 0;
- };
- }
- function binarySearch(array, pred) {
- let low = -1;
- let high = array.length;
- while (1 + low < high) {
- const mid = low + (high - low >> 1);
- if (pred(array[mid]))
- high = mid;
- else
- low = mid;
- }
- return high;
- }
- const multilineCommentsRE = /\/\*([^*\/])*?\*\//gms;
- const singlelineCommentsRE = /(?:^|\n|\r)\s*\/\/.*(?:\r|\n|$)/gm;
- const templateLiteralRE = /\$\{(\s*(?:|{.*}|(?!\$\{).|\n|\r)*?\s*)\}/g;
- const quotesRE = [
- /(["'`])((?:\\\1|(?!\1)|.|\r)*?)\1/gm,
- /([`])((?:\\\1|(?!\1)|.|\n|\r)*?)\1/gm
- // multi-line strings (i.e. template literals only)
- ];
- function stripLiteralRegex(code, options) {
- const FILL_COMMENT = " ";
- const FILL = options?.fillChar ?? " ";
- const filter = options?.filter ?? (() => true);
- code = code.replace(multilineCommentsRE, (s) => filter(s) ? FILL_COMMENT.repeat(s.length) : s).replace(singlelineCommentsRE, (s) => filter(s) ? FILL_COMMENT.repeat(s.length) : s);
- let expanded = code;
- for (let i = 0; i < 16; i++) {
- const before = expanded;
- expanded = expanded.replace(templateLiteralRE, "` $1`");
- if (expanded === before)
- break;
- }
- quotesRE.forEach((re) => {
- expanded = expanded.replace(re, (s, quote, body, index) => {
- if (!filter(s.slice(1, -1)))
- return s;
- code = code.slice(0, index + 1) + FILL.repeat(s.length - 2) + code.slice(index + s.length - 1);
- return quote + FILL.repeat(s.length - 2) + quote;
- });
- });
- return code;
- }
- function stripLiteral(code, options) {
- return stripLiteralDetailed(code, options).result;
- }
- function stripLiteralDetailed(code, options) {
- const acorn = _stripLiteralAcorn(code, options);
- if (!acorn.error) {
- return {
- mode: "acorn",
- result: acorn.result,
- acorn
- };
- }
- return {
- mode: "regex",
- result: stripLiteralRegex(acorn.result + code.slice(acorn.result.length), options),
- acorn
- };
- }
- exports.createIsLiteralPositionAcorn = createIsLiteralPositionAcorn;
- exports.stripLiteral = stripLiteral;
- exports.stripLiteralAcorn = stripLiteralAcorn;
- exports.stripLiteralDetailed = stripLiteralDetailed;
- exports.stripLiteralRegex = stripLiteralRegex;
|