feat: docker compose maybe
This commit is contained in:
390
node_modules/code-red/src/index.js
generated
vendored
Normal file
390
node_modules/code-red/src/index.js
generated
vendored
Normal file
@ -0,0 +1,390 @@
|
||||
import * as acorn from 'acorn';
|
||||
import { walk } from 'estree-walker';
|
||||
import { id, re } from './utils/id.js';
|
||||
import { get_comment_handlers } from './utils/comments.js';
|
||||
|
||||
/** @typedef {import('estree').Expression} Expression */
|
||||
/** @typedef {import('estree').Node} Node */
|
||||
/** @typedef {import('estree').ObjectExpression} ObjectExpression */
|
||||
/** @typedef {import('estree').Property} Property */
|
||||
/** @typedef {import('estree').SpreadElement} SpreadElement */
|
||||
|
||||
/** @typedef {import('./utils/comments').CommentWithLocation} CommentWithLocation */
|
||||
|
||||
/** @type {Record<string, string>} */
|
||||
const sigils = {
|
||||
'@': 'AT',
|
||||
'#': 'HASH'
|
||||
};
|
||||
|
||||
/** @param {TemplateStringsArray} strings */
|
||||
const join = (strings) => {
|
||||
let str = strings[0];
|
||||
for (let i = 1; i < strings.length; i += 1) {
|
||||
str += `_${id}_${i - 1}_${strings[i]}`;
|
||||
}
|
||||
return str.replace(
|
||||
/([@#])(\w+)/g,
|
||||
(_m, sigil, name) => `_${id}_${sigils[sigil]}_${name}`
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {any[]} array
|
||||
* @param {any[]} target
|
||||
*/
|
||||
const flatten_body = (array, target) => {
|
||||
for (let i = 0; i < array.length; i += 1) {
|
||||
const statement = array[i];
|
||||
if (Array.isArray(statement)) {
|
||||
flatten_body(statement, target);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (statement.type === 'ExpressionStatement') {
|
||||
if (statement.expression === EMPTY) continue;
|
||||
|
||||
if (Array.isArray(statement.expression)) {
|
||||
// TODO this is hacktacular
|
||||
let node = statement.expression[0];
|
||||
while (Array.isArray(node)) node = node[0];
|
||||
if (node) node.leadingComments = statement.leadingComments;
|
||||
|
||||
flatten_body(statement.expression, target);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (/(Expression|Literal)$/.test(statement.expression.type)) {
|
||||
target.push(statement);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (statement.leadingComments)
|
||||
statement.expression.leadingComments = statement.leadingComments;
|
||||
if (statement.trailingComments)
|
||||
statement.expression.trailingComments = statement.trailingComments;
|
||||
|
||||
target.push(statement.expression);
|
||||
continue;
|
||||
}
|
||||
|
||||
target.push(statement);
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {any[]} array
|
||||
* @param {any[]} target
|
||||
*/
|
||||
const flatten_properties = (array, target) => {
|
||||
for (let i = 0; i < array.length; i += 1) {
|
||||
const property = array[i];
|
||||
|
||||
if (property.value === EMPTY) continue;
|
||||
|
||||
if (property.key === property.value && Array.isArray(property.key)) {
|
||||
flatten_properties(property.key, target);
|
||||
continue;
|
||||
}
|
||||
|
||||
target.push(property);
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {any[]} nodes
|
||||
* @param {any[]} target
|
||||
*/
|
||||
const flatten = (nodes, target) => {
|
||||
for (let i = 0; i < nodes.length; i += 1) {
|
||||
const node = nodes[i];
|
||||
|
||||
if (node === EMPTY) continue;
|
||||
|
||||
if (Array.isArray(node)) {
|
||||
flatten(node, target);
|
||||
continue;
|
||||
}
|
||||
|
||||
target.push(node);
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
const EMPTY = { type: 'Empty' };
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {CommentWithLocation[]} comments
|
||||
* @param {string} raw
|
||||
* @returns {any}
|
||||
*/
|
||||
const acorn_opts = (comments, raw) => {
|
||||
const { onComment } = get_comment_handlers(comments, raw);
|
||||
return {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
allowAwaitOutsideFunction: true,
|
||||
allowImportExportEverywhere: true,
|
||||
allowReturnOutsideFunction: true,
|
||||
onComment
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} raw
|
||||
* @param {Node} node
|
||||
* @param {any[]} values
|
||||
* @param {CommentWithLocation[]} comments
|
||||
*/
|
||||
const inject = (raw, node, values, comments) => {
|
||||
comments.forEach((comment) => {
|
||||
comment.value = comment.value.replace(re, (m, i) =>
|
||||
+i in values ? values[+i] : m
|
||||
);
|
||||
});
|
||||
|
||||
const { enter, leave } = get_comment_handlers(comments, raw);
|
||||
|
||||
return walk(node, {
|
||||
enter,
|
||||
|
||||
/** @param {any} node */
|
||||
leave(node) {
|
||||
if (node.type === 'Identifier') {
|
||||
re.lastIndex = 0;
|
||||
const match = re.exec(node.name);
|
||||
|
||||
if (match) {
|
||||
if (match[1]) {
|
||||
if (+match[1] in values) {
|
||||
let value = values[+match[1]];
|
||||
|
||||
if (typeof value === 'string') {
|
||||
value = {
|
||||
type: 'Identifier',
|
||||
name: value,
|
||||
leadingComments: node.leadingComments,
|
||||
trailingComments: node.trailingComments
|
||||
};
|
||||
} else if (typeof value === 'number') {
|
||||
value = {
|
||||
type: 'Literal',
|
||||
value,
|
||||
leadingComments: node.leadingComments,
|
||||
trailingComments: node.trailingComments
|
||||
};
|
||||
}
|
||||
|
||||
this.replace(value || EMPTY);
|
||||
}
|
||||
} else {
|
||||
node.name = `${match[2] ? `@` : `#`}${match[4]}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type === 'Literal') {
|
||||
if (typeof node.value === 'string') {
|
||||
re.lastIndex = 0;
|
||||
const new_value = /** @type {string} */ (node.value).replace(
|
||||
re,
|
||||
(m, i) => (+i in values ? values[+i] : m)
|
||||
);
|
||||
const has_changed = new_value !== node.value;
|
||||
node.value = new_value;
|
||||
if (has_changed && node.raw) {
|
||||
// preserve the quotes
|
||||
node.raw = `${node.raw[0]}${JSON.stringify(node.value).slice(
|
||||
1,
|
||||
-1
|
||||
)}${node.raw[node.raw.length - 1]}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type === 'TemplateElement') {
|
||||
re.lastIndex = 0;
|
||||
node.value.raw = /** @type {string} */ (node.value.raw).replace(
|
||||
re,
|
||||
(m, i) => (+i in values ? values[+i] : m)
|
||||
);
|
||||
}
|
||||
|
||||
if (node.type === 'Program' || node.type === 'BlockStatement') {
|
||||
node.body = flatten_body(node.body, []);
|
||||
}
|
||||
|
||||
if (node.type === 'ObjectExpression' || node.type === 'ObjectPattern') {
|
||||
node.properties = flatten_properties(node.properties, []);
|
||||
}
|
||||
|
||||
if (node.type === 'ArrayExpression' || node.type === 'ArrayPattern') {
|
||||
node.elements = flatten(node.elements, []);
|
||||
}
|
||||
|
||||
if (
|
||||
node.type === 'FunctionExpression' ||
|
||||
node.type === 'FunctionDeclaration' ||
|
||||
node.type === 'ArrowFunctionExpression'
|
||||
) {
|
||||
node.params = flatten(node.params, []);
|
||||
}
|
||||
|
||||
if (node.type === 'CallExpression' || node.type === 'NewExpression') {
|
||||
node.arguments = flatten(node.arguments, []);
|
||||
}
|
||||
|
||||
if (
|
||||
node.type === 'ImportDeclaration' ||
|
||||
node.type === 'ExportNamedDeclaration'
|
||||
) {
|
||||
node.specifiers = flatten(node.specifiers, []);
|
||||
}
|
||||
|
||||
if (node.type === 'ForStatement') {
|
||||
node.init = node.init === EMPTY ? null : node.init;
|
||||
node.test = node.test === EMPTY ? null : node.test;
|
||||
node.update = node.update === EMPTY ? null : node.update;
|
||||
}
|
||||
|
||||
leave(node);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {TemplateStringsArray} strings
|
||||
* @param {any[]} values
|
||||
* @returns {Node[]}
|
||||
*/
|
||||
export function b(strings, ...values) {
|
||||
const str = join(strings);
|
||||
|
||||
/** @type {CommentWithLocation[]} */
|
||||
const comments = [];
|
||||
|
||||
try {
|
||||
let ast = /** @type {any} */ (acorn.parse(str, acorn_opts(comments, str)));
|
||||
|
||||
ast = inject(str, ast, values, comments);
|
||||
|
||||
return ast.body;
|
||||
} catch (err) {
|
||||
handle_error(str, err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {TemplateStringsArray} strings
|
||||
* @param {any[]} values
|
||||
* @returns {Expression & { start: Number, end: number }}
|
||||
*/
|
||||
export function x(strings, ...values) {
|
||||
const str = join(strings);
|
||||
|
||||
/** @type {CommentWithLocation[]} */
|
||||
const comments = [];
|
||||
|
||||
try {
|
||||
let expression =
|
||||
/** @type {Expression & { start: Number, end: number }} */ (
|
||||
acorn.parseExpressionAt(str, 0, acorn_opts(comments, str))
|
||||
);
|
||||
const match = /\S+/.exec(str.slice(expression.end));
|
||||
if (match) {
|
||||
throw new Error(`Unexpected token '${match[0]}'`);
|
||||
}
|
||||
|
||||
expression = /** @type {Expression & { start: Number, end: number }} */ (
|
||||
inject(str, expression, values, comments)
|
||||
);
|
||||
|
||||
return expression;
|
||||
} catch (err) {
|
||||
handle_error(str, err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {TemplateStringsArray} strings
|
||||
* @param {any[]} values
|
||||
* @returns {(Property | SpreadElement) & { start: Number, end: number }}
|
||||
*/
|
||||
export function p(strings, ...values) {
|
||||
const str = `{${join(strings)}}`;
|
||||
|
||||
/** @type {CommentWithLocation[]} */
|
||||
const comments = [];
|
||||
|
||||
try {
|
||||
let expression = /** @type {any} */ (
|
||||
acorn.parseExpressionAt(str, 0, acorn_opts(comments, str))
|
||||
);
|
||||
|
||||
expression = inject(str, expression, values, comments);
|
||||
|
||||
return expression.properties[0];
|
||||
} catch (err) {
|
||||
handle_error(str, err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} str
|
||||
* @param {Error} err
|
||||
*/
|
||||
function handle_error(str, err) {
|
||||
// TODO location/code frame
|
||||
|
||||
re.lastIndex = 0;
|
||||
|
||||
str = str.replace(re, (m, i, at, hash, name) => {
|
||||
if (at) return `@${name}`;
|
||||
if (hash) return `#${name}`;
|
||||
|
||||
return '${...}';
|
||||
});
|
||||
|
||||
console.log(`failed to parse:\n${str}`);
|
||||
throw err;
|
||||
}
|
||||
|
||||
export { print } from './print/index.js';
|
||||
|
||||
/**
|
||||
* @param {string} source
|
||||
* @param {any} opts
|
||||
*/
|
||||
export const parse = (source, opts) => {
|
||||
/** @type {CommentWithLocation[]} */
|
||||
const comments = [];
|
||||
const { onComment, enter, leave } = get_comment_handlers(comments, source);
|
||||
const ast = /** @type {any} */ (acorn.parse(source, { onComment, ...opts }));
|
||||
walk(ast, { enter, leave });
|
||||
return ast;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} source
|
||||
* @param {number} index
|
||||
* @param {any} opts
|
||||
*/
|
||||
export const parseExpressionAt = (source, index, opts) => {
|
||||
/** @type {CommentWithLocation[]} */
|
||||
const comments = [];
|
||||
const { onComment, enter, leave } = get_comment_handlers(comments, source);
|
||||
const ast = /** @type {any} */ (
|
||||
acorn.parseExpressionAt(source, index, { onComment, ...opts })
|
||||
);
|
||||
walk(ast, { enter, leave });
|
||||
return ast;
|
||||
};
|
1513
node_modules/code-red/src/print/handlers.js
generated
vendored
Executable file
1513
node_modules/code-red/src/print/handlers.js
generated
vendored
Executable file
File diff suppressed because it is too large
Load Diff
145
node_modules/code-red/src/print/index.js
generated
vendored
Normal file
145
node_modules/code-red/src/print/index.js
generated
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
import * as perisopic from 'periscopic';
|
||||
import { handle } from './handlers.js';
|
||||
import { encode } from '@jridgewell/sourcemap-codec';
|
||||
|
||||
/** @type {(str?: string) => string} str */
|
||||
let btoa = () => {
|
||||
throw new Error(
|
||||
'Unsupported environment: `window.btoa` or `Buffer` should be supported.'
|
||||
);
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
|
||||
btoa = (str) => window.btoa(unescape(encodeURIComponent(str)));
|
||||
} else if (typeof Buffer === 'function') {
|
||||
btoa = (str) => Buffer.from(str, 'utf-8').toString('base64');
|
||||
}
|
||||
|
||||
/** @typedef {import('estree').Node} Node */
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* file?: string;
|
||||
* sourceMapSource?: string;
|
||||
* sourceMapContent?: string;
|
||||
* sourceMapEncodeMappings?: boolean; // default true
|
||||
* getName?: (name: string) => string;
|
||||
* }} PrintOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @param {PrintOptions} opts
|
||||
* @returns {{ code: string, map: any }} // TODO
|
||||
*/
|
||||
export function print(node, opts = {}) {
|
||||
if (Array.isArray(node)) {
|
||||
return print(
|
||||
{
|
||||
type: 'Program',
|
||||
body: node,
|
||||
sourceType: 'module'
|
||||
},
|
||||
opts
|
||||
);
|
||||
}
|
||||
|
||||
const {
|
||||
getName = /** @param {string} x */ (x) => {
|
||||
throw new Error(`Unhandled sigil @${x}`);
|
||||
}
|
||||
} = opts;
|
||||
|
||||
let { map: scope_map, scope } = perisopic.analyze(node);
|
||||
const deconflicted = new WeakMap();
|
||||
|
||||
const chunks = handle(node, {
|
||||
indent: '',
|
||||
getName,
|
||||
scope,
|
||||
scope_map,
|
||||
deconflicted,
|
||||
comments: []
|
||||
});
|
||||
|
||||
/** @typedef {[number, number, number, number]} Segment */
|
||||
|
||||
let code = '';
|
||||
let current_column = 0;
|
||||
|
||||
/** @type {Segment[][]} */
|
||||
let mappings = [];
|
||||
|
||||
/** @type {Segment[]} */
|
||||
let current_line = [];
|
||||
|
||||
for (let i = 0; i < chunks.length; i += 1) {
|
||||
const chunk = chunks[i];
|
||||
|
||||
code += chunk.content;
|
||||
|
||||
if (chunk.loc) {
|
||||
current_line.push([
|
||||
current_column,
|
||||
0, // source index is always zero
|
||||
chunk.loc.start.line - 1,
|
||||
chunk.loc.start.column
|
||||
]);
|
||||
}
|
||||
|
||||
for (let i = 0; i < chunk.content.length; i += 1) {
|
||||
if (chunk.content[i] === '\n') {
|
||||
mappings.push(current_line);
|
||||
current_line = [];
|
||||
current_column = 0;
|
||||
} else {
|
||||
current_column += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (chunk.loc) {
|
||||
current_line.push([
|
||||
current_column,
|
||||
0, // source index is always zero
|
||||
chunk.loc.end.line - 1,
|
||||
chunk.loc.end.column
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
mappings.push(current_line);
|
||||
|
||||
const map = {
|
||||
version: 3,
|
||||
/** @type {string[]} */
|
||||
names: [],
|
||||
sources: [opts.sourceMapSource || null],
|
||||
sourcesContent: [opts.sourceMapContent || null],
|
||||
mappings:
|
||||
opts.sourceMapEncodeMappings == undefined || opts.sourceMapEncodeMappings
|
||||
? encode(mappings)
|
||||
: mappings
|
||||
};
|
||||
|
||||
Object.defineProperties(map, {
|
||||
toString: {
|
||||
enumerable: false,
|
||||
value: function toString() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
},
|
||||
toUrl: {
|
||||
enumerable: false,
|
||||
value: function toUrl() {
|
||||
return (
|
||||
'data:application/json;charset=utf-8;base64,' + btoa(this.toString())
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
code,
|
||||
map
|
||||
};
|
||||
}
|
86
node_modules/code-red/src/utils/comments.js
generated
vendored
Normal file
86
node_modules/code-red/src/utils/comments.js
generated
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
import { re } from './id.js';
|
||||
|
||||
/** @typedef {import('estree').Comment} Comment */
|
||||
/** @typedef {import('estree').Node} Node */
|
||||
|
||||
/**
|
||||
* @typedef {Node & {
|
||||
* start: number;
|
||||
* end: number;
|
||||
* has_trailing_newline?: boolean
|
||||
* }} NodeWithLocation
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Comment & {
|
||||
* start: number;
|
||||
* end: number;
|
||||
* has_trailing_newline?: boolean
|
||||
* }} CommentWithLocation
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {CommentWithLocation[]} comments
|
||||
* @param {string} raw
|
||||
*/
|
||||
export const get_comment_handlers = (comments, raw) => ({
|
||||
// pass to acorn options
|
||||
/**
|
||||
* @param {boolean} block
|
||||
* @param {string} value
|
||||
* @param {number} start
|
||||
* @param {number} end
|
||||
*/
|
||||
onComment: (block, value, start, end) => {
|
||||
if (block && /\n/.test(value)) {
|
||||
let a = start;
|
||||
while (a > 0 && raw[a - 1] !== '\n') a -= 1;
|
||||
|
||||
let b = a;
|
||||
while (/[ \t]/.test(raw[b])) b += 1;
|
||||
|
||||
const indentation = raw.slice(a, b);
|
||||
value = value.replace(new RegExp(`^${indentation}`, 'gm'), '');
|
||||
}
|
||||
|
||||
comments.push({ type: block ? 'Block' : 'Line', value, start, end });
|
||||
},
|
||||
|
||||
// pass to estree-walker options
|
||||
/** @param {NodeWithLocation} node */
|
||||
enter(node) {
|
||||
let comment;
|
||||
|
||||
while (comments[0] && comments[0].start < node.start) {
|
||||
comment = comments.shift();
|
||||
|
||||
comment.value = comment.value.replace(
|
||||
re,
|
||||
(match, id, at, hash, value) => {
|
||||
if (hash) return `#${value}`;
|
||||
if (at) return `@${value}`;
|
||||
|
||||
return match;
|
||||
}
|
||||
);
|
||||
|
||||
const next = comments[0] || node;
|
||||
comment.has_trailing_newline =
|
||||
comment.type === 'Line' ||
|
||||
/\n/.test(raw.slice(comment.end, next.start));
|
||||
|
||||
(node.leadingComments || (node.leadingComments = [])).push(comment);
|
||||
}
|
||||
},
|
||||
|
||||
/** @param {NodeWithLocation} node */
|
||||
leave(node) {
|
||||
if (comments[0]) {
|
||||
const slice = raw.slice(node.end, comments[0].start);
|
||||
|
||||
if (/^[,) \t]*$/.test(slice)) {
|
||||
node.trailingComments = [comments.shift()];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
3
node_modules/code-red/src/utils/id.js
generated
vendored
Normal file
3
node_modules/code-red/src/utils/id.js
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
// generate an ID that is, to all intents and purposes, unique
|
||||
export const id = Math.round(Math.random() * 1e20).toString(36);
|
||||
export const re = new RegExp(`_${id}_(?:(\\d+)|(AT)|(HASH))_(\\w+)?`, 'g');
|
12
node_modules/code-red/src/utils/push_array.js
generated
vendored
Normal file
12
node_modules/code-red/src/utils/push_array.js
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Does `array.push` for all `items`. Needed because `array.push(...items)` throws
|
||||
* "Maximum call stack size exceeded" when `items` is too big of an array.
|
||||
*
|
||||
* @param {any[]} array
|
||||
* @param {any[]} items
|
||||
*/
|
||||
export function push_array(array, items) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
array.push(items[i]);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user