| 1 | 'use strict';
|
|---|
| 2 |
|
|---|
| 3 | Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|---|
| 4 |
|
|---|
| 5 | const escape = require('./escape.js');
|
|---|
| 6 | const attempt = require('../function/attempt.js');
|
|---|
| 7 | const defaults = require('../object/defaults.js');
|
|---|
| 8 | const toString = require('../util/toString.js');
|
|---|
| 9 |
|
|---|
| 10 | const esTemplateRegExp = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
|
|---|
| 11 | const unEscapedRegExp = /['\n\r\u2028\u2029\\]/g;
|
|---|
| 12 | const noMatchExp = /($^)/;
|
|---|
| 13 | const escapeMap = new Map([
|
|---|
| 14 | ['\\', '\\'],
|
|---|
| 15 | ["'", "'"],
|
|---|
| 16 | ['\n', 'n'],
|
|---|
| 17 | ['\r', 'r'],
|
|---|
| 18 | ['\u2028', 'u2028'],
|
|---|
| 19 | ['\u2029', 'u2029'],
|
|---|
| 20 | ]);
|
|---|
| 21 | function escapeString(match) {
|
|---|
| 22 | return `\\${escapeMap.get(match)}`;
|
|---|
| 23 | }
|
|---|
| 24 | const defaultInterpolateRegExp = /<%=([\s\S]+?)%>/g;
|
|---|
| 25 | const templateSettings = {
|
|---|
| 26 | escape: /<%-([\s\S]+?)%>/g,
|
|---|
| 27 | evaluate: /<%([\s\S]+?)%>/g,
|
|---|
| 28 | interpolate: defaultInterpolateRegExp,
|
|---|
| 29 | variable: '',
|
|---|
| 30 | imports: {
|
|---|
| 31 | _: {
|
|---|
| 32 | escape: escape.escape,
|
|---|
| 33 | template,
|
|---|
| 34 | },
|
|---|
| 35 | },
|
|---|
| 36 | };
|
|---|
| 37 | function template(string, options, guard) {
|
|---|
| 38 | string = toString.toString(string);
|
|---|
| 39 | if (guard) {
|
|---|
| 40 | options = templateSettings;
|
|---|
| 41 | }
|
|---|
| 42 | options = defaults.defaults({ ...options }, templateSettings);
|
|---|
| 43 | const delimitersRegExp = new RegExp([
|
|---|
| 44 | options.escape?.source ?? noMatchExp.source,
|
|---|
| 45 | options.interpolate?.source ?? noMatchExp.source,
|
|---|
| 46 | options.interpolate === defaultInterpolateRegExp ? esTemplateRegExp.source : noMatchExp.source,
|
|---|
| 47 | options.evaluate?.source ?? noMatchExp.source,
|
|---|
| 48 | '$',
|
|---|
| 49 | ].join('|'), 'g');
|
|---|
| 50 | let lastIndex = 0;
|
|---|
| 51 | let isEvaluated = false;
|
|---|
| 52 | let source = `__p += ''`;
|
|---|
| 53 | for (const match of string.matchAll(delimitersRegExp)) {
|
|---|
| 54 | const [fullMatch, escapeValue, interpolateValue, esTemplateValue, evaluateValue] = match;
|
|---|
| 55 | const { index } = match;
|
|---|
| 56 | source += ` + '${string.slice(lastIndex, index).replace(unEscapedRegExp, escapeString)}'`;
|
|---|
| 57 | if (escapeValue) {
|
|---|
| 58 | source += ` + _.escape(${escapeValue})`;
|
|---|
| 59 | }
|
|---|
| 60 | if (interpolateValue) {
|
|---|
| 61 | source += ` + ((${interpolateValue}) == null ? '' : ${interpolateValue})`;
|
|---|
| 62 | }
|
|---|
| 63 | else if (esTemplateValue) {
|
|---|
| 64 | source += ` + ((${esTemplateValue}) == null ? '' : ${esTemplateValue})`;
|
|---|
| 65 | }
|
|---|
| 66 | if (evaluateValue) {
|
|---|
| 67 | source += `;\n${evaluateValue};\n __p += ''`;
|
|---|
| 68 | isEvaluated = true;
|
|---|
| 69 | }
|
|---|
| 70 | lastIndex = index + fullMatch.length;
|
|---|
| 71 | }
|
|---|
| 72 | const imports = defaults.defaults({ ...options.imports }, templateSettings.imports);
|
|---|
| 73 | const importsKeys = Object.keys(imports);
|
|---|
| 74 | const importValues = Object.values(imports);
|
|---|
| 75 | const sourceURL = `//# sourceURL=${options.sourceURL ? String(options.sourceURL).replace(/[\r\n]/g, ' ') : `es-toolkit.templateSource[${Date.now()}]`}\n`;
|
|---|
| 76 | const compiledFunction = `function(${options.variable || 'obj'}) {
|
|---|
| 77 | let __p = '';
|
|---|
| 78 | ${options.variable ? '' : 'if (obj == null) { obj = {}; }'}
|
|---|
| 79 | ${isEvaluated ? `function print() { __p += Array.prototype.join.call(arguments, ''); }` : ''}
|
|---|
| 80 | ${options.variable ? source : `with(obj) {\n${source}\n}`}
|
|---|
| 81 | return __p;
|
|---|
| 82 | }`;
|
|---|
| 83 | const result = attempt.attempt(() => new Function(...importsKeys, `${sourceURL}return ${compiledFunction}`)(...importValues));
|
|---|
| 84 | result.source = compiledFunction;
|
|---|
| 85 | if (result instanceof Error) {
|
|---|
| 86 | throw result;
|
|---|
| 87 | }
|
|---|
| 88 | return result;
|
|---|
| 89 | }
|
|---|
| 90 |
|
|---|
| 91 | exports.template = template;
|
|---|
| 92 | exports.templateSettings = templateSettings;
|
|---|