interpolation is complete (current state)
parent
f12afb753a
commit
0bc3d52fac
|
@ -10,6 +10,7 @@
|
|||
"dependencies": {
|
||||
"hast-util-from-html": "^2.0.1",
|
||||
"hast-util-to-html": "^9.0.0",
|
||||
"unist-util-parents": "^3.0.0",
|
||||
"unist-util-visit-parents": "^6.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -4899,6 +4900,18 @@
|
|||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/unist-util-parents": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unist-util-parents/-/unist-util-parents-3.0.0.tgz",
|
||||
"integrity": "sha512-3DVSfp+MkJhcJbGn/W7aOlZYVpsMQQ054cpfbPHZAqYPu/lvu5rCdzjuIt4eEMriLkCWLcnJjax97Awm1Bkhtg==",
|
||||
"dependencies": {
|
||||
"@types/unist": "^3.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/unist-util-position": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
|
||||
|
@ -8768,6 +8781,14 @@
|
|||
"@types/unist": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"unist-util-parents": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unist-util-parents/-/unist-util-parents-3.0.0.tgz",
|
||||
"integrity": "sha512-3DVSfp+MkJhcJbGn/W7aOlZYVpsMQQ054cpfbPHZAqYPu/lvu5rCdzjuIt4eEMriLkCWLcnJjax97Awm1Bkhtg==",
|
||||
"requires": {
|
||||
"@types/unist": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"unist-util-position": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
"dependencies": {
|
||||
"hast-util-from-html": "^2.0.1",
|
||||
"hast-util-to-html": "^9.0.0",
|
||||
"unist-util-parents": "^3.0.0",
|
||||
"unist-util-visit-parents": "^6.0.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,50 @@
|
|||
import { visitParents } from 'unist-util-visit-parents';
|
||||
import { createContext, runInContext } from 'vm';
|
||||
|
||||
export function interpolate(node, rootData, options = {}) {
|
||||
if (!node.data) {
|
||||
node.data = {};
|
||||
export function interpolateTree(tree, data, mask = {}, options = {}) {
|
||||
tree.data = tree.data || {};
|
||||
|
||||
if (data) {
|
||||
tree.data.interp = data;
|
||||
}
|
||||
|
||||
node.data.interp = rootData || {};
|
||||
visitParents(node, interpolateNode);
|
||||
const opt = Object.assign({
|
||||
rootNodeOnly: false,
|
||||
}, options);
|
||||
|
||||
return node;
|
||||
|
||||
visitParents(tree, (node, ancestors) => {
|
||||
|
||||
if (opt.rootNodeOnly && node !== tree) {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = getMaskedData(node, ancestors);
|
||||
|
||||
if (node.properties && typeof node.properties === 'object') {
|
||||
for (const key in node.properties) {
|
||||
if (typeof node.properties[key] === 'string') {
|
||||
node.properties[key] = interpolateString(
|
||||
node.properties[key],
|
||||
data
|
||||
);
|
||||
} else if (Array.isArray(node.properties[key])) {
|
||||
node.properties[key] = node.properties[key].map(
|
||||
(value) => interpolateString(value, data)
|
||||
);
|
||||
}
|
||||
else {
|
||||
node.properties[key] = '' + node.properties[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type === 'text' && node.value) {
|
||||
node.value = interpolateString(node.value, data);
|
||||
}
|
||||
})
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
function getMaskedData(node, ancestors, mask = {}) {
|
||||
|
@ -23,32 +58,8 @@ function getMaskedData(node, ancestors, mask = {}) {
|
|||
return foo;
|
||||
}
|
||||
|
||||
function interpolateNode(node, ancestors) {
|
||||
const data = getMaskedData(node, ancestors);
|
||||
|
||||
if (node.properties && typeof node.properties === 'object') {
|
||||
for (const key in node.properties) {
|
||||
if (typeof node.properties[key] === 'string') {
|
||||
node.properties[key] = interpolateString(
|
||||
node.properties[key],
|
||||
data
|
||||
);
|
||||
} else if (Array.isArray(node.properties[key])) {
|
||||
node.properties[key] = node.properties[key].map(
|
||||
(value) => interpolateString(value, data)
|
||||
);
|
||||
}
|
||||
else {
|
||||
node.properties[key] = '' + node.properties[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type === 'text' && node.value) {
|
||||
node.value = interpolateString(node.value, data);
|
||||
}
|
||||
|
||||
return node;
|
||||
function interpolateNode(node, data, mask) {
|
||||
return interpolateTree(node, data, mask, { rootNodeOnly: true });
|
||||
}
|
||||
|
||||
|
||||
|
@ -58,19 +69,6 @@ function interpolateString(str, data) {
|
|||
const interpolatedStr = runInContext(`\`${str}\``, context);
|
||||
return interpolatedStr;
|
||||
}
|
||||
/*
|
||||
function interpolateString(str, data) {
|
||||
const context = createContext({ ...data, ...global });
|
||||
|
||||
try {
|
||||
const interpolatedStr = runInContext(`\`${str}\``, context);
|
||||
return interpolatedStr;
|
||||
} catch (e) {
|
||||
console.error('Error interpolating string:', e);
|
||||
return str;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
export const __testExports = {
|
||||
getMaskedData,
|
||||
|
@ -78,4 +76,4 @@ export const __testExports = {
|
|||
interpolateString,
|
||||
}
|
||||
|
||||
export default interpolate;
|
||||
export default interpolateTree;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import interpolate, { __testExports } from '../src/interpolate.mjs';
|
||||
import interpolateTree, { __testExports } from '../src/interpolate.mjs';
|
||||
import htmlToAst from '../src/html-to-ast.mjs';
|
||||
import astToHtml from '../src/ast-to-html.mjs';
|
||||
|
||||
describe("interpolate()", () => {
|
||||
describe("interpolateTree()", () => {
|
||||
|
||||
it("should import", () => {
|
||||
expect(interpolate).toBeDefined();
|
||||
expect(interpolateTree).toBeDefined();
|
||||
});
|
||||
|
||||
it("should handle nodes without properties", () => {
|
||||
|
@ -15,7 +15,7 @@ describe("interpolate()", () => {
|
|||
data: {},
|
||||
};
|
||||
const data = {};
|
||||
expect(() => interpolate(node, data)).not.toThrow();
|
||||
expect(() => interpolateTree(node, data)).not.toThrow();
|
||||
});
|
||||
|
||||
it("should handle nodes without data", () => {
|
||||
|
@ -24,7 +24,7 @@ describe("interpolate()", () => {
|
|||
value: 'Test',
|
||||
data: {},
|
||||
};
|
||||
expect(() => interpolate(node)).not.toThrow();
|
||||
expect(() => interpolateTree(node)).not.toThrow();
|
||||
});
|
||||
|
||||
it("should handle nodes with array properties", () => {
|
||||
|
@ -35,7 +35,7 @@ describe("interpolate()", () => {
|
|||
data: {},
|
||||
};
|
||||
const data = { value: 'interpolated' };
|
||||
const interpolated = interpolate(node, data);
|
||||
const interpolated = interpolateTree(node, data);
|
||||
expect(interpolated.properties.test[0]).toEqual('interpolated');
|
||||
});
|
||||
|
||||
|
@ -46,7 +46,7 @@ describe("interpolate()", () => {
|
|||
},
|
||||
};
|
||||
const data = { value: 'interpolated' };
|
||||
const interpolated = interpolate(node, data);
|
||||
const interpolated = interpolateTree(node, data);
|
||||
expect(interpolated.properties.test).toEqual('interpolated');
|
||||
});
|
||||
|
||||
|
@ -73,20 +73,43 @@ describe("interpolate()", () => {
|
|||
},
|
||||
},
|
||||
};
|
||||
const ancestors = [];
|
||||
const interpolatedNode = __testExports.interpolateNode(node, ancestors);
|
||||
const interpolatedNode = __testExports.interpolateNode(node);
|
||||
expect(interpolatedNode.properties.test).toEqual('interpolated');
|
||||
});
|
||||
|
||||
it("should interpolate node properties that are not strings or arrays", () => {
|
||||
it("should abandon all its children with disdain", () => {
|
||||
const node = {
|
||||
properties: {
|
||||
prop: 45, // Corrected property name
|
||||
test: '${value}',
|
||||
},
|
||||
data: {
|
||||
interp: {
|
||||
value: 'interpolated',
|
||||
},
|
||||
},
|
||||
children: [{
|
||||
properties: {
|
||||
test: '${piggly}',
|
||||
},
|
||||
data: {
|
||||
interp: {
|
||||
value: 'wiggly',
|
||||
},
|
||||
},
|
||||
}],
|
||||
};
|
||||
const interpolatedNode = __testExports.interpolateNode(node);
|
||||
expect(interpolatedNode.children[0].properties.test).toEqual('${piggly}');
|
||||
});
|
||||
|
||||
it("should handle node properties that are not strings or arrays", () => {
|
||||
const node = {
|
||||
properties: {
|
||||
prop: 45,
|
||||
},
|
||||
data: {},
|
||||
};
|
||||
const ancestors = [];
|
||||
const interpolatedNode = __testExports.interpolateNode(node, ancestors);
|
||||
const interpolatedNode = __testExports.interpolateNode(node);
|
||||
expect(interpolatedNode.properties.prop).toEqual('45');
|
||||
});
|
||||
});
|
||||
|
@ -106,12 +129,6 @@ describe("interpolate()", () => {
|
|||
});
|
||||
|
||||
});
|
||||
});
|
||||
describe("interpolate()", () => {
|
||||
|
||||
it("should import", () => {
|
||||
expect(interpolate).toBeDefined();
|
||||
})
|
||||
|
||||
it("should interpolate a single node", () => {
|
||||
const uninterpolated = '<div class="${classname}"></div>';
|
||||
|
@ -119,7 +136,7 @@ describe("interpolate()", () => {
|
|||
|
||||
const data = { classname: "foo" };
|
||||
const ast = htmlToAst(uninterpolated);
|
||||
const interpolated = interpolate(ast, data);
|
||||
const interpolated = interpolateTree(ast, data);
|
||||
const rendered = astToHtml(interpolated);
|
||||
|
||||
expect(rendered).toEqual(expected);
|
||||
|
@ -155,7 +172,7 @@ describe("interpolate()", () => {
|
|||
},
|
||||
};
|
||||
const ast = htmlToAst(uninterpolated);
|
||||
const interpolated = interpolate(ast, data);
|
||||
const interpolated = interpolateTree(ast, data);
|
||||
const rendered = astToHtml(interpolated);
|
||||
|
||||
expect(rendered).toEqual(expected);
|
||||
|
@ -184,7 +201,7 @@ describe("interpolate()", () => {
|
|||
square: (num) => Math.pow(num, 2),
|
||||
};
|
||||
const ast = htmlToAst(uninterpolated);
|
||||
const interpolated = interpolate(ast, data);
|
||||
const interpolated = interpolateTree(ast, data);
|
||||
const rendered = astToHtml(interpolated);
|
||||
|
||||
expect(rendered).toEqual(expected);
|
||||
|
|
Loading…
Reference in New Issue