\n'
31 | + '';
32 |
33 | const processor = unified()
34 | .use(markdown)
35 | .use(remark2rehype)
36 | .use(resly({ code }))
37 | .use(html);
38 |
39 | const readme = fs.createReadStream(path.resolve(__dirname, '../../', 'README.md'));
40 | readme.pipe(stream(processor)).pipe(process.stdout);
41 |
--------------------------------------------------------------------------------
/examples/hast/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "htlengine-example-hast",
3 | "private": true,
4 | "version": "1.0.0",
5 | "description": "Example to use htlengine with unified / hast",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "node index.js"
9 | },
10 | "author": "",
11 | "license": "Apache-2.0",
12 | "dependencies": {
13 | "@adobe/htlengine": "file:../../",
14 | "remark-parse": "^6.0.3",
15 | "remark-rehype": "^4.0.1",
16 | "unified": "^7.1.0",
17 | "unified-stream": "^1.0.6"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/jsdom/helper.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = class Helper {
13 | async use(globals) {
14 | const document = globals.document;
15 | return {
16 | get title() {
17 | return document.querySelector('h1').innerHTML;
18 | },
19 |
20 | get headings() {
21 | // HTL iterator doesn't support NodeLists correctly yet.
22 | const ret = [];
23 | for(const h of document.querySelectorAll('h1,h2,h3').values()) {
24 | ret.push(h);
25 | }
26 | return ret;
27 | },
28 | };
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/examples/jsdom/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | /* eslint-disable */
13 |
14 | const { JSDOM } = require('jsdom');
15 | const { Compiler, Runtime } = require('@adobe/htlengine');
16 |
17 | const code = ''
18 | + ''
19 | + ''
20 | + '${doc.title}\n'
21 | + '\n'
22 | + '
'
31 | + 'This example shows how t use JSDOM with the HTL Engine.'
32 | + '
Install
'
33 | + 'foo bar...'
34 | + '
Run
'
35 | + 'npm test'
36 | + '
Development
'
37 | + 'contributions welcome';
38 |
39 | async function run() {
40 | // setup the HTL compiler
41 | const compiler = new Compiler().withRuntimeVar('document');
42 |
43 | const template = await compiler.compileToFunction(code, __dirname, require);
44 |
45 | // generate the input data using JSDOM
46 | const document = new JSDOM(html).window.document;
47 |
48 | // create a dom factory, providing a document implementation
49 | const domFactory = new Runtime.VDOMFactory(document.implementation);
50 |
51 | // create the HTL runtime
52 | const runtime = new Runtime()
53 | .withDomFactory(domFactory)
54 | .setGlobal({
55 | document
56 | });
57 |
58 | // finally, execute the template. the result is a Document.
59 | const result = await template(runtime);
60 | return `${result.documentElement.outerHTML}`;
61 | }
62 |
63 | run().then(console.log).catch(console.error);
64 |
--------------------------------------------------------------------------------
/examples/jsdom/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "htlengine-example-jsom",
3 | "private": true,
4 | "version": "1.0.0",
5 | "description": "Example to use htlengine with JSDOM",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "node index.js"
9 | },
10 | "author": "",
11 | "license": "Apache-2.0",
12 | "dependencies": {
13 | "@adobe/htlengine": "file:../../",
14 | "jsdom": "^15.2.1"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@adobe/htlengine",
3 | "version": "6.4.34",
4 | "description": "Javascript Based HTL (Sightly) parser",
5 | "main": "src/index.js",
6 | "license": "Apache-2.0",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/adobe/htlengine.git"
10 | },
11 | "engines": {
12 | "node": ">=14"
13 | },
14 | "scripts": {
15 | "build": "npm run build:compile && npm run build:railroad",
16 | "build:compile": "nearleyc ./src/parser/grammar/sightly.ne --out ./src/parser/generated/grammar.js",
17 | "build:railroad": "nearley-railroad ./src/parser/grammar/sightly.ne --out ./src/parser/generated/grammar.html",
18 | "semantic-release": "semantic-release",
19 | "semantic-release-dry": "semantic-release --dry-run --branches $CI_BRANCH",
20 | "start": "node src/run.js",
21 | "test": "c8 mocha",
22 | "lint": "eslint .",
23 | "prepare": "husky"
24 | },
25 | "dependencies": {
26 | "dompurify": "3.2.6",
27 | "fs-extra": "11.3.0",
28 | "he": "1.2.0",
29 | "jsdom": "26.1.0",
30 | "moment": "2.30.1",
31 | "moo": "0.5.2",
32 | "nearley": "2.20.1",
33 | "node-esapi": "0.0.1",
34 | "numeral": "2.0.6",
35 | "rehype-parse": "7.0.1",
36 | "source-map": "0.7.4",
37 | "unified": "9.2.2",
38 | "unist-util-inspect": "6.0.1",
39 | "xregexp": "5.1.2"
40 | },
41 | "devDependencies": {
42 | "@semantic-release/changelog": "6.0.3",
43 | "@semantic-release/git": "10.0.1",
44 | "c8": "10.1.3",
45 | "eslint": "8.57.1",
46 | "eslint-config-airbnb-base": "15.0.0",
47 | "eslint-plugin-header": "3.1.1",
48 | "eslint-plugin-import": "2.31.0",
49 | "husky": "9.1.7",
50 | "lint-staged": "16.1.0",
51 | "mocha": "11.6.0",
52 | "mocha-junit-reporter": "2.2.1",
53 | "rehype-stringify": "8.0.0",
54 | "remark-parse": "9.0.0",
55 | "remark-rehype": "8.1.0",
56 | "semantic-release": "24.2.5"
57 | },
58 | "lint-staged": {
59 | "*.js": "eslint"
60 | },
61 | "bugs": {
62 | "url": "https://github.com/adobe/htlengine/issues"
63 | },
64 | "homepage": "https://github.com/adobe/htlengine#readme"
65 | }
66 |
--------------------------------------------------------------------------------
/src/cli.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | // declared dependencies
14 | const fse = require('fs-extra');
15 | // local modules
16 | const engine = require('./main');
17 |
18 | (async () => {
19 | const filename = process.argv[2];
20 | const template = await fse.readFile(filename, 'utf-8');
21 |
22 | const resource = {
23 | world: 'Earth',
24 | properties: {
25 | title: 'Hello, world.',
26 | fruits: ['Apple', 'Banana', 'Orange'],
27 | comma: ', ',
28 | },
29 | nav: {
30 | foo: 'This is foo. ',
31 | },
32 | test: 'This is a test',
33 | qttMin: 4,
34 | qttMax: 4,
35 | expression: 'this is an expression.',
36 | it: {
37 | html: 'foo barty!',
38 | title: 'Hello, world!',
39 | children: [
40 | '
A
',
41 | '
B
',
42 | ],
43 | },
44 | };
45 |
46 | engine(resource, template).then((ret) => {
47 | // eslint-disable-next-line no-console
48 | console.log(ret.body);
49 | });
50 | })();
51 |
--------------------------------------------------------------------------------
/src/compiler/ExternalTemplateLoader.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | const path = require('path');
13 | const fse = require('fs-extra');
14 |
15 | /**
16 | * Creates a template loader that compiles the templates and returns their exec function.
17 | */
18 | module.exports = function createLoader(opts) {
19 | const {
20 | compiler,
21 | outputDirectory,
22 | } = opts;
23 |
24 | /**
25 | * Load the template.
26 | * @param {string} templatePath template path
27 | * @param {string} scriptId the script id
28 | * @returns {Promise<>} the template source and resolved path
29 | */
30 | async function load(templatePath, scriptId) {
31 | const comp = await compiler.createTemplateCompiler(templatePath, outputDirectory, scriptId);
32 | const filename = `${path.basename(templatePath)}.js`;
33 | const outfile = path.resolve(outputDirectory, filename);
34 | const source = await fse.readFile(templatePath, 'utf-8');
35 | const file = await comp.compileToFile(source, outfile, compiler.dir);
36 | return {
37 | path: file,
38 | code: `require(${JSON.stringify(file)})($);`,
39 | };
40 | }
41 |
42 | return load;
43 | };
44 |
--------------------------------------------------------------------------------
/src/compiler/JSCodeTemplate.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /* eslint-disable */
14 |
15 | module.exports = function main($) {
16 | // RUNTIME_GLOBALS
17 |
18 | // TEMPLATES
19 |
20 | return $.run(function* () {
21 | // CODE
22 | });
23 | };
24 |
--------------------------------------------------------------------------------
/src/compiler/JSPureTemplate.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /* eslint-disable */
14 |
15 | module.exports = function main($) {
16 | // RUNTIME_GLOBALS
17 |
18 | // TEMPLATES
19 | };
20 |
--------------------------------------------------------------------------------
/src/compiler/JSRuntimeTemplate.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /* eslint-disable */
14 | const { Runtime } = require('MOD_HTLENGINE');
15 |
16 | function run($) {
17 | // RUNTIME_GLOBALS
18 |
19 | // TEMPLATES
20 |
21 | return $.run(function* () {
22 | // CODE
23 | });
24 | }
25 |
26 | module.exports.main = async function main(resource) {
27 | const runtime = new Runtime();
28 | runtime.setGlobal(resource);
29 | return await run(runtime);
30 | };
31 |
--------------------------------------------------------------------------------
/src/compiler/ScriptResolver.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | const path = require('path');
13 | const fse = require('fs-extra');
14 |
15 | /**
16 | * Creates a script resolver.
17 | * @param {string[]} roots Root directories for resolution.
18 | */
19 | module.exports = function createResolver(roots) {
20 | if (!Array.isArray(roots)) {
21 | // eslint-disable-next-line no-param-reassign
22 | roots = [roots];
23 | }
24 |
25 | /**
26 | * Resolves the script against the given roots.
27 | * @param {string} baseDir additional root
28 | * @param {string} uri script uri
29 | * @returns {Promise}
30 | */
31 | async function resolve(baseDir, uri) {
32 | let bases = [baseDir, ...roots];
33 |
34 | // if uri starts with '.' or '..', only consider specified bases.
35 | // otherwise also consider apps and libs.
36 | if (!uri.startsWith('./') && !uri.startsWith('../')) {
37 | bases = bases.reduce((prev, root) => {
38 | prev.push(root);
39 | prev.push(path.resolve(root, 'apps'));
40 | prev.push(path.resolve(root, 'libs'));
41 | return prev;
42 | }, []);
43 | }
44 |
45 | // eslint-disable-next-line no-restricted-syntax
46 | for (const base of bases) {
47 | const scriptPath = path.resolve(base, uri);
48 | // eslint-disable-next-line no-await-in-loop
49 | if (await fse.pathExists(scriptPath)) {
50 | return scriptPath;
51 | }
52 | }
53 | throw Error(`Unable to resolve script: ${uri}. Search Path: ${bases}`);
54 | }
55 |
56 | return resolve;
57 | };
58 |
--------------------------------------------------------------------------------
/src/compiler/TemplateLoader.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | const fse = require('fs-extra');
13 |
14 | /**
15 | * Creates an template loader.
16 | */
17 | module.exports = function createLoader() {
18 | /**
19 | * @param {string} filePath Template path
20 | * @returns {Promise<>} the template source and path
21 | */
22 | async function load(filePath) {
23 | return {
24 | data: await fse.readFile(filePath, 'utf-8'),
25 | path: filePath,
26 | };
27 | }
28 |
29 | return load;
30 | };
31 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Compiler = require('./compiler/Compiler.js');
14 | const createTemplateLoader = require('./compiler/TemplateLoader.js');
15 | const createScriptResolver = require('./compiler/ScriptResolver.js');
16 | const Runtime = require('./runtime/Runtime.js');
17 | const resly = require('./runtime/resly.js');
18 |
19 | module.exports = Object.freeze({
20 | Compiler,
21 | Runtime,
22 | createTemplateLoader,
23 | createScriptResolver,
24 | resly,
25 | });
26 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const { Compiler, Runtime } = require('./index.js');
14 |
15 | /**
16 | * Simple engine that compiles the given template and executes it.
17 | * @param {*} resource the global object to pass into the script
18 | * @param {string} template the HTL script
19 | * @returns A promise that resolves to the evaluated code.
20 | */
21 | module.exports = async function main(resource, template) {
22 | // setup the HTL compiler
23 | const compiler = new Compiler().withRuntimeVar(Object.keys(resource));
24 |
25 | // compile the script to a executable template function
26 | const fn = await compiler.compileToFunction(template);
27 |
28 | // create the HTL runtime
29 | const runtime = new Runtime()
30 | .setGlobal(resource);
31 |
32 | // finally, execute the template function and return the result
33 | return fn(runtime);
34 | };
35 |
--------------------------------------------------------------------------------
/src/parser/commands/AddAttribute.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 | const MarkupContext = require('../html/MarkupContext');
15 |
16 | module.exports = class AddAttribute extends Command {
17 | constructor(name, value, context = MarkupContext.ATTRIBUTE) {
18 | super();
19 | this._name = name;
20 | this._value = value;
21 | this._context = context;
22 | }
23 |
24 | get name() {
25 | return this._name;
26 | }
27 |
28 | get value() {
29 | return this._value;
30 | }
31 |
32 | get context() {
33 | return this._context;
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/src/parser/commands/Command.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /**
14 | * A {@code Command} represents the type of instruction a certain HTL expression or block element
15 | * should execute.
16 | * Commands are immutable and can only be processed through a {@link CommandVisitor}.
17 | */
18 | module.exports = class Command {
19 | constructor(location) {
20 | this._location = location;
21 | }
22 |
23 | /**
24 | * Accept a visitor.
25 | *
26 | * @param {CommandVisitor} visitor the visitor that will process this command
27 | */
28 | accept(visitor) {
29 | visitor.visit(this);
30 | }
31 |
32 | get location() {
33 | return this._location;
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/src/parser/commands/CommandStream.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const FunctionBlock = require('./FunctionBlock');
14 | const OutText = require('./OutText');
15 |
16 | module.exports = class CommandStream {
17 | constructor() {
18 | this._commands = [];
19 | this._warnings = [];
20 | this._wasText = false;
21 | this._ignore = 0;
22 | }
23 |
24 | write(command, force) {
25 | if (this._ignore && !force) {
26 | return;
27 | }
28 | const isText = command instanceof OutText;
29 | if (isText) {
30 | if (this._wasText) {
31 | this._commands[this._commands.length - 1].append(command.text);
32 | return;
33 | }
34 | }
35 | this._wasText = isText;
36 | this._commands.push(command);
37 | }
38 |
39 | warn(message, code) {
40 | this._warnings.push({
41 | message,
42 | code,
43 | });
44 | }
45 |
46 | // eslint-disable-next-line class-methods-use-this
47 | close() {
48 | }
49 |
50 | get commands() {
51 | return this._commands;
52 | }
53 |
54 | beginFunction(expression, options) {
55 | this.write(new FunctionBlock.Start(expression, options));
56 | }
57 |
58 | endFunction() {
59 | this.write(FunctionBlock.END);
60 | }
61 |
62 | beginIgnore() {
63 | this._ignore += 1;
64 | this._wasText = false;
65 | }
66 |
67 | endIgnore() {
68 | this._ignore -= 1;
69 | if (this._ignore < 0) {
70 | throw Error('stream ignore block mismatch');
71 | }
72 | }
73 | };
74 |
--------------------------------------------------------------------------------
/src/parser/commands/Comment.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 |
15 | module.exports = class Comment extends Command {
16 | constructor(text, location) {
17 | super(location);
18 | this._text = text;
19 | }
20 |
21 | get text() {
22 | return this._text;
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/src/parser/commands/Conditional.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | // eslint-disable-next-line max-classes-per-file
14 | const Command = require('./Command');
15 |
16 | module.exports = {
17 |
18 | Start: class Start extends Command {
19 | constructor(expression, negate, location) {
20 | super(location);
21 | this._expression = expression;
22 | this._negate = negate;
23 | }
24 |
25 | get expression() {
26 | return this._expression;
27 | }
28 |
29 | get negate() {
30 | return this._negate;
31 | }
32 | },
33 |
34 | End: class End extends Command {
35 |
36 | },
37 |
38 | };
39 |
40 | module.exports.END = new module.exports.End();
41 |
--------------------------------------------------------------------------------
/src/parser/commands/CreateElement.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 |
15 | module.exports = class CreateElement extends Command {
16 | constructor(name, isEmpty, isVoid) {
17 | super();
18 | this._name = name;
19 | this._isEmpty = isEmpty;
20 | this._isVoid = isVoid;
21 | }
22 |
23 | get name() {
24 | return this._name;
25 | }
26 |
27 | get isEmpty() {
28 | return this._isEmpty;
29 | }
30 |
31 | get isVoid() {
32 | return this._isVoid;
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/src/parser/commands/Doctype.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 |
15 | module.exports = class Doctype extends Command {
16 | constructor(name, publicId, systemId, location) {
17 | super(location);
18 | this._name = name;
19 | this._publicId = publicId;
20 | this._systemId = systemId;
21 | }
22 |
23 | get name() {
24 | return this._name;
25 | }
26 |
27 | get publicId() {
28 | return this._publicId;
29 | }
30 |
31 | get systemId() {
32 | return this._systemId;
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/src/parser/commands/ExternalCode.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 |
15 | module.exports = class ExternalCode extends Command {
16 | constructor(code, location) {
17 | super(location);
18 | this._code = code;
19 | }
20 |
21 | get code() {
22 | return this._code;
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/src/parser/commands/FileReference.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 |
15 | module.exports = class FileReference extends Command {
16 | constructor(name, filename, args) {
17 | super();
18 | this._name = name;
19 | this._filename = filename;
20 | this._args = args || [];
21 | this._id = null;
22 | }
23 |
24 | get name() {
25 | return this._name;
26 | }
27 |
28 | get filename() {
29 | return this._filename;
30 | }
31 |
32 | set id(value) {
33 | this._id = value;
34 | }
35 |
36 | get id() {
37 | return this._id;
38 | }
39 |
40 | get args() {
41 | return this._args;
42 | }
43 |
44 | isTemplate() {
45 | return this._filename.endsWith('.htl') || this._filename.endsWith('.html');
46 | }
47 | };
48 |
--------------------------------------------------------------------------------
/src/parser/commands/FunctionBlock.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Deloitte Digital. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | // eslint-disable-next-line max-classes-per-file
14 | const Command = require('./Command');
15 |
16 | class Start extends Command {
17 | constructor(expression, options) {
18 | super();
19 | this._expression = expression;
20 | this._options = options;
21 | this._id = null;
22 | }
23 |
24 | set id(value) {
25 | this._id = value;
26 | }
27 |
28 | get id() {
29 | return this._id;
30 | }
31 |
32 | get expression() {
33 | return this._expression;
34 | }
35 |
36 | get options() {
37 | return this._options;
38 | }
39 |
40 | get args() {
41 | return Object.keys(this._options);
42 | }
43 | }
44 |
45 | class End extends Command {}
46 |
47 | const END = new End();
48 |
49 | module.exports = {
50 | Start,
51 | End,
52 | END,
53 | };
54 |
--------------------------------------------------------------------------------
/src/parser/commands/FunctionCall.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 |
15 | module.exports = class FunctionCall extends Command {
16 | constructor(functionName, args, location) {
17 | super(location);
18 | this._functionName = functionName;
19 | this._args = args;
20 | }
21 |
22 | get functionName() {
23 | return this._functionName;
24 | }
25 |
26 | get args() {
27 | return this._args;
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/src/parser/commands/Loop.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | // eslint-disable-next-line max-classes-per-file
14 | const Command = require('./Command');
15 |
16 | module.exports = {
17 |
18 | Init: class Init extends Command {
19 | constructor(variableName, expression, options = {}) {
20 | super();
21 | this._variableName = variableName;
22 | this._expression = expression;
23 | this._options = options;
24 | }
25 |
26 | get variableName() {
27 | return this._variableName;
28 | }
29 |
30 | get expression() {
31 | return this._expression;
32 | }
33 |
34 | get options() {
35 | return this._options;
36 | }
37 | },
38 |
39 | Start: class Start extends Command {
40 | constructor(listVariable, itemVariable, indexVariable) {
41 | super();
42 | this._listVariable = listVariable;
43 | this._itemVariable = itemVariable;
44 | this._indexVariable = indexVariable;
45 | }
46 |
47 | get listVariable() {
48 | return this._listVariable;
49 | }
50 |
51 | get itemVariable() {
52 | return this._itemVariable;
53 | }
54 |
55 | get indexVariable() {
56 | return this._indexVariable;
57 | }
58 | },
59 |
60 | End: class End extends Command {
61 |
62 | },
63 |
64 | };
65 |
66 | module.exports.END = new module.exports.End();
67 |
--------------------------------------------------------------------------------
/src/parser/commands/OutText.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 |
15 | module.exports = class OutText extends Command {
16 | constructor(text, location) {
17 | super(location);
18 | this._text = text;
19 | }
20 |
21 | get text() {
22 | return this._text;
23 | }
24 |
25 | append(text) {
26 | this._text += text;
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/src/parser/commands/OutputVariable.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 |
15 | module.exports = class OutputVariable extends Command {
16 | constructor(variableName, location) {
17 | super(location);
18 | this._variableName = variableName;
19 | }
20 |
21 | get variableName() {
22 | return this._variableName;
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/src/parser/commands/PopElement.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 |
15 | module.exports = class PopElement extends Command {
16 | constructor(name, isEmpty, isVoid) {
17 | super();
18 | this._name = name;
19 | this._isEmpty = isEmpty;
20 | this._isVoid = isVoid;
21 | }
22 |
23 | get name() {
24 | return this._name;
25 | }
26 |
27 | get isEmpty() {
28 | return this._isEmpty;
29 | }
30 |
31 | get isVoid() {
32 | return this._isVoid;
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/src/parser/commands/PushElement.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Command = require('./Command');
14 |
15 | module.exports = class PushElement extends Command {
16 | constructor(name, isEmpty, isVoid) {
17 | super();
18 | this._name = name;
19 | this._isEmpty = isEmpty;
20 | this._isVoid = isVoid;
21 | }
22 |
23 | get name() {
24 | return this._name;
25 | }
26 |
27 | get isEmpty() {
28 | return this._isEmpty;
29 | }
30 |
31 | get isVoid() {
32 | return this._isVoid;
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/src/parser/commands/VariableBinding.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | // eslint-disable-next-line max-classes-per-file
14 | const Command = require('./Command');
15 |
16 | module.exports = {
17 |
18 | Start: class Start extends Command {
19 | constructor(variableName, expression) {
20 | super();
21 | this._variableName = variableName;
22 | this._expression = expression;
23 | }
24 |
25 | get variableName() {
26 | return this._variableName;
27 | }
28 |
29 | get expression() {
30 | return this._expression;
31 | }
32 | },
33 |
34 | End: class End extends Command {
35 |
36 | },
37 |
38 | Global: class Global extends Command {
39 | constructor(variableName, expression) {
40 | super();
41 | this._variableName = variableName.toLowerCase();
42 | this._expression = expression;
43 | }
44 |
45 | get variableName() {
46 | return this._variableName;
47 | }
48 |
49 | get expression() {
50 | return this._expression;
51 | }
52 | },
53 | };
54 |
55 | module.exports.END = new module.exports.End();
56 |
--------------------------------------------------------------------------------
/src/parser/generated/.gitignore:
--------------------------------------------------------------------------------
1 | *.interp
2 | *.tokens
3 |
--------------------------------------------------------------------------------
/src/parser/grammar/lexer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | /* eslint-disable no-template-curly-in-string,no-control-regex */
13 | const moo = require('moo');
14 |
15 | function parseDString(str) {
16 | return JSON.parse(`{"s":${str}}`).s;
17 | }
18 |
19 | function parseSString(str) {
20 | const sb = str.substring(1, str.length - 1)
21 | .replace(/[^\\]"/g, '\\"')
22 | .replace('\\\'', '\'');
23 | return JSON.parse(`{"s":"${sb}"}`).s;
24 | }
25 |
26 | const lexer = moo.states({
27 | main: {
28 | TEXT_PART: { match: /[^$\\\x03]+/, lineBreaks: true },
29 | EXPR_START: { match: /\$\{/, push: 'expr' },
30 | ESC_EXPR: /\\\$/,
31 | DOLLAR: '$',
32 | EOF: /\03/,
33 | },
34 | expr: {
35 | EOF: /\x03/,
36 | COMMENT: //,
37 | EXPR_END: { match: '}', pop: 1 },
38 | DOT: '.',
39 | LBRACKET: '(',
40 | RBRACKET: ')',
41 | AND_OP: '&&',
42 | OR_OP: '||',
43 | NEQ: {
44 | match: '!=',
45 | value: () => '!==',
46 | },
47 | NOT_OP: '!',
48 | COMMA: ',',
49 | ARRAY_START: '[',
50 | ARRAY_END: ']',
51 | OPTION_SEP: '@',
52 | TERNARY_Q_OP: '?',
53 | TERNARY_BRANCHES_OP: ':',
54 | LEQ: '<=',
55 | LT: '<',
56 | GEQ: '>=',
57 | GT: '>',
58 | EQ: {
59 | match: '==',
60 | value: () => '===',
61 | },
62 | ASSIGN: '=',
63 | ID: {
64 | match: /[a-zA-Z_][a-zA-Z0-9_:]*/,
65 | type: moo.keywords({
66 | BOOL_CONSTANT: ['true', 'false'],
67 | IN_OP: 'in',
68 | }),
69 | },
70 | FLOAT: /-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/,
71 | INT: /-?\d+/,
72 | WS: { match: /\s+/, lineBreaks: true },
73 |
74 | S_STRING: {
75 | match: /'(?:\\u[a-fA-F0-9]{4}|\\["'\\btnfr]|[^'\n\\])*'/,
76 | value: parseSString,
77 | },
78 | D_STRING: {
79 | match: /"(?:\\u[a-fA-F0-9]{4,6}|\\["'\\btnfr]|[^"\n\\])*"/,
80 | value: parseDString,
81 | },
82 | },
83 | });
84 |
85 | module.exports = lexer;
86 |
--------------------------------------------------------------------------------
/src/parser/htl/HTLParser.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2021 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const nearley = require('nearley');
14 | const inspect = require('unist-util-inspect');
15 | const grammar = require('../generated/grammar.js');
16 | const Interpolation = require('./nodes/Interpolation');
17 |
18 | module.exports = class HTLParser {
19 | constructor() {
20 | this.debug = false;
21 | }
22 |
23 | /**
24 | * Parses the input and returns an Interpolation.
25 | * @param {string} text Input text
26 | * @return {object} The parsed abstract syntax tree.
27 | */
28 | // eslint-disable-next-line class-methods-use-this
29 | parse(text, { line = 0, column = 0 } = {}) {
30 | // eslint-disable-next-line no-param-reassign
31 | text = text || ''; // avoid null
32 | if (this.debug) {
33 | process.stdout.write(`[${line}:${column}] ${text.substring(0, 40).replace(/\n\r/g, ' ')}\n`);
34 | }
35 | let htl = new Interpolation();
36 | if (text) {
37 | const parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar));
38 | parser.feed(`${text}\x03`);
39 | // eslint-disable-next-line prefer-destructuring
40 | htl = parser.results[0];
41 | }
42 |
43 | if (this.debug) {
44 | process.stdout.write(inspect(htl));
45 | process.stdout.write('\n\n');
46 | }
47 | return htl;
48 | }
49 | };
50 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/ArrayLiteral.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const ExpressionNode = require('./ExpressionNode');
14 |
15 | module.exports = class ArrayLiteral extends ExpressionNode {
16 | /**
17 | * @param {ExpressionNode[]} items Items
18 | */
19 | constructor(items) {
20 | super();
21 | this.type = 'array';
22 | this.children = items || [];
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/Atom.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const ExpressionNode = require('./ExpressionNode');
14 |
15 | module.exports = class Atom extends ExpressionNode {
16 | get text() { // eslint-disable-line class-methods-use-this
17 | throw new TypeError('Abstract method error');
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/BinaryOperation.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const ExpressionNode = require('./ExpressionNode');
14 |
15 | module.exports = class BinaryOperation extends ExpressionNode {
16 | /**
17 | *
18 | * @param {BinaryOperator} operator Operator
19 | * @param {ExpressionNode} leftOperand Left operand expression
20 | * @param {ExpressionNode} rightOperand Right operand expression
21 | */
22 | constructor(operator, leftOperand, rightOperand) {
23 | super();
24 | this.type = 'binary';
25 | Object.defineProperty(this, '_operator', { value: operator, enumerable: false });
26 | this.name = operator.sym;
27 | this.children = [leftOperand, rightOperand];
28 | }
29 |
30 | get operator() {
31 | return this._operator;
32 | }
33 |
34 | get leftOperand() {
35 | return this.children[0];
36 | }
37 |
38 | get rightOperand() {
39 | return this.children[1];
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/BooleanConstant.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Atom = require('./Atom');
14 |
15 | class BooleanConstant extends Atom {
16 | constructor(value) {
17 | super();
18 | this.type = 'bool';
19 | this.value = value;
20 | }
21 |
22 | get text() {
23 | return this.value ? 'true' : 'false';
24 | }
25 | }
26 | BooleanConstant.TRUE = new BooleanConstant(true);
27 | BooleanConstant.FALSE = new BooleanConstant(false);
28 |
29 | module.exports = BooleanConstant;
30 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/Expression.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | module.exports = class Expression {
14 | /**
15 | *
16 | * @param {ExpressionNode} root Root node
17 | * @param {Map} options Options
18 | * @param {String} rawText Raw text
19 | */
20 | constructor(root, options, rawText) {
21 | this.type = 'expression';
22 | this._options = options || {};
23 | this.children = [root];
24 | this._rawText = rawText;
25 | }
26 |
27 | get root() {
28 | return this.children[0];
29 | }
30 |
31 | get options() {
32 | return this._options;
33 | }
34 |
35 | get rawText() {
36 | return this._rawText;
37 | }
38 |
39 | withRawText(rawText) {
40 | return new Expression(this._root, this._options, rawText);
41 | }
42 |
43 | withNode(node) {
44 | return new Expression(node, this._options, null);
45 | }
46 |
47 | containsOption(option) {
48 | return option in this._options;
49 | }
50 |
51 | containsSomeOption(options) {
52 | return options.some((opt) => opt in this._options);
53 | }
54 |
55 | /**
56 | * Removes the given option from this expression.
57 | *
58 | * @param {String} option the option to be removed
59 | * @return the option, or {@code null} if the option doesn't exist
60 | */
61 | removeOption(option) {
62 | const ret = this._options[option];
63 | delete this._options[option];
64 | return ret;
65 | }
66 |
67 | accept(visitor) {
68 | return visitor.visit(this);
69 | }
70 | };
71 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/ExpressionNode.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | module.exports = class ExpressionNode {
14 | constructor() {
15 | this.type = 'node';
16 | }
17 |
18 | withHasParens(p) {
19 | this._hasParens = p;
20 | return this;
21 | }
22 |
23 | get hasParens() {
24 | return this._hasParens;
25 | }
26 |
27 | accept(visitor) {
28 | return visitor.visit(this);
29 | }
30 | };
31 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/Identifier.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Atom = require('./Atom');
14 |
15 | class Identifier extends Atom {
16 | constructor(name) {
17 | super();
18 | this.type = 'identifier';
19 | this.name = name;
20 | }
21 |
22 | get value() {
23 | return this.name;
24 | }
25 |
26 | get text() {
27 | return this._name;
28 | }
29 | }
30 |
31 | Identifier.NULL = new Identifier('null');
32 |
33 | module.exports = Identifier;
34 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/Interpolation.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /**
14 | * A sequence with alternating string fragments and HTL expressions. These result from parsing HTML
15 | * attributes or string nodes.
16 | * For instance "Hello ${World}!" would result in 3 fragments: "Hello ", ${World} and "!"
17 | */
18 | module.exports = class Interpolation {
19 | constructor() {
20 | this.type = 'interpolation';
21 | this.children = [];
22 | this._content = '';
23 | this._isPlainText = true;
24 | }
25 |
26 | addExpression(expression) {
27 | this._isPlainText = false;
28 | this.children.push(expression);
29 | }
30 |
31 | addText(text) {
32 | this.children.push({
33 | type: 'text',
34 | value: text,
35 | });
36 | }
37 |
38 | get fragments() {
39 | return this.children;
40 | }
41 |
42 | get content() {
43 | return this._content;
44 | }
45 |
46 | set content(content) {
47 | this._content = content;
48 | }
49 |
50 | accept(visitor) {
51 | return visitor.visit(this);
52 | }
53 |
54 | getPlainText() {
55 | if (!this._isPlainText) {
56 | return null;
57 | }
58 | let text = '';
59 | for (let i = 0; i < this.children.length; i += 1) {
60 | text += this.children[i].value;
61 | }
62 | return text;
63 | }
64 | };
65 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/MapLiteral.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const ExpressionNode = require('./ExpressionNode');
14 |
15 | module.exports = class MapLiteral extends ExpressionNode {
16 | constructor(map) {
17 | super();
18 | this.type = 'map';
19 | this._map = map;
20 | }
21 |
22 | /**
23 | * Returns an {@link ExpressionNode} from the backing map.
24 | *
25 | * @param {String} key the key under which the node is stored
26 | * @return {ExpressionNode} the node, if one is stored under that key; {@code null} otherwise
27 | */
28 | getValue(key) {
29 | return this._map[key];
30 | }
31 |
32 | /**
33 | * Checks if the map contains the property identified by the passed property name.
34 | *
35 | * @param {String} name the property name
36 | * @return {@code true} if the map contains the property, {@code false} otherwise
37 | */
38 | containsKey(name) {
39 | return name in this._map;
40 | }
41 |
42 | get map() {
43 | return this._map;
44 | }
45 | };
46 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/MultiOperation.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const ExpressionNode = require('./ExpressionNode');
14 |
15 | module.exports = class MultiOperation extends ExpressionNode {
16 | /**
17 | * @param {BinaryOperator} operator Operator
18 | * @param {ExpressionNode[]} operands The operands
19 | */
20 | constructor(operator, operands) {
21 | super();
22 | this.type = 'multi';
23 | Object.defineProperty(this, '_operator', { value: operator, enumerable: false });
24 | this.name = operator.sym;
25 | this.children = operands;
26 | }
27 |
28 | get operator() {
29 | return this._operator;
30 | }
31 |
32 | get operands() {
33 | return this.children;
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/NullLiteral.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const ExpressionNode = require('./ExpressionNode');
14 |
15 | class NullLiteral extends ExpressionNode {
16 | constructor() {
17 | super();
18 | this.type = 'null';
19 | }
20 |
21 | // eslint-disable-next-line class-methods-use-this
22 | toString() {
23 | return 'null';
24 | }
25 | }
26 |
27 | NullLiteral.INSTANCE = new NullLiteral();
28 |
29 | module.exports = NullLiteral;
30 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/NumericConstant.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Atom = require('./Atom');
14 |
15 | /**
16 | * Defines a numeric constant expression (e.g. "42.1").
17 | */
18 | class NumericConstant extends Atom {
19 | /**
20 | * Creates a numeric constant.
21 | *
22 | * @param {*} text the text representation
23 | */
24 | constructor(value) {
25 | super();
26 | this.type = 'number';
27 | this.value = value;
28 | }
29 |
30 | get text() {
31 | return String(this.value);
32 | }
33 | }
34 |
35 | NumericConstant.ZERO = new NumericConstant(0);
36 | NumericConstant.ONE = new NumericConstant(1);
37 | NumericConstant.TWO = new NumericConstant(2);
38 |
39 | module.exports = NumericConstant;
40 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/PropertyAccess.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const ExpressionNode = require('./ExpressionNode');
14 |
15 | module.exports = class PropertyAccess extends ExpressionNode {
16 | /**
17 | * @param {ExpressionNode} target Target expression
18 | * @param {ExpressionNode} property Property Expression
19 | */
20 | constructor(target, property) {
21 | super();
22 | this.type = 'access';
23 | this.children = [target, property];
24 | }
25 |
26 | get target() {
27 | return this.children[0];
28 | }
29 |
30 | get property() {
31 | return this.children[1];
32 | }
33 | };
34 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/PropertyIdentifier.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Identifier = require('./Identifier');
14 |
15 | class PropertyIdentifier extends Identifier {
16 | constructor(name) {
17 | super(name);
18 | this.type = 'property';
19 | }
20 | }
21 |
22 | module.exports = PropertyIdentifier;
23 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/RuntimeCall.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const ExpressionNode = require('./ExpressionNode');
14 |
15 | /**
16 | * A {@code RuntimeCall} is a special expression which provides access to utility functions from the
17 | * runtime.
18 | */
19 | module.exports = class RuntimeCall extends ExpressionNode {
20 | /**
21 | * Creates a {@code RuntimeCall} based on a {@code functionName} and an array
22 | * of {@code arguments}.
23 | *
24 | * @param {String} functionName the name of the function identifying the runtime call
25 | * @param {ExpressionNode} expression the node this call is applied on
26 | * @param {ExpressionNode...} args the arguments passed to the runtime call
27 | */
28 | constructor(functionName, expression, args) {
29 | super();
30 | this.type = 'runtimeCall';
31 | this._functionName = functionName;
32 | this._expression = expression;
33 | this._args = args || [];
34 | }
35 |
36 | get children() {
37 | return [this._expression, ...this._args];
38 | }
39 |
40 | get functionName() {
41 | return this._functionName;
42 | }
43 |
44 | get expression() {
45 | return this._expression;
46 | }
47 |
48 | get args() {
49 | return this._args;
50 | }
51 | };
52 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/StringConstant.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Atom = require('./Atom');
14 |
15 | class StringConstant extends Atom {
16 | static parse(str) {
17 | if (str[0] === '\'') {
18 | const sb = str.substring(1, str.length - 1)
19 | .replace(/[^\\]"/g, '\\"')
20 | .replace('\\\'', '\'');
21 | return new StringConstant(JSON.parse(`{"s":"${sb}"}`).s);
22 | }
23 | return new StringConstant(JSON.parse(`{"s":${str}}`).s);
24 | }
25 |
26 | constructor(text) {
27 | super();
28 | this.type = 'string';
29 | this.value = text;
30 | }
31 |
32 | get text() {
33 | return this.value;
34 | }
35 | }
36 |
37 | StringConstant.EMPTY = new StringConstant('');
38 | StringConstant.TRUE = new StringConstant('true');
39 | StringConstant.FALSE = new StringConstant('false');
40 |
41 | module.exports = StringConstant;
42 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/TernaryOperation.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const ExpressionNode = require('./ExpressionNode');
14 |
15 | module.exports = class TernaryOperation extends ExpressionNode {
16 | /**
17 | *
18 | * @param {ExpressionNode} condition Condition expression
19 | * @param {ExpressionNode} thenBranch Then branch expression
20 | * @param {ExpressionNode} elseBranch Else branch expression
21 | */
22 | constructor(condition, thenBranch, elseBranch) {
23 | super();
24 | this.type = 'ternary';
25 | this.children = [condition, thenBranch, elseBranch];
26 | }
27 |
28 | get condition() {
29 | return this.children[0];
30 | }
31 |
32 | get thenBranch() {
33 | return this.children[1];
34 | }
35 |
36 | get elseBranch() {
37 | return this.children[2];
38 | }
39 | };
40 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/UnaryOperation.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const ExpressionNode = require('./ExpressionNode');
14 |
15 | module.exports = class UnaryOperation extends ExpressionNode {
16 | /**
17 | *
18 | * @param {BinaryOperator} operator Binary operator
19 | * @param {ExpressionNode} target Target expression
20 | */
21 | constructor(operator, target) {
22 | super();
23 | this.type = 'unary';
24 | Object.defineProperty(this, '_operator', { value: operator, enumerable: false });
25 | this.name = operator.sym;
26 | this.children = [target];
27 | }
28 |
29 | get operator() {
30 | return this._operator;
31 | }
32 |
33 | get target() {
34 | return this.children[0];
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/src/parser/htl/nodes/UnaryOperator.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /**
14 | * Binary operators used in expressions.
15 | */
16 | module.exports = Object.freeze({
17 |
18 | /**
19 | * Evaluates the logical negation of the operand
20 | */
21 | NOT: {
22 | sym: '!',
23 | calc: (operand) => {
24 | if (Array.isArray(operand)) {
25 | return !operand.length;
26 | }
27 | return !operand;
28 | },
29 | },
30 |
31 | /**
32 | * Evaluates whether the operand is a string of only whitespace characters
33 | */
34 | IS_WHITESPACE: {
35 | sym: 'ws:',
36 | calc: (operand) => String(operand).trim().length === 0,
37 | },
38 |
39 | /**
40 | * Evaluates the length of a collection
41 | */
42 | LENGTH: {
43 | sym: 'len:',
44 | calc: (operand) => {
45 | if (Array.isArray(operand)) {
46 | return operand.length;
47 | }
48 | if (operand.length && (typeof operand.length === 'function')) {
49 | return operand.length();
50 | }
51 | return -1;
52 | },
53 | },
54 |
55 | /**
56 | * Evaluates if a value is empty
57 | */
58 | IS_EMPTY: {
59 | sym: 'emp:',
60 | calc: (operand) => {
61 | if (Array.isArray(operand)) {
62 | return operand.length === 0;
63 | }
64 | if (operand.length && (typeof operand.length === 'function')) {
65 | return operand.length() === 0;
66 | }
67 | return !`${operand}`;
68 | },
69 | },
70 |
71 | });
72 |
--------------------------------------------------------------------------------
/src/parser/html/ElementContext.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const PluginProxy = require('./PluginProxy');
14 |
15 | /**
16 | * The element context contains the information about the current processed element in the markup
17 | * handler, @type {module.ElementContext}
18 | */
19 | module.exports = class ElementContext {
20 | constructor(tagName) {
21 | this._tagName = tagName;
22 | this._attributes = {};
23 | this._isSlyTag = tagName.toLowerCase() === 'sly';
24 | this._plugin = new PluginProxy();
25 | }
26 |
27 | addAttribute(name, value, location) {
28 | this._attributes[name] = {
29 | name,
30 | value,
31 | location,
32 | };
33 | }
34 |
35 | addPluginAttribute(name, signature, expression) {
36 | this._attributes[name] = {
37 | name,
38 | signature,
39 | expression,
40 | };
41 | }
42 |
43 | addCallbackAttribute(name, callback) {
44 | this._attributes[name] = {
45 | name,
46 | callback,
47 | };
48 | }
49 |
50 | get tagName() {
51 | return this._tagName;
52 | }
53 |
54 | get isSlyTag() {
55 | return this._isSlyTag;
56 | }
57 |
58 | get attributes() {
59 | return this._attributes;
60 | }
61 |
62 | addPlugin(p) {
63 | this._plugin.add(p);
64 | }
65 |
66 | get plugin() {
67 | return this._plugin;
68 | }
69 | };
70 |
--------------------------------------------------------------------------------
/src/parser/html/ExpressionContext.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const PLUGIN_PREFIX = 'PLUGIN_DATA_SLY_';
14 |
15 | const ECTX = {
16 |
17 | // Plugin contexts
18 | PLUGIN_DATA_SLY_USE: 'PLUGIN_DATA_SLY_USE',
19 | PLUGIN_DATA_SLY_TEXT: 'PLUGIN_DATA_SLY_TEXT',
20 | PLUGIN_DATA_SLY_SET: 'PLUGIN_DATA_SLY_SET',
21 | PLUGIN_DATA_SLY_ATTRIBUTE: 'PLUGIN_DATA_SLY_ATTRIBUTE',
22 | PLUGIN_DATA_SLY_ELEMENT: 'PLUGIN_DATA_SLY_ELEMENT',
23 | PLUGIN_DATA_SLY_TEST: 'PLUGIN_DATA_SLY_TEST',
24 | PLUGIN_DATA_SLY_LIST: 'PLUGIN_DATA_SLY_LIST',
25 | PLUGIN_DATA_SLY_REPEAT: 'PLUGIN_DATA_SLY_REPEAT',
26 | PLUGIN_DATA_SLY_INCLUDE: 'PLUGIN_DATA_SLY_INCLUDE',
27 | PLUGIN_DATA_SLY_RESOURCE: 'PLUGIN_DATA_SLY_RESOURCE',
28 | PLUGIN_DATA_SLY_TEMPLATE: 'PLUGIN_DATA_SLY_TEMPLATE',
29 | PLUGIN_DATA_SLY_CALL: 'PLUGIN_DATA_SLY_CALL',
30 | PLUGIN_DATA_SLY_UNWRAP: 'PLUGIN_DATA_SLY_UNWRAP',
31 |
32 | // Markup contexts
33 | ELEMENT: 'ELEMENT',
34 | TEXT: 'TEXT',
35 | ATTRIBUTE: 'ATTRIBUTE',
36 |
37 | getContextForPlugin: (name) => {
38 | const ctx = ECTX[PLUGIN_PREFIX + name.toUpperCase()];
39 | if (!ctx) {
40 | throw new Error(`invalid plugin: ${name}`);
41 | }
42 | return ctx;
43 | },
44 | };
45 |
46 | module.exports = ECTX;
47 |
--------------------------------------------------------------------------------
/src/parser/html/ExpressionTransformer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const StringConstant = require('../htl/nodes/StringConstant');
14 | const Expression = require('../htl/nodes/Expression');
15 | const MultiOperation = require('../htl/nodes/MultiOperation');
16 | const BinaryOperator = require('../htl/nodes/BinaryOperator');
17 | const OptionHandler = require('../htl/OptionHandler');
18 |
19 | function join(nodes) {
20 | if (nodes.length === 0) {
21 | return StringConstant.EMPTY;
22 | }
23 | if (nodes.length === 1) {
24 | return nodes[0];
25 | }
26 | return new MultiOperation(BinaryOperator.CONCATENATE, nodes);
27 | }
28 |
29 | module.exports = class ExpressionTransformer {
30 | transform(interpolation, markupContext, expressionContext) {
31 | const nodes = [];
32 | const /* HashMap */ options = {};
33 | interpolation.fragments.forEach((fragment) => {
34 | if (fragment.type === 'text') {
35 | nodes.push(new StringConstant(fragment.value));
36 | } else {
37 | const xformed = this.adjustToContext(fragment, markupContext, expressionContext);
38 | nodes.push(xformed.root);
39 | Object.assign(options, xformed.options);
40 | }
41 | });
42 |
43 | const root = join(nodes);
44 |
45 | if (interpolation.fragments.length > 1 && options.context) {
46 | // context must not be calculated by merging
47 | delete options.context;
48 | }
49 | return new Expression(root, options, interpolation.content);
50 | }
51 |
52 | // eslint-disable-next-line class-methods-use-this
53 | adjustToContext(expression, markupContext, expressionContext) {
54 | const expr = expression;
55 | if (markupContext != null && !expr.options.context) {
56 | expr.options.context = new StringConstant(markupContext);
57 | }
58 | return OptionHandler.filter(expr, expressionContext);
59 | }
60 | };
61 |
--------------------------------------------------------------------------------
/src/parser/html/MarkupContext.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const MCTX = {
14 | HTML: 'html',
15 | TEXT: 'text',
16 | ELEMENT_NAME: 'elementName',
17 | ELEMENT_NAME_NF: 'elementNameNoFallback',
18 | ATTRIBUTE_NAME: 'attributeName',
19 | ATTRIBUTE: 'attribute',
20 | URI: 'uri',
21 | SCRIPT_TOKEN: 'scriptToken',
22 | SCRIPT_STRING: 'scriptString',
23 | SCRIPT_COMMENT: 'scriptComment',
24 | SCRIPT_REGEXP: 'scriptRegExp',
25 | STYLE_TOKEN: 'styleToken',
26 | STYLE_STRING: 'styleString',
27 | STYLE_COMMENT: 'styleComment',
28 | COMMENT: 'comment',
29 | NUMBER: 'number',
30 | UNSAFE: 'unsafe',
31 |
32 | attributeContext: (name) => {
33 | const upName = name.toLowerCase();
34 | if (upName === 'src' || upName === 'href') {
35 | return MCTX.URI;
36 | }
37 | return MCTX.ATTRIBUTE;
38 | },
39 | };
40 |
41 | const reverse = {};
42 | Object.keys(MCTX).forEach((k) => {
43 | reverse[MCTX[k]] = k;
44 | });
45 |
46 | MCTX.lookup = (k) => reverse[k];
47 |
48 | module.exports = MCTX;
49 |
--------------------------------------------------------------------------------
/src/parser/html/Plugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /* eslint-disable no-unused-vars,class-methods-use-this */
14 |
15 | module.exports = class Plugin {
16 | constructor(signature, pluginContext, expression, location) {
17 | this._signature = signature;
18 | this._pluginContext = pluginContext;
19 | this._expression = expression;
20 | this._location = location;
21 | }
22 |
23 | isValid() {
24 | return true;
25 | }
26 |
27 | get pluginContext() {
28 | return this._pluginContext;
29 | }
30 |
31 | get expression() {
32 | return this._expression;
33 | }
34 |
35 | get location() {
36 | return this._location;
37 | }
38 |
39 | beforeElement(stream, tagName, elementContext) {
40 | }
41 |
42 | beforeTagOpen(stream) {
43 | }
44 |
45 | beforeAttributes(stream) {
46 | }
47 |
48 | beforeAttribute(stream, attributeName) {
49 | }
50 |
51 | beforeAttributeValue(stream, attributeName, attributeValue) {
52 | }
53 |
54 | afterAttributeValue(stream, attributeName) {
55 | }
56 |
57 | afterAttribute(stream, attributeName) {
58 | }
59 |
60 | onPluginCall(stream, signature, expression) {
61 | }
62 |
63 | afterAttributes(stream) {
64 | }
65 |
66 | afterTagOpen(stream) {
67 | }
68 |
69 | beforeChildren(stream) {
70 | }
71 |
72 | afterChildren(stream) {
73 | }
74 |
75 | beforeTagClose(stream, isSelfClosing) {
76 | }
77 |
78 | afterTagClose(stream, isSelfClosing) {
79 | }
80 |
81 | afterElement(stream) {
82 | }
83 | };
84 |
--------------------------------------------------------------------------------
/src/parser/html/PluginContext.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const RuntimeCall = require('../htl/nodes/RuntimeCall');
14 |
15 | module.exports = class PluginContext {
16 | constructor(symbolGenerator, transformer, stream) {
17 | this._symbolGenerator = symbolGenerator;
18 | this._transformer = transformer;
19 | this._stream = stream;
20 | }
21 |
22 | get symbolGenerator() {
23 | return this._symbolGenerator;
24 | }
25 |
26 | get transformer() {
27 | return this._transformer;
28 | }
29 |
30 | get stream() {
31 | return this._stream;
32 | }
33 |
34 | generateVariable(hint) {
35 | return this._symbolGenerator.next(hint);
36 | }
37 |
38 | adjustToContext(expression, markupContext, expressionContext) {
39 | const { root } = expression;
40 | if (root instanceof RuntimeCall) {
41 | if (root.functionName === 'xss') {
42 | return expression;
43 | }
44 | }
45 | return this._transformer.adjustToContext(expression, markupContext, expressionContext);
46 | }
47 | };
48 |
--------------------------------------------------------------------------------
/src/parser/html/PluginProxy.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Plugin = require('./Plugin');
14 |
15 | module.exports = class PluginProxy {
16 | constructor() {
17 | this._plugins = [];
18 | }
19 |
20 | add(plugin) {
21 | this._plugins.push(plugin);
22 | }
23 |
24 | _delegate(fn, args) {
25 | this._plugins.forEach((p) => {
26 | p[fn](...args);
27 | });
28 | }
29 | };
30 |
31 | Object.getOwnPropertyNames(Plugin.prototype).filter((p) => p.startsWith('before') || p.startsWith('after') || p.startsWith('on')).forEach((fn) => {
32 | module.exports.prototype[fn] = function () { // eslint-disable-line func-names
33 | this._delegate(fn, arguments); // eslint-disable-line prefer-rest-params
34 | };
35 | });
36 |
--------------------------------------------------------------------------------
/src/parser/html/PluginSignature.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const PLUGIN_ATTRIBUTE_PREFIX = 'data-sly-';
14 |
15 | module.exports = class PluginSignature {
16 | constructor(name, args) {
17 | this._name = name;
18 | this._arguments = args || [];
19 | }
20 |
21 | get name() {
22 | return this._name;
23 | }
24 |
25 | get args() {
26 | return this._arguments;
27 | }
28 |
29 | static fromAttribute(attributeName) {
30 | if (!attributeName.startsWith(PLUGIN_ATTRIBUTE_PREFIX)) {
31 | return null;
32 | }
33 |
34 | const fragment = attributeName.substring(9);
35 | const parts = fragment.split('.');
36 | if (parts.length === 0) {
37 | return null;
38 | }
39 | return new PluginSignature(parts[0], parts.slice(1));
40 | }
41 |
42 | getVariableName(defaultValue) {
43 | const args = this._arguments;
44 | if (args.length > 0) {
45 | return args[0];
46 | }
47 | return defaultValue;
48 | }
49 | };
50 |
--------------------------------------------------------------------------------
/src/parser/html/SymbolGenerator.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const DEFAULT_VAR_PREFIX = 'var_';
14 |
15 | module.exports = class SymbolGenerator {
16 | constructor(prefix) {
17 | this._prefix = prefix || DEFAULT_VAR_PREFIX;
18 | this._counter = -1;
19 | }
20 |
21 | next(hint) {
22 | const middle = hint ? hint.replace(/-/g, '_') : '';
23 | this._counter += 1;
24 | return this._prefix + middle + this._counter;
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/src/parser/html/TemplateParser.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const MarkupHandler = require('./MarkupHandler');
14 | const CommandStream = require('../commands/CommandStream');
15 | const HTMLParser = require('./HTMLParser');
16 |
17 | module.exports = class TemplateParser {
18 | /**
19 | * Sets the default markup context when writing properties to the response.
20 | * @param {MarkupContext} context the default context
21 | * @return this
22 | */
23 | withDefaultMarkupContext(context) {
24 | this._defaultMarkupContext = context;
25 | return this;
26 | }
27 |
28 | /**
29 | * Parses the input and returns an the generated commands.
30 | * @param {String} input Input text
31 | * @return {Command[]} The generated commands
32 | */
33 | // eslint-disable-next-line class-methods-use-this
34 | parse(input) {
35 | const stream = new CommandStream();
36 | const handler = new MarkupHandler(stream);
37 | if (this._defaultMarkupContext !== undefined) {
38 | handler.withDefaultMarkupContext(this._defaultMarkupContext);
39 | }
40 |
41 | HTMLParser.parse(input, handler);
42 | return stream.commands;
43 | }
44 | };
45 |
--------------------------------------------------------------------------------
/src/parser/plugins/CallPlugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Deloitte Digital. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | const Plugin = require('../html/Plugin');
13 | const FunctionCall = require('../commands/FunctionCall');
14 | const MapLiteral = require('../htl/nodes/MapLiteral');
15 |
16 | module.exports = class CallPlugin extends Plugin {
17 | beforeChildren(stream) {
18 | stream.write(
19 | new FunctionCall(
20 | this._expression.root,
21 | new MapLiteral(this._expression.options),
22 | this.location,
23 | ),
24 | );
25 | stream.beginIgnore();
26 | }
27 |
28 | // eslint-disable-next-line class-methods-use-this
29 | afterChildren(stream) {
30 | stream.endIgnore();
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/src/parser/plugins/ElementPlugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Plugin = require('../html/Plugin');
14 | const VariableBinding = require('../commands/VariableBinding');
15 | const Conditional = require('../commands/Conditional');
16 | const OutputVariable = require('../commands/OutputVariable');
17 | const CreateElement = require('../commands/CreateElement');
18 | const PopElement = require('../commands/PopElement');
19 | const MarkupContext = require('../html/MarkupContext');
20 | const ExpressionContext = require('../html/ExpressionContext');
21 |
22 | module.exports = class ElementPlugin extends Plugin {
23 | constructor(signature, pluginContext, expression) {
24 | super(signature, pluginContext, expression);
25 |
26 | this.node = pluginContext.adjustToContext(
27 | expression,
28 | MarkupContext.ELEMENT_NAME_NF,
29 | ExpressionContext.ELEMENT,
30 | ).root;
31 | this.tagVar = pluginContext.generateVariable('tagVar');
32 | }
33 |
34 | beforeElement(stream) {
35 | stream.write(new VariableBinding.Start(this.tagVar, this.node));
36 | }
37 |
38 | beforeTagOpen(stream, isEmpty, isVoid) {
39 | stream.write(new Conditional.Start(this.tagVar));
40 | stream.write(new CreateElement(new OutputVariable(this.tagVar), isEmpty, isVoid));
41 | stream.write(Conditional.END);
42 | stream.write(new Conditional.Start(this.tagVar, true));
43 | }
44 |
45 | // eslint-disable-next-line class-methods-use-this
46 | beforeAttributes(stream) {
47 | stream.write(Conditional.END);
48 | }
49 |
50 | beforeTagClose(stream, isEmpty, isVoid) {
51 | stream.write(new Conditional.Start(this.tagVar));
52 | stream.write(new PopElement(new OutputVariable(this.tagVar), isEmpty, isVoid));
53 | stream.write(Conditional.END);
54 | stream.write(new Conditional.Start(this.tagVar, true));
55 | }
56 |
57 | // eslint-disable-next-line class-methods-use-this
58 | afterTagClose(stream/* , isSelfClosing */) {
59 | stream.write(Conditional.END);
60 | }
61 |
62 | // eslint-disable-next-line class-methods-use-this
63 | afterElement(stream) {
64 | stream.write(VariableBinding.END);
65 | }
66 | };
67 |
--------------------------------------------------------------------------------
/src/parser/plugins/ResourcePlugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Plugin = require('../html/Plugin');
14 | const OutputVariable = require('../commands/OutputVariable');
15 | const RuntimeCall = require('../htl/nodes/RuntimeCall');
16 | const MapLiteral = require('../htl/nodes/MapLiteral');
17 | const VariableBinding = require('../commands/VariableBinding');
18 |
19 | module.exports = class ResourcePlugin extends Plugin {
20 | beforeChildren(stream) {
21 | const variableName = this.pluginContext.generateVariable('resourceContent');
22 | const runtimeCall = new RuntimeCall('resource', this._expression.root, [new MapLiteral(this._expression.options)]);
23 | stream.write(new VariableBinding.Start(variableName, runtimeCall));
24 | stream.write(new OutputVariable(variableName));
25 | stream.write(VariableBinding.END);
26 | stream.beginIgnore();
27 | }
28 |
29 | // eslint-disable-next-line class-methods-use-this
30 | afterChildren(stream) {
31 | stream.endIgnore();
32 | }
33 | };
34 |
--------------------------------------------------------------------------------
/src/parser/plugins/SetPlugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Plugin = require('../html/Plugin');
14 | const VariableBinding = require('../commands/VariableBinding');
15 |
16 | module.exports = class SetPlugin extends Plugin {
17 | beforeElement(stream) {
18 | const variableName = this._signature.getVariableName(null);
19 | stream.write(new VariableBinding.Global(variableName, this.expression.root));
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/src/parser/plugins/TemplatePlugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Deloitte Digital. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | const Plugin = require('../html/Plugin');
13 |
14 | module.exports = class TemplatePlugin extends Plugin {
15 | beforeElement(stream) {
16 | const variableName = this._signature.getVariableName(null);
17 | if (variableName === null) {
18 | throw new Error('data-sly-template must be called with an identifier');
19 | }
20 | stream.beginFunction(variableName, this._expression.options);
21 | stream.beginIgnore();
22 | }
23 |
24 | // eslint-disable-next-line class-methods-use-this
25 | beforeChildren(stream) {
26 | stream.endIgnore();
27 | }
28 |
29 | // eslint-disable-next-line class-methods-use-this
30 | afterChildren(stream) {
31 | stream.endFunction();
32 | stream.beginIgnore();
33 | }
34 |
35 | // eslint-disable-next-line class-methods-use-this
36 | afterElement(stream) {
37 | stream.endIgnore();
38 | }
39 | };
40 |
--------------------------------------------------------------------------------
/src/parser/plugins/TestPlugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Plugin = require('../html/Plugin');
14 | const VariableBinding = require('../commands/VariableBinding');
15 | const Conditional = require('../commands/Conditional');
16 | const Identifier = require('../htl/nodes/Identifier');
17 |
18 | module.exports = class TestPlugin extends Plugin {
19 | beforeElement(stream) {
20 | const ctx = this.pluginContext;
21 | let variableName = this._signature.getVariableName(null);
22 | this._useGlobalBinding = variableName != null;
23 | if (variableName == null) {
24 | variableName = ctx.generateVariable('testVariable');
25 | } else {
26 | variableName = variableName.toLowerCase();
27 | }
28 | this._variableName = variableName;
29 |
30 | if (this._useGlobalBinding) {
31 | stream.write(new VariableBinding.Global(variableName, this.expression.root));
32 | } else {
33 | stream.write(new VariableBinding.Start(variableName, this.expression.root));
34 | }
35 | }
36 |
37 | beforeTagOpen(stream) {
38 | stream.write(new Conditional.Start(new Identifier(this._variableName)), true);
39 | }
40 |
41 | afterElement(stream) {
42 | stream.write(Conditional.END);
43 | if (!this._useGlobalBinding) {
44 | stream.write(VariableBinding.END);
45 | }
46 | }
47 | };
48 |
--------------------------------------------------------------------------------
/src/parser/plugins/TextPlugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Plugin = require('../html/Plugin');
14 | const VariableBinding = require('../commands/VariableBinding');
15 | const OutputVariable = require('../commands/OutputVariable');
16 | const ExpressionContext = require('../html/ExpressionContext');
17 | const MarkupContext = require('../html/MarkupContext');
18 |
19 | module.exports = class TextPlugin extends Plugin {
20 | beforeChildren(stream) {
21 | const ctx = this.pluginContext;
22 | const variable = ctx.generateVariable('textContent');
23 | stream.write(new VariableBinding.Start(
24 | variable,
25 | ctx.adjustToContext(this.expression, MarkupContext.TEXT, ExpressionContext.TEXT).root,
26 | ));
27 | stream.write(new OutputVariable(variable));
28 | stream.write(VariableBinding.END);
29 | stream.beginIgnore();
30 | }
31 |
32 | // eslint-disable-next-line class-methods-use-this
33 | afterChildren(stream) {
34 | stream.endIgnore();
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/src/parser/plugins/UnwrapPlugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Plugin = require('../html/Plugin');
14 | const VariableBinding = require('../commands/VariableBinding');
15 | const Conditional = require('../commands/Conditional');
16 | const BooleanConstant = require('../htl/nodes/BooleanConstant');
17 | const StringConstant = require('../htl/nodes/StringConstant');
18 |
19 | module.exports = class UnwrapPlugin extends Plugin {
20 | beforeElement(stream/* , elemContext */) {
21 | const ctx = this.pluginContext;
22 | this.variableName = this._signature.getVariableName(null);
23 | this._useGlobalBinding = this.variableName != null;
24 | if (this.variableName == null) {
25 | this.variableName = ctx.generateVariable('unwrapCondition');
26 | }
27 | this.variableName = this.variableName.toLowerCase();
28 | this.unwrapTest = new Conditional.Start(this.variableName, true);
29 |
30 | if (this._useGlobalBinding) {
31 | stream.write(new VariableBinding.Global(this.variableName, this.expression.root));
32 | } else {
33 | stream.write(new VariableBinding.Start(this.variableName, this.testRoot()));
34 | }
35 | }
36 |
37 | beforeTagOpen(stream) {
38 | stream.write(this.unwrapTest);
39 | }
40 |
41 | // eslint-disable-next-line class-methods-use-this
42 | afterTagOpen(stream) {
43 | stream.write(Conditional.END);
44 | }
45 |
46 | beforeTagClose(stream) {
47 | stream.write(this.unwrapTest);
48 | }
49 |
50 | // eslint-disable-next-line class-methods-use-this
51 | afterTagClose(stream) {
52 | stream.write(Conditional.END);
53 | }
54 |
55 | afterElement(stream) {
56 | if (!this._useGlobalBinding) {
57 | stream.write(VariableBinding.END);
58 | }
59 | }
60 |
61 | testRoot() {
62 | const testNode = this.expression.root instanceof StringConstant
63 | && this.expression.root.text.length === 0;
64 | return testNode ? BooleanConstant.TRUE : this.expression.root;
65 | }
66 | };
67 |
--------------------------------------------------------------------------------
/src/parser/plugins/UsePlugin.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | const Plugin = require('../html/Plugin');
14 | const FileReference = require('../commands/FileReference');
15 | const MapLiteral = require('../htl/nodes/MapLiteral');
16 | const StringConstant = require('../htl/nodes/StringConstant');
17 |
18 | const DEFAULT_VARIABLE_NAME = 'useBean';
19 |
20 | module.exports = class UsePlugin extends Plugin {
21 | beforeElement(stream) {
22 | const variableName = this._signature.getVariableName(DEFAULT_VARIABLE_NAME).toLowerCase();
23 | if (this._expression.root instanceof StringConstant) {
24 | const lib = this._expression.root.text;
25 | stream.write(new FileReference(
26 | variableName,
27 | lib,
28 | [new MapLiteral(this._expression.options)],
29 | ), true);
30 | return;
31 | }
32 | throw new Error('data-sly-use only supports static references.');
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/src/runtime/DOMFactory.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | /* eslint-disable class-methods-use-this,no-unused-vars */
13 | module.exports = class DOMFactory {
14 | start() {}
15 |
16 | end() {}
17 |
18 | doctype(node, text) {}
19 |
20 | text(node, text) {}
21 |
22 | rem(node, text) {}
23 |
24 | append(node, value) {}
25 |
26 | create(name) {}
27 |
28 | attr(node, name, value) {}
29 |
30 | push(parent, node) {}
31 |
32 | pop(node) {}
33 | };
34 |
--------------------------------------------------------------------------------
/src/runtime/HDOMFactory.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | /* eslint-disable class-methods-use-this */
13 | const unified = require('unified');
14 | const parse = require('rehype-parse');
15 | const DOMFactory = require('./DOMFactory');
16 |
17 | module.exports = class HDOMFactory extends DOMFactory {
18 | start() {
19 | this._root = { type: 'root', children: [] };
20 | return this._root;
21 | }
22 |
23 | end() {
24 | return this._root;
25 | }
26 |
27 | doctype(node, name) {
28 | node.children.push({ type: 'doctype', name });
29 | return node;
30 | }
31 |
32 | create(tagName) {
33 | return {
34 | type: 'element',
35 | tagName,
36 | properties: {},
37 | children: [],
38 | };
39 | }
40 |
41 | append(node, value) {
42 | if (typeof value === 'object' && value.type) {
43 | // todo: clone ?
44 | } else {
45 | // eslint-disable-next-line no-param-reassign
46 | value = unified().use(parse, { fragment: true }).parse(String(value));
47 | }
48 | node.children.push(value);
49 | }
50 |
51 | text(node, text) {
52 | node.children.push({ type: 'text', value: text });
53 | }
54 |
55 | rem(node, text) {
56 | node.children.push({ type: 'comment', value: text });
57 | }
58 |
59 | attr(node, name, value) {
60 | // eslint-disable-next-line no-param-reassign
61 | node.properties[name] = Array.isArray(value) ? value.join(',') : `${value}`;
62 | }
63 |
64 | push(parent, node) {
65 | parent.children.push(node);
66 | // eslint-disable-next-line no-param-reassign
67 | node.parent = parent;
68 | return node;
69 | }
70 |
71 | pop(node) {
72 | const ret = node.parent;
73 | // eslint-disable-next-line no-param-reassign
74 | delete node.parent;
75 | return ret;
76 | }
77 | };
78 |
--------------------------------------------------------------------------------
/src/runtime/HtmlDOMFactory.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | const DOMFactory = require('./DOMFactory');
13 | const formatXss = require('./format_xss');
14 |
15 | module.exports = class HtmlDOMFactory extends DOMFactory {
16 | start() {
17 | this._stack = [];
18 | this._buf = '';
19 | }
20 |
21 | _out(text) {
22 | this._buf += text;
23 | }
24 |
25 | end() {
26 | return this._buf;
27 | }
28 |
29 | doctype(node, name) {
30 | this._out(``);
31 | return node;
32 | }
33 |
34 | create(tagName, isEmpty, isVoid) {
35 | this._out(`<${tagName}`);
36 | return {
37 | tagName,
38 | isEmpty,
39 | isVoid,
40 | };
41 | }
42 |
43 | append(node, value) {
44 | this._out(value);
45 | }
46 |
47 | text(node, text) {
48 | this._out(text);
49 | }
50 |
51 | rem(node, text) {
52 | this._out(``);
53 | }
54 |
55 | attr(node, name, value, context) {
56 | if (value === true || value === null) {
57 | this._out(` ${name}`);
58 | return;
59 | }
60 | if (typeof value === 'string' && !value) {
61 | this._out(` ${name}=""`);
62 | return;
63 | }
64 | const escaped = formatXss(value, context, name);
65 | if (escaped) {
66 | this._out(` ${name}="${escaped}"`);
67 | }
68 | }
69 |
70 | push(parent, node) {
71 | if (node.isEmpty) {
72 | this._out('/>');
73 | } else {
74 | this._out('>');
75 | }
76 | this._stack.push(node);
77 | }
78 |
79 | pop() {
80 | const n = this._stack.pop();
81 | if (!n.isEmpty && !n.isVoid) {
82 | this._out(`${n.tagName}>`);
83 | }
84 | }
85 | };
86 |
--------------------------------------------------------------------------------
/src/runtime/fsResourceLoader.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2020 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | const path = require('path');
13 | const fs = require('fs');
14 |
15 | /**
16 | * Creates an FS based resource loader using the `resourceDir` as base directory.
17 | * @param {string} resourceDir The directory to resolve resources.
18 | */
19 | module.exports = function createResourceLoader(resourceDir) {
20 | /**
21 | * Load the resource with the give uri.
22 | * @param {Runtime} runtime current runtime
23 | * @param {string} uri resource uri
24 | * @returns {Promise<*>} the resource
25 | */
26 | return async (runtime, uri) => {
27 | const resourcePath = path.resolve(resourceDir, uri);
28 |
29 | return new Promise((resolve, reject) => {
30 | fs.readFile(resourcePath, 'utf8', (err, data) => {
31 | if (err) {
32 | reject(err);
33 | } else {
34 | resolve(data);
35 | }
36 | });
37 | });
38 | };
39 | };
40 |
--------------------------------------------------------------------------------
/src/runtime/resly.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | const Compiler = require('../compiler/Compiler');
13 | const Runtime = require('./Runtime');
14 |
15 | /**
16 | * HTL transformer for unified.
17 | * @param {*} options The transformer options
18 | * @param {string} options.code The HTL template code
19 | * @returns {function(): transformer}
20 | */
21 | module.exports = function resly(options = {}) {
22 | if (!options.code) {
23 | throw Error('option.code is mandatory.');
24 | }
25 |
26 | async function compile(code) {
27 | const compiler = new Compiler()
28 | .withRuntimeVar('dom');
29 | return compiler.compileToFunction(code);
30 | }
31 |
32 | return function hastUtilHTL() {
33 | const runtime = new Runtime()
34 | .withDomFactory(new Runtime.HDOMFactory());
35 |
36 | return function transformer(node, file, next) {
37 | runtime.setGlobal('dom', node);
38 |
39 | compile(options.code)
40 | .then((main) => main(runtime))
41 | .then((result) => {
42 | next(null, result, file);
43 | }).catch(next);
44 | };
45 | };
46 | };
47 |
--------------------------------------------------------------------------------
/test/TestHandler.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | /* eslint-disable no-unused-vars */
13 | module.exports = class TestHandler {
14 | onDocumentStart() {
15 | this._result = '';
16 | }
17 |
18 | // eslint-disable-next-line class-methods-use-this
19 | onDocumentEnd() {
20 | }
21 |
22 | onOpenTagStart(tagName) {
23 | this._result += `<${tagName}`;
24 | }
25 |
26 | onAttribute(name, value, quoteChar, line, column) {
27 | if (value !== null) {
28 | if (quoteChar === '"') {
29 | // eslint-disable-next-line no-param-reassign
30 | value = value.replace('"', '"');
31 | }
32 | this._result += ` ${name}=${quoteChar}${value}${quoteChar}`;
33 | } else {
34 | this._result += ` ${name}`;
35 | }
36 | }
37 |
38 | onOpenTagEnd(isEmpty, isVoid) {
39 | const markup = isEmpty ? '/>' : '>';
40 | this._result += markup;
41 | }
42 |
43 | onCloseTag(tagName, isVoid) {
44 | if (!isVoid) {
45 | this._result += `${tagName}>`;
46 | }
47 | }
48 |
49 | onText(text, line, column) {
50 | this._result += text;
51 | }
52 |
53 | onComment(markup, line, column) {
54 | this._result += ``;
55 | }
56 |
57 | onDocType(markup, line, column) {
58 | this._result += markup;
59 | }
60 |
61 | get result() {
62 | return this._result;
63 | }
64 | };
65 |
--------------------------------------------------------------------------------
/test/engine_test.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /* eslint-env mocha */
14 |
15 | // built-in modules
16 | const assert = require('assert');
17 | const path = require('path');
18 | // declared dependencies
19 | const fse = require('fs-extra');
20 | // local modules
21 | const engine = require('../src/main');
22 |
23 | const TEMPLATE_SIMPLE_2 = path.resolve(__dirname, 'templates', 'simple2.htl');
24 | const EXPECTED_SIMPLE_2 = path.resolve(__dirname, 'templates', 'simple2.html');
25 | const GLOBALS = {
26 | world: 'Earth',
27 | properties: {
28 | title: 'Hello, world.',
29 | fruits: ['Apple', 'Banana', 'Orange'],
30 | comma: ', ',
31 | },
32 | nav: {
33 | foo: 'This is foo. ',
34 | },
35 | test: 'This is a test',
36 | qttMin: 4,
37 | qttMax: 4,
38 | expression: 'this is an expression.',
39 | it: {
40 | html: 'foo barty!',
41 | title: 'Hello, world!',
42 | children: [
43 | '
A
',
44 | '
B
',
45 | ],
46 | },
47 | };
48 |
49 | describe('Engine test', async () => {
50 | it('Simple htl can be executed', async () => {
51 | const template = await fse.readFile(TEMPLATE_SIMPLE_2, 'utf-8');
52 | const expected = await fse.readFile(EXPECTED_SIMPLE_2, 'utf-8');
53 | const ret = await engine(GLOBALS, template);
54 | assert.equal(ret, expected);
55 | });
56 | });
57 |
58 | describe('Engine Performance test', async () => {
59 | const TEST_FILES = ['simple2.html', '400kb.htm', '700kb.htm'];
60 | TEST_FILES.forEach((filename) => {
61 | it(`produces htl output for ${filename}`, async () => {
62 | const filePath = path.resolve(__dirname, 'templates', filename);
63 | const source = await fse.readFile(filePath, 'utf-8');
64 | const result = await engine(GLOBALS, source);
65 | assert.equal(result, source);
66 | }).timeout(30000);
67 | });
68 | });
69 |
--------------------------------------------------------------------------------
/test/html_parser_test.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /* eslint-env mocha */
14 |
15 | // built-in modules
16 | const assert = require('assert');
17 | const path = require('path');
18 | // declared dependencies
19 | const fse = require('fs-extra');
20 | // local modules
21 | const MarkupHandler = require('../src/parser/html/MarkupHandler');
22 | const CommandStream = require('../src/parser/commands/CommandStream');
23 | const HTMLParser = require('../src/parser/html/HTMLParser');
24 | const TestHandler = require('./TestHandler');
25 |
26 | /**
27 | * Simple tests that check if the parser can parse html
28 | */
29 | describe('HTML Parsing', () => {
30 | const TEST_FILES = ['simple.htm'];
31 |
32 | TEST_FILES.forEach((filename) => {
33 | it(`parses ${filename}`, async () => {
34 | const filePath = path.resolve(__dirname, 'templates', filename);
35 | const source = await fse.readFile(filePath, 'utf-8');
36 |
37 | const handler = new TestHandler();
38 | HTMLParser.parse(source, handler);
39 | assert.equal(handler.result, source);
40 | });
41 | });
42 | });
43 |
44 | /**
45 | * Simple tests that check if the parser can process all the expressions
46 | */
47 | describe('HTML Parsing and Processing', () => {
48 | const TEST_FILES = ['simple.htm', '400kb.htm', '700kb.htm'];
49 |
50 | TEST_FILES.forEach((filename) => {
51 | it(`parses and processes ${filename}`, async () => {
52 | const filePath = path.resolve(__dirname, 'templates', filename);
53 | const source = await fse.readFile(filePath, 'utf-8');
54 |
55 | const handler = new MarkupHandler(new CommandStream());
56 | HTMLParser.parse(source, handler);
57 | }).timeout(30000);
58 | });
59 | });
60 |
--------------------------------------------------------------------------------
/test/include/main.htl:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/test/multi/test-data.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = {
13 | foo: 42,
14 | bar: 66,
15 | title: 'Hello, world.',
16 | 'jcr:title': 'Hello, mars.',
17 | list: [
18 | { title: 'item 1' },
19 | { title: 'item 2' },
20 | { title: 'item 3' },
21 | ],
22 | tabs: [
23 | { title: 'tab 1' },
24 | { title: 'tab 2' },
25 | { title: 'tab 3' },
26 | ],
27 | };
28 |
--------------------------------------------------------------------------------
/test/resly_test.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /* eslint-env mocha */
14 | /* eslint-disable no-template-curly-in-string */
15 | const assert = require('assert');
16 | const unified = require('unified');
17 | const markdown = require('remark-parse');
18 | const remark2rehype = require('remark-rehype');
19 | const html = require('rehype-stringify');
20 | const { resly } = require('../src/index.js');
21 |
22 | const code = '${dom.children[0].children[0].value}\n'
23 | + '\n'
24 | + '
\n'
44 | + '';
45 |
46 | describe('resly test', () => {
47 | it('can transform simple hast', (done) => {
48 | unified()
49 | .use(markdown)
50 | .use(remark2rehype)
51 | .use(resly({ code }))
52 | .use(html)
53 | .process(md, (err, file) => {
54 | if (err) {
55 | done(err);
56 | return;
57 | }
58 | try {
59 | assert.equal(String(file), expected);
60 | done();
61 | } catch (e) {
62 | done(e);
63 | }
64 | });
65 | });
66 | });
67 |
--------------------------------------------------------------------------------
/test/specs/attribute.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = {
13 | properties: {
14 | myValues: 'some data value',
15 | myClass: 'super-green',
16 | 'jcr:content': 'the content',
17 | },
18 | 'jcr:content': 'hello again',
19 | quotes: 'Hello, "World & Mars!"',
20 | foobar: {
21 | id: 'foo',
22 | class: 'bar',
23 | lang: '',
24 | },
25 | attrs: {
26 | checked: true,
27 | },
28 | date: '2019-04-02T08:44:26.000Z',
29 | };
30 |
--------------------------------------------------------------------------------
/test/specs/call.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Deloitte Digital. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = {
13 | foo: 42,
14 | };
15 |
--------------------------------------------------------------------------------
/test/specs/call_spec/recursion_test.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Deloitte Digital. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = class MyUseClass {
13 | // eslint-disable-next-line class-methods-use-this
14 | use() {
15 | return {
16 | pages: [
17 | {
18 | title: 'Page A',
19 | pages: [
20 | {
21 | title: 'Page 1',
22 | }, {
23 | title: 'Page 2',
24 | }, {
25 | title: 'Page 3',
26 | },
27 | ],
28 | }, {
29 | title: 'Page B',
30 | pages: [
31 | {
32 | title: 'Page 1',
33 | }, {
34 | title: 'Page 2',
35 | },
36 | ],
37 | }, {
38 | title: 'Page C',
39 | pages: [
40 | {
41 | title: 'Page 1',
42 | }, {
43 | title: 'Page 2',
44 | }, {
45 | title: 'Page 3',
46 | }, {
47 | title: 'Page 4',
48 | },
49 | ],
50 | },
51 | ],
52 | };
53 | }
54 | };
55 |
--------------------------------------------------------------------------------
/test/specs/context.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = {
13 | properties: {
14 | title: 'HTML & Things are bold or Single \' or double " quoted.',
15 | attvalue: '" onload="alert()" "',
16 | nav: '/SUMMARY',
17 | abs: 'https://www.primordialsoup.life/index.html',
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/test/specs/dom.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | const unified = require('unified');
13 | const parse = require('rehype-parse');
14 | const { JSDOM } = require('jsdom');
15 |
16 | const header = 'Hello, World';
17 |
18 | const mydoc = new JSDOM('
13 | #
14 | ###
15 |
--------------------------------------------------------------------------------
/test/specs/element.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = {
13 | properties: {
14 | allowed: ['section', 'nav', 'article', 'aside', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'footer', 'address', 'main', 'p', 'pre', 'blockquote', 'ol', 'li', 'dl', 'dt', 'dd', 'figure', 'figcaption', 'div', 'a', 'em', 'strong', 'small', 's', 'cite', 'q', 'dfn', 'abbr', 'data', 'time', 'code', 'var', 'samp', 'kbd', 'sub', 'sup', 'i', 'b', 'u', 'mark', 'ruby', 'rt', 'rp', 'bdi', 'bdo', 'span', 'br', 'wbr', 'ins', 'del', 'table', 'caption', 'colgroup', 'col', 'tbody', 'thead', 'tfoot', 'tr', 'td', 'th'],
15 | forbidden: ['script', 'style', 'form', 'input'],
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/test/specs/element.spec:
--------------------------------------------------------------------------------
1 | #
2 | ### sightly element replacement
3 | #
4 |
3 |
4 |
--------------------------------------------------------------------------------
/test/specs/template_spec/templateLib.html:
--------------------------------------------------------------------------------
1 | blah 1
2 |
3 | stuff outside the template should not be rendered!
4 |
5 | blah 2
6 |
7 | blah ${jcr:title}
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/test/specs/template_spec/templateLib1.html:
--------------------------------------------------------------------------------
1 |
2 | ${a}
3 |
4 |
--------------------------------------------------------------------------------
/test/specs/tst.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = {
13 | properties: {
14 | true0: 'hello',
15 | true1: 1,
16 | true2: true,
17 | false0: '',
18 | false1: 0,
19 | false2: false,
20 | },
21 | };
22 |
--------------------------------------------------------------------------------
/test/specs/tst_hast.spec:
--------------------------------------------------------------------------------
1 | #
2 | ### simple test
3 | #
4 |
Title: Bold!
32 | ===
33 |
34 | #
35 | ### test with global variable
36 | #
37 |
It is true!
38 | It was: ${out}
39 | ===
40 |
It is true!
41 | It was: hello
42 | #
43 | ### test with variable with colon
44 | #
45 |
It is true!
46 | It was: ${is:out}
47 | ===
48 |
It is true!
49 | It was: hello
50 | #
51 | ###
52 |
--------------------------------------------------------------------------------
/test/specs/unwrap.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = {
13 | properties: {
14 | unwrap: true,
15 | falseTest: false,
16 | url: 'url',
17 | title: 'yes',
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/test/specs/unwrap.spec:
--------------------------------------------------------------------------------
1 | #
2 | ### unwrap with value and variable
3 | #
4 |
5 | ${properties.title}: ${unwrapTest}
6 |
7 | ===
8 |
9 | yes: true
10 |
11 | #
12 | ### unwrap with value and variable with false
13 | #
14 |
15 | ${properties.title}: ${unwrapTest}
16 |
17 | ===
18 |
19 | yes: false
20 |
21 | #
22 | ### unwrap with value no variable
23 | #
24 |
25 | ${properties.title}
26 |
27 | ===
28 |
29 | yes
30 |
31 | #
32 | ### unwrap
33 | #
34 | ${properties.title}
35 | ===
36 | yes
37 | #
38 | ###
39 |
--------------------------------------------------------------------------------
/test/specs/unwrap_hast.spec:
--------------------------------------------------------------------------------
1 | #
2 | ### unwrap with value and variable
3 | #
4 |
5 | ${properties.title}
6 |
7 | ===
8 |
9 | yes
10 |
11 | #
12 | ### unwrap with value no variable
13 | #
14 |
15 | ${properties.title}
16 |
17 | ===
18 |
19 | yes
20 |
21 | #
22 | ### unwrap
23 | #
24 | ${properties.title}
25 | ===
26 | yes
27 | #
28 | ###
29 |
--------------------------------------------------------------------------------
/test/specs/uri.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = {
13 | jsuse: {
14 | query: {
15 | q: 'htl',
16 | array: [1, 2, 3],
17 | },
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/test/specs/use.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = {
13 | properties: {
14 | title: 'Hello, world',
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/test/specs/use.spec:
--------------------------------------------------------------------------------
1 | #
2 | ### sightly use function
3 | #
4 |
Hello ${page.title}.
5 | ===
6 |
Hello Jupiter.
7 | ^^^
8 | 29: $.dom.append($n, var_0);
9 | #
10 | ### sightly use variables are case insensitive
11 | #
12 |
25 | #
26 | ### using functions with colon
27 | #
28 |
etag: ${page.jcr:etag}
29 | ===
30 |
etag: 1234
31 | #
32 | ### using async use classes
33 | #
34 |
Hello ${page.title}.
35 | ===
36 |
Hello Saturn.
37 | #
38 | ###
39 |
--------------------------------------------------------------------------------
/test/specs/use_spec/test_page.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = class MyUseClass {
13 | use() {
14 | const r = Number(this.radius);
15 |
16 | return {
17 | title: this['jcr:title'] || 'Jupiter',
18 | subTitle: `${this.value1}: ${this.value2}`,
19 | get area() {
20 | return 4 * Math.PI * r * r;
21 | },
22 | get 'jcr:etag'() {
23 | return '1234';
24 | },
25 | getText() {
26 | return 'some text';
27 | },
28 | isBold() {
29 | return true;
30 | },
31 | delayedText() {
32 | return new Promise((resolve) => {
33 | setTimeout(() => resolve('delayed hello.'), 10);
34 | });
35 | },
36 | };
37 | }
38 | };
39 |
--------------------------------------------------------------------------------
/test/specs/use_spec/test_page_async.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 | module.exports = class MyUseClass {
13 | // eslint-disable-next-line class-methods-use-this
14 | use() {
15 | return new Promise((resolve) => {
16 | setTimeout(resolve({
17 | title: 'Saturn',
18 | }), 200);
19 | });
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/test/templates/custom_modules/exp.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /* eslint-disable */
14 |
15 | module.exports = function main($) {
16 |
17 | const global = $.globals;
18 |
19 | const $use_0 = myRequire('foo');
20 | const $use_1 = require("global-module");
21 | const $use_2 = require("./local-module");
22 | const $use_3 = require("./../relative-module");
23 |
24 | return $.run(function* () {
25 | let $t, $n = $.dom.start();
26 | const v1 = yield $.use($use_0, {});
27 | $.dom.text($n,"\n");
28 | const v2 = yield $.use($use_1, {});
29 | $.dom.text($n,"\n");
30 | const v4 = yield $.use($use_2, {});
31 | $.dom.text($n,"\n");
32 | const v5 = yield $.use($use_3, {});
33 | $.dom.text($n,"\n");
34 | return $.dom.end();
35 |
36 | });
37 | };
38 |
--------------------------------------------------------------------------------
/test/templates/custom_modules/src.htl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/test/templates/custom_template.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Adobe. All rights reserved.
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License. You may obtain a copy
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 | *
7 | * Unless required by applicable law or agreed to in writing, software distributed under
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 | * OF ANY KIND, either express or implied. See the License for the specific language
10 | * governing permissions and limitations under the License.
11 | */
12 |
13 | /* eslint-disable */
14 | const { Runtime } = require('MOD_HTLENGINE');
15 |
16 | function run($) {
17 | // TEMPLATES
18 |
19 | return $.run(function* () {
20 |
21 | // RUNTIME_GLOBALS
22 |
23 | // CODE
24 | });
25 | }
26 |
27 | module.exports.main = async function main(resource) {
28 | const runtime = new Runtime();
29 | runtime.setGlobal(resource);
30 | return run(runtime);
31 | };
32 |
--------------------------------------------------------------------------------
/test/templates/fragment.htl:
--------------------------------------------------------------------------------
1 |