This commit is contained in:
2024-03-22 03:47:51 +05:30
parent 8bcf3d211e
commit 89819f6fe2
28440 changed files with 3211033 additions and 2 deletions

133
node_modules/estree-util-to-js/lib/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,133 @@
export function toJs(tree: Program, options: OptionsWithSourceMapGenerator): ResultWithSourceMapGenerator;
export function toJs(tree: Program, options: OptionsWithMaybeMapGenerator): ResultWithMaybeSourceMapGenerator;
export function toJs(tree: Program, options?: OptionsWithoutSourceMapGenerator | null | undefined): ResultWithoutSourceMapGenerator;
export type State = import('astring').State;
export type Nodes = import('estree-jsx').Node;
export type Program = import('estree-jsx').Program;
export type SourceMapGenerator = typeof import('source-map').SourceMapGenerator;
export type Map = import('source-map').RawSourceMap;
export type Generator = Record<Nodes['type'], Handler>;
/**
* Handle a particular node.
*/
export type Handler = (this: Generator, node: any, state: State) => undefined;
export type Handlers = Partial<import('astring').Generator>;
/**
* Configuration.
*/
export type Options = OptionsWithMaybeMapGenerator;
/**
* Base shared option fields.
*/
export type OptionsFieldsBase = {
/**
* Object mapping node types to functions handling the corresponding nodes.
*/
handlers?: Handlers | null | undefined;
};
/**
* Extra option fields where theres definitely no source map generator.
*/
export type OptionsFieldsWithoutSourceMapGenerator = {
/**
* Generate a source map by passing a `SourceMapGenerator` from `source-map`
* in; this works if there is positional info on nodes.
*/
SourceMapGenerator?: null | undefined;
/**
* Path to input file; only used in source map.
*/
filePath?: null | undefined;
};
/**
* Extra option fields where theres definitely a source map generator.
*/
export type OptionsFieldsWithSourceMapGenerator = {
/**
* Generate a source map by passing a `SourceMapGenerator` from `source-map`
* in; this works if there is positional info on nodes.
*/
SourceMapGenerator: SourceMapGenerator;
/**
* Path to input file; only used in source map.
*/
filePath?: string | null | undefined;
};
/**
* Extra option fields where there may or may not be a source map generator.
*/
export type OptionsFieldsMaybeSourceMapGenerator = {
/**
* Generate a source map by passing a `SourceMapGenerator` from `source-map`
* in; this works if there is positional info on nodes.
*/
SourceMapGenerator?: SourceMapGenerator | null | undefined;
/**
* Path to input file; only used in source map.
*/
filePath?: string | null | undefined;
};
/**
* Options where theres definitely no source map generator.
*/
export type OptionsWithoutSourceMapGenerator = OptionsFieldsBase & OptionsFieldsWithoutSourceMapGenerator;
/**
* Options where theres definitely a source map generator.
*/
export type OptionsWithSourceMapGenerator = OptionsFieldsBase & OptionsFieldsWithSourceMapGenerator;
/**
* Options where there may or may not be a source map generator.
*/
export type OptionsWithMaybeMapGenerator = OptionsFieldsBase & OptionsFieldsMaybeSourceMapGenerator;
/**
* Result.
*/
export type Result = ResultWithMaybeSourceMapGenerator;
/**
* Base shared result fields.
*/
export type ResultFieldsBase = {
/**
* Serialized JavaScript.
*/
value: string;
};
/**
* Extra result fields where theres definitely no source map generator.
*/
export type ResultFieldsWithoutSourceMapGenerator = {
/**
* Source map as (parsed) JSON, if `SourceMapGenerator` is passed.
*/
map: undefined;
};
/**
* Extra result fields where theres definitely a source map generator.
*/
export type ResultFieldsWithSourceMapGenerator = {
/**
* Source map as (parsed) JSON, if `SourceMapGenerator` is not passed.
*/
map: Map;
};
/**
* Extra result fields where there may or may not be a source map generator.
*/
export type ResultFieldsMaybeSourceMapGenerator = {
/**
* Source map as (parsed) JSON, if `SourceMapGenerator` might be passed.
*/
map: Map | undefined;
};
/**
* Result where theres definitely no source map generator.
*/
export type ResultWithoutSourceMapGenerator = ResultFieldsBase & ResultFieldsWithoutSourceMapGenerator;
/**
* Result where theres definitely a source map generator.
*/
export type ResultWithSourceMapGenerator = ResultFieldsBase & ResultFieldsWithSourceMapGenerator;
/**
* Result where there may or may not be a source map generator.
*/
export type ResultWithMaybeSourceMapGenerator = ResultFieldsBase & ResultFieldsMaybeSourceMapGenerator;

145
node_modules/estree-util-to-js/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,145 @@
/**
* @typedef {import('astring').State} State
* @typedef {import('estree-jsx').Node} Nodes
* @typedef {import('estree-jsx').Program} Program
* @typedef {typeof import('source-map').SourceMapGenerator} SourceMapGenerator
* @typedef {import('source-map').RawSourceMap} Map
*/
/**
* @typedef {Record<Nodes['type'], Handler>} Generator
*
* @callback Handler
* Handle a particular node.
* @param {Generator} this
* `astring` generator.
* @param {any} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*
* @typedef {Partial<import('astring').Generator>} Handlers
*/
/**
* @typedef {OptionsWithMaybeMapGenerator} Options
* Configuration.
*
* @typedef OptionsFieldsBase
* Base shared option fields.
* @property {Handlers | null | undefined} [handlers]
* Object mapping node types to functions handling the corresponding nodes.
*
* @typedef OptionsFieldsWithoutSourceMapGenerator
* Extra option fields where theres definitely no source map generator.
* @property {null | undefined} [SourceMapGenerator]
* Generate a source map by passing a `SourceMapGenerator` from `source-map`
* in; this works if there is positional info on nodes.
* @property {null | undefined} [filePath]
* Path to input file; only used in source map.
*
* @typedef OptionsFieldsWithSourceMapGenerator
* Extra option fields where theres definitely a source map generator.
* @property {SourceMapGenerator} SourceMapGenerator
* Generate a source map by passing a `SourceMapGenerator` from `source-map`
* in; this works if there is positional info on nodes.
* @property {string | null | undefined} [filePath]
* Path to input file; only used in source map.
*
* @typedef OptionsFieldsMaybeSourceMapGenerator
* Extra option fields where there may or may not be a source map generator.
* @property {SourceMapGenerator | null | undefined} [SourceMapGenerator]
* Generate a source map by passing a `SourceMapGenerator` from `source-map`
* in; this works if there is positional info on nodes.
* @property {string | null | undefined} [filePath]
* Path to input file; only used in source map.
*
* @typedef {OptionsFieldsBase & OptionsFieldsWithoutSourceMapGenerator} OptionsWithoutSourceMapGenerator
* Options where theres definitely no source map generator.
* @typedef {OptionsFieldsBase & OptionsFieldsWithSourceMapGenerator} OptionsWithSourceMapGenerator
* Options where theres definitely a source map generator.
* @typedef {OptionsFieldsBase & OptionsFieldsMaybeSourceMapGenerator} OptionsWithMaybeMapGenerator
* Options where there may or may not be a source map generator.
*
* @typedef {ResultWithMaybeSourceMapGenerator} Result
* Result.
*
* @typedef ResultFieldsBase
* Base shared result fields.
* @property {string} value
* Serialized JavaScript.
*
* @typedef ResultFieldsWithoutSourceMapGenerator
* Extra result fields where theres definitely no source map generator.
* @property {undefined} map
* Source map as (parsed) JSON, if `SourceMapGenerator` is passed.
*
* @typedef ResultFieldsWithSourceMapGenerator
* Extra result fields where theres definitely a source map generator.
* @property {Map} map
* Source map as (parsed) JSON, if `SourceMapGenerator` is not passed.
*
* @typedef ResultFieldsMaybeSourceMapGenerator
* Extra result fields where there may or may not be a source map generator.
* @property {Map | undefined} map
* Source map as (parsed) JSON, if `SourceMapGenerator` might be passed.
*
* @typedef {ResultFieldsBase & ResultFieldsWithoutSourceMapGenerator} ResultWithoutSourceMapGenerator
* Result where theres definitely no source map generator.
* @typedef {ResultFieldsBase & ResultFieldsWithSourceMapGenerator} ResultWithSourceMapGenerator
* Result where theres definitely a source map generator.
* @typedef {ResultFieldsBase & ResultFieldsMaybeSourceMapGenerator} ResultWithMaybeSourceMapGenerator
* Result where there may or may not be a source map generator.
*/
import {GENERATOR, generate} from 'astring'
/** @type {Options} */
const emptyOptions = {}
/**
* Serialize an estree as JavaScript.
*
* @overload
* @param {Program} tree
* @param {OptionsWithSourceMapGenerator} options
* @returns {ResultWithSourceMapGenerator}
*
* @overload
* @param {Program} tree
* @param {OptionsWithMaybeMapGenerator} options
* @returns {ResultWithMaybeSourceMapGenerator}
*
* @overload
* @param {Program} tree
* @param {OptionsWithoutSourceMapGenerator | null | undefined} [options]
* @returns {ResultWithoutSourceMapGenerator}
*
* @param {Program} tree
* Estree (esast).
* @param {Options | null | undefined} [options]
* Configuration (optional).
* @returns {Result}
* Result, optionally with source map.
*/
export function toJs(tree, options) {
const {SourceMapGenerator, filePath, handlers} = options || emptyOptions
const sourceMap = SourceMapGenerator
? new SourceMapGenerator({file: filePath || '<unknown>.js'})
: undefined
const value = generate(
tree,
// @ts-expect-error: `sourceMap` can be undefined, `astring` types are buggy.
{
comments: true,
generator: {...GENERATOR, ...handlers},
sourceMap: sourceMap || undefined
}
)
const map = sourceMap ? sourceMap.toJSON() : undefined
return {value, map}
}

213
node_modules/estree-util-to-js/lib/jsx.d.ts generated vendored Normal file
View File

@@ -0,0 +1,213 @@
export namespace jsx {
export { jsxAttribute as JSXAttribute };
export { jsxClosingElement as JSXClosingElement };
export { jsxClosingFragment as JSXClosingFragment };
export { jsxElement as JSXElement };
export { jsxEmptyExpression as JSXEmptyExpression };
export { jsxExpressionContainer as JSXExpressionContainer };
export { jsxFragment as JSXFragment };
export { jsxIdentifier as JSXIdentifier };
export { jsxMemberExpression as JSXMemberExpression };
export { jsxNamespacedName as JSXNamespacedName };
export { jsxOpeningElement as JSXOpeningElement };
export { jsxOpeningFragment as JSXOpeningFragment };
export { jsxSpreadAttribute as JSXSpreadAttribute };
export { jsxText as JSXText };
}
export type JsxAttribute = import('estree-jsx').JSXAttribute;
export type JsxClosingElement = import('estree-jsx').JSXClosingElement;
export type JsxClosingFragment = import('estree-jsx').JSXClosingFragment;
export type JsxElement = import('estree-jsx').JSXElement;
export type JsxExpressionContainer = import('estree-jsx').JSXExpressionContainer;
export type JsxFragment = import('estree-jsx').JSXFragment;
export type JsxIdentifier = import('estree-jsx').JSXIdentifier;
export type JsxMemberExpression = import('estree-jsx').JSXMemberExpression;
export type JsxNamespacedName = import('estree-jsx').JSXNamespacedName;
export type JsxOpeningElement = import('estree-jsx').JSXOpeningElement;
export type JsxOpeningFragment = import('estree-jsx').JSXOpeningFragment;
export type JsxSpreadAttribute = import('estree-jsx').JSXSpreadAttribute;
export type JsxText = import('estree-jsx').JSXText;
export type Generator = import('./index.js').Generator;
export type State = import('./index.js').State;
/**
* `attr`
* `attr="something"`
* `attr={1}`
*
* @this {Generator}
* `astring` generator.
* @param {JsxAttribute} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxAttribute(this: import("./index.js").Generator, node: JsxAttribute, state: State): undefined;
/**
* `</div>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxClosingElement} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxClosingElement(this: import("./index.js").Generator, node: JsxClosingElement, state: State): undefined;
/**
* `</>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxClosingFragment} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxClosingFragment(this: import("./index.js").Generator, node: JsxClosingFragment, state: State): undefined;
/**
* `<div />`
* `<div></div>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxElement} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxElement(this: import("./index.js").Generator, node: JsxElement, state: State): undefined;
/**
* `{}` (always in a `JSXExpressionContainer`, which does the curlies)
*
* @this {Generator}
* `astring` generator.
* @returns {undefined}
* Nothing.
*/
declare function jsxEmptyExpression(this: import("./index.js").Generator): undefined;
/**
* `{expression}`
*
* @this {Generator}
* `astring` generator.
* @param {JsxExpressionContainer} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxExpressionContainer(this: import("./index.js").Generator, node: JsxExpressionContainer, state: State): undefined;
/**
* `<></>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxFragment} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxFragment(this: import("./index.js").Generator, node: JsxFragment, state: State): undefined;
/**
* `div`
*
* @this {Generator}
* `astring` generator.
* @param {JsxIdentifier} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxIdentifier(this: import("./index.js").Generator, node: JsxIdentifier, state: State): undefined;
/**
* `member.expression`
*
* @this {Generator}
* `astring` generator.
* @param {JsxMemberExpression} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxMemberExpression(this: import("./index.js").Generator, node: JsxMemberExpression, state: State): undefined;
/**
* `ns:name`
*
* @this {Generator}
* `astring` generator.
* @param {JsxNamespacedName} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxNamespacedName(this: import("./index.js").Generator, node: JsxNamespacedName, state: State): undefined;
/**
* `<div>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxOpeningElement} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxOpeningElement(this: import("./index.js").Generator, node: JsxOpeningElement, state: State): undefined;
/**
* `<>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxOpeningFragment} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxOpeningFragment(this: import("./index.js").Generator, node: JsxOpeningFragment, state: State): undefined;
/**
* `{...argument}`
*
* @this {Generator}
* `astring` generator.
* @param {JsxSpreadAttribute} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxSpreadAttribute(this: import("./index.js").Generator, node: JsxSpreadAttribute, state: State): undefined;
/**
* `!`
*
* @this {Generator}
* `astring` generator.
* @param {JsxText} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
declare function jsxText(this: import("./index.js").Generator, node: JsxText, state: State): undefined;
export {};

364
node_modules/estree-util-to-js/lib/jsx.js generated vendored Normal file
View File

@@ -0,0 +1,364 @@
/**
* @typedef {import('estree-jsx').JSXAttribute} JsxAttribute
* @typedef {import('estree-jsx').JSXClosingElement} JsxClosingElement
* @typedef {import('estree-jsx').JSXClosingFragment} JsxClosingFragment
* @typedef {import('estree-jsx').JSXElement} JsxElement
* @typedef {import('estree-jsx').JSXExpressionContainer} JsxExpressionContainer
* @typedef {import('estree-jsx').JSXFragment} JsxFragment
* @typedef {import('estree-jsx').JSXIdentifier} JsxIdentifier
* @typedef {import('estree-jsx').JSXMemberExpression} JsxMemberExpression
* @typedef {import('estree-jsx').JSXNamespacedName} JsxNamespacedName
* @typedef {import('estree-jsx').JSXOpeningElement} JsxOpeningElement
* @typedef {import('estree-jsx').JSXOpeningFragment} JsxOpeningFragment
* @typedef {import('estree-jsx').JSXSpreadAttribute} JsxSpreadAttribute
* @typedef {import('estree-jsx').JSXText} JsxText
*
* @typedef {import('./index.js').Generator} Generator
* @typedef {import('./index.js').State} State
*/
export const jsx = {
JSXAttribute: jsxAttribute,
JSXClosingElement: jsxClosingElement,
JSXClosingFragment: jsxClosingFragment,
JSXElement: jsxElement,
JSXEmptyExpression: jsxEmptyExpression,
JSXExpressionContainer: jsxExpressionContainer,
JSXFragment: jsxFragment,
JSXIdentifier: jsxIdentifier,
JSXMemberExpression: jsxMemberExpression,
JSXNamespacedName: jsxNamespacedName,
JSXOpeningElement: jsxOpeningElement,
JSXOpeningFragment: jsxOpeningFragment,
JSXSpreadAttribute: jsxSpreadAttribute,
JSXText: jsxText
}
/**
* `attr`
* `attr="something"`
* `attr={1}`
*
* @this {Generator}
* `astring` generator.
* @param {JsxAttribute} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxAttribute(node, state) {
this[node.name.type](node.name, state)
if (node.value !== null && node.value !== undefined) {
state.write('=')
// Encode double quotes in attribute values.
if (node.value.type === 'Literal') {
state.write(
'"' + encodeJsx(String(node.value.value)).replace(/"/g, '&quot;') + '"',
node
)
} else {
this[node.value.type](node.value, state)
}
}
}
/**
* `</div>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxClosingElement} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxClosingElement(node, state) {
state.write('</')
this[node.name.type](node.name, state)
state.write('>')
}
/**
* `</>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxClosingFragment} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxClosingFragment(node, state) {
state.write('</>', node)
}
/**
* `<div />`
* `<div></div>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxElement} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxElement(node, state) {
let index = -1
this[node.openingElement.type](node.openingElement, state)
if (node.children) {
while (++index < node.children.length) {
const child = node.children[index]
// Supported in types but not by Acorn.
/* c8 ignore next 3 */
if (child.type === 'JSXSpreadChild') {
throw new Error('JSX spread children are not supported')
}
this[child.type](child, state)
}
}
if (node.closingElement) {
this[node.closingElement.type](node.closingElement, state)
}
}
/**
* `{}` (always in a `JSXExpressionContainer`, which does the curlies)
*
* @this {Generator}
* `astring` generator.
* @returns {undefined}
* Nothing.
*/
function jsxEmptyExpression() {}
/**
* `{expression}`
*
* @this {Generator}
* `astring` generator.
* @param {JsxExpressionContainer} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxExpressionContainer(node, state) {
state.write('{')
this[node.expression.type](node.expression, state)
state.write('}')
}
/**
* `<></>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxFragment} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxFragment(node, state) {
let index = -1
this[node.openingFragment.type](node.openingFragment, state)
if (node.children) {
while (++index < node.children.length) {
const child = node.children[index]
// Supported in types but not by Acorn.
/* c8 ignore next 3 */
if (child.type === 'JSXSpreadChild') {
throw new Error('JSX spread children are not supported')
}
this[child.type](child, state)
}
}
this[node.closingFragment.type](node.closingFragment, state)
}
/**
* `div`
*
* @this {Generator}
* `astring` generator.
* @param {JsxIdentifier} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxIdentifier(node, state) {
state.write(node.name, node)
}
/**
* `member.expression`
*
* @this {Generator}
* `astring` generator.
* @param {JsxMemberExpression} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxMemberExpression(node, state) {
this[node.object.type](node.object, state)
state.write('.')
this[node.property.type](node.property, state)
}
/**
* `ns:name`
*
* @this {Generator}
* `astring` generator.
* @param {JsxNamespacedName} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxNamespacedName(node, state) {
this[node.namespace.type](node.namespace, state)
state.write(':')
this[node.name.type](node.name, state)
}
/**
* `<div>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxOpeningElement} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxOpeningElement(node, state) {
let index = -1
state.write('<')
this[node.name.type](node.name, state)
if (node.attributes) {
while (++index < node.attributes.length) {
state.write(' ')
this[node.attributes[index].type](node.attributes[index], state)
}
}
state.write(node.selfClosing ? ' />' : '>')
}
/**
* `<>`
*
* @this {Generator}
* `astring` generator.
* @param {JsxOpeningFragment} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxOpeningFragment(node, state) {
state.write('<>', node)
}
/**
* `{...argument}`
*
* @this {Generator}
* `astring` generator.
* @param {JsxSpreadAttribute} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxSpreadAttribute(node, state) {
state.write('{')
// eslint-disable-next-line new-cap
this.SpreadElement(node, state)
state.write('}')
}
/**
* `!`
*
* @this {Generator}
* `astring` generator.
* @param {JsxText} node
* Node to serialize.
* @param {State} state
* Info passed around.
* @returns {undefined}
* Nothing.
*/
function jsxText(node, state) {
state.write(encodeJsx(node.value).replace(/[<>{}]/g, replaceJsxChar), node)
}
/**
* Make sure that character references dont pop up.
*
* For example, the text `&copy;` should stay that way, and not turn into `©`.
* We could encode all `&` (easy but verbose) or look for actual valid
* references (complex but cleanest output).
* Looking for the 2nd character gives us a middle ground.
* The `#` is for (decimal and hexadecimal) numeric references, the letters
* are for the named references.
*
* @param {string} value
* Value to encode.
* @returns {string}
* Encoded value.
*/
function encodeJsx(value) {
return value.replace(/&(?=[#a-z])/gi, '&amp;')
}
/**
* @param {string} $0
* @returns {string}
*/
function replaceJsxChar($0) {
return $0 === '<'
? '&lt;'
: $0 === '>'
? '&gt;'
: $0 === '{'
? '&#123;'
: '&#125;'
}