@platformos/liquid-html-parser 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -0
- package/dist/conditional-comment.d.ts +5 -0
- package/dist/conditional-comment.js +16 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.js +57 -0
- package/dist/grammar.d.ts +16 -0
- package/dist/grammar.js +42 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +28 -0
- package/dist/stage-1-cst.d.ts +477 -0
- package/dist/stage-1-cst.js +1104 -0
- package/dist/stage-2-ast.d.ts +794 -0
- package/dist/stage-2-ast.js +1513 -0
- package/dist/types.d.ts +124 -0
- package/dist/types.js +146 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +31 -0
- package/grammar/liquid-html.ohm +750 -0
- package/grammar/liquid-html.ohm.js +751 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<h1 align="center" style="position: relative;" >
|
|
2
|
+
<br>
|
|
3
|
+
<img src="https://github.com/Platform-OS/platformos-tools/blob/main/packages/vscode-extension/images/platformos_logo.png?raw=true" alt="platformOS logo" width="200">
|
|
4
|
+
<br>
|
|
5
|
+
Liquid HTML parser
|
|
6
|
+
</h1>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="https://www.npmjs.com/package/@platformos/liquid-html-parser"><img src="https://img.shields.io/npm/v/@platformos/liquid-html-parser.svg?sanitize=true" alt="Version"></a>
|
|
10
|
+
<a href="https://github.com/Platform-OS/platformos-tools/blob/main/LICENSE.md"><img src="https://img.shields.io/npm/l/@platformos/liquid-html-parser.svg?sanitize=true" alt="License"></a>
|
|
11
|
+
<a href="https://github.com/Platform-OS/platformos-tools/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/Platform-OS/platformos-tools/actions/workflows/ci.yml/badge.svg"></a>
|
|
12
|
+
<!--
|
|
13
|
+
<a href="https://npmcharts.com/compare/@platformos/liquid-html-parser?minimal=true"><img src="https://img.shields.io/npm/dm/@platformos/prettier-plugin-liquid.svg?sanitize=true" alt="Downloads"></a>
|
|
14
|
+
-->
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
This module provides the Liquid HTML parser that powers the prettier plugin, linter and language server for platformOS.
|
|
18
|
+
|
|
19
|
+
It turns a `.liquid` file contents into an Abstract Syntax Tree (AST) that contains _both_ Liquid and HTML nodes.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# with npm
|
|
25
|
+
npm install @platformos/liquid-html-parser
|
|
26
|
+
|
|
27
|
+
# with yarn
|
|
28
|
+
yarn add @platformos/liquid-html-parser
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { toLiquidHtmlAST, LiquidHtmlNode, NodeTypes } from '@platformos/prettier-plugin-liquid';
|
|
35
|
+
|
|
36
|
+
const ast: LiquidHtmlNode = toLiquidHtmlAST(`
|
|
37
|
+
<body>
|
|
38
|
+
{% for product in all_products %}
|
|
39
|
+
<img src="{{ product | image_url }}">
|
|
40
|
+
{% endfor %}
|
|
41
|
+
</body>
|
|
42
|
+
`);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## You should know
|
|
46
|
+
|
|
47
|
+
Because Liquid is very permissive, things like the `name` of an HTML tag may have a surprising type: an array of `LiquidVariableOutput | TextNode`.
|
|
48
|
+
|
|
49
|
+
This is because the following use cases are supported by the parser:
|
|
50
|
+
|
|
51
|
+
```liquid
|
|
52
|
+
{% # compound html tag names %}
|
|
53
|
+
<tag-{{ name }}>
|
|
54
|
+
</tag-{{ name }}>
|
|
55
|
+
|
|
56
|
+
{% # compound html attribute names %}
|
|
57
|
+
<img data-{{ attr_name }}="...">
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
MIT.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getConditionalComment = void 0;
|
|
4
|
+
const commentRegex = /(<!--\[if[^\]]*]>)((.|\n)*)(<!\[endif\]-->)$/;
|
|
5
|
+
const getConditionalComment = (comment) => {
|
|
6
|
+
const matches = comment.match(commentRegex);
|
|
7
|
+
if (matches) {
|
|
8
|
+
return {
|
|
9
|
+
startTag: matches[1],
|
|
10
|
+
body: matches[2].trim(),
|
|
11
|
+
endTag: matches[4],
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
exports.getConditionalComment = getConditionalComment;
|
|
16
|
+
//# sourceMappingURL=conditional-comment.js.map
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { MatchResult } from 'ohm-js';
|
|
2
|
+
import { NodeTypes, Position } from './types';
|
|
3
|
+
interface LineColPosition {
|
|
4
|
+
line: number;
|
|
5
|
+
column: number;
|
|
6
|
+
}
|
|
7
|
+
export declare class LiquidHTMLCSTParsingError extends SyntaxError {
|
|
8
|
+
loc?: {
|
|
9
|
+
start: LineColPosition;
|
|
10
|
+
end: LineColPosition;
|
|
11
|
+
};
|
|
12
|
+
constructor(ohm: MatchResult);
|
|
13
|
+
}
|
|
14
|
+
export type UnclosedNode = {
|
|
15
|
+
type: NodeTypes;
|
|
16
|
+
name: string;
|
|
17
|
+
blockStartPosition: Position;
|
|
18
|
+
};
|
|
19
|
+
export declare class LiquidHTMLASTParsingError extends SyntaxError {
|
|
20
|
+
loc?: {
|
|
21
|
+
start: LineColPosition;
|
|
22
|
+
end: LineColPosition;
|
|
23
|
+
};
|
|
24
|
+
unclosed: UnclosedNode | null;
|
|
25
|
+
constructor(message: string, source: string, startIndex: number, endIndex: number, unclosed?: UnclosedNode);
|
|
26
|
+
}
|
|
27
|
+
export {};
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LiquidHTMLASTParsingError = exports.LiquidHTMLCSTParsingError = void 0;
|
|
7
|
+
const line_column_1 = __importDefault(require("line-column"));
|
|
8
|
+
class LiquidHTMLCSTParsingError extends SyntaxError {
|
|
9
|
+
constructor(ohm) {
|
|
10
|
+
super(ohm.shortMessage);
|
|
11
|
+
this.name = 'LiquidHTMLParsingError';
|
|
12
|
+
const input = ohm.input;
|
|
13
|
+
const errorPos = ohm._rightmostFailurePosition;
|
|
14
|
+
const lineCol = (0, line_column_1.default)(input).fromIndex(Math.min(errorPos, input.length - 1));
|
|
15
|
+
// Plugging ourselves into @babel/code-frame since this is how
|
|
16
|
+
// the babel parser can print where the parsing error occured.
|
|
17
|
+
// https://github.com/prettier/prettier/blob/cd4a57b113177c105a7ceb94e71f3a5a53535b81/src/main/parser.js
|
|
18
|
+
if (lineCol) {
|
|
19
|
+
this.loc = {
|
|
20
|
+
start: {
|
|
21
|
+
line: lineCol.line,
|
|
22
|
+
column: lineCol.col,
|
|
23
|
+
},
|
|
24
|
+
end: {
|
|
25
|
+
line: lineCol.line,
|
|
26
|
+
column: lineCol.col,
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.LiquidHTMLCSTParsingError = LiquidHTMLCSTParsingError;
|
|
33
|
+
class LiquidHTMLASTParsingError extends SyntaxError {
|
|
34
|
+
constructor(message, source, startIndex, endIndex, unclosed) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = 'LiquidHTMLParsingError';
|
|
37
|
+
this.unclosed = unclosed ?? null;
|
|
38
|
+
const lc = (0, line_column_1.default)(source);
|
|
39
|
+
const start = lc.fromIndex(startIndex);
|
|
40
|
+
const end = lc.fromIndex(Math.min(endIndex, source.length - 1));
|
|
41
|
+
// Plugging ourselves into @babel/code-frame since this is how
|
|
42
|
+
// the babel parser can print where the parsing error occured.
|
|
43
|
+
// https://github.com/prettier/prettier/blob/cd4a57b113177c105a7ceb94e71f3a5a53535b81/src/main/parser.js
|
|
44
|
+
this.loc = {
|
|
45
|
+
start: {
|
|
46
|
+
line: start.line,
|
|
47
|
+
column: start.col,
|
|
48
|
+
},
|
|
49
|
+
end: {
|
|
50
|
+
line: end.line,
|
|
51
|
+
column: end.col,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.LiquidHTMLASTParsingError = LiquidHTMLASTParsingError;
|
|
57
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Grammar } from 'ohm-js';
|
|
2
|
+
export declare const liquidHtmlGrammars: import("ohm-js").Namespace;
|
|
3
|
+
export declare const TextNodeGrammar: Grammar;
|
|
4
|
+
export declare const LiquidDocGrammar: Grammar;
|
|
5
|
+
export interface LiquidGrammars {
|
|
6
|
+
Liquid: Grammar;
|
|
7
|
+
LiquidHTML: Grammar;
|
|
8
|
+
LiquidStatement: Grammar;
|
|
9
|
+
}
|
|
10
|
+
export declare const strictGrammars: LiquidGrammars;
|
|
11
|
+
export declare const tolerantGrammars: LiquidGrammars;
|
|
12
|
+
export declare const placeholderGrammars: LiquidGrammars;
|
|
13
|
+
export declare const BLOCKS: string[];
|
|
14
|
+
export declare const RAW_TAGS: string[];
|
|
15
|
+
export declare const VOID_ELEMENTS: string[];
|
|
16
|
+
export declare const TAGS_WITHOUT_MARKUP: string[];
|
package/dist/grammar.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TAGS_WITHOUT_MARKUP = exports.VOID_ELEMENTS = exports.RAW_TAGS = exports.BLOCKS = exports.placeholderGrammars = exports.tolerantGrammars = exports.strictGrammars = exports.LiquidDocGrammar = exports.TextNodeGrammar = exports.liquidHtmlGrammars = void 0;
|
|
4
|
+
const ohm_js_1 = require("ohm-js");
|
|
5
|
+
exports.liquidHtmlGrammars = (0, ohm_js_1.grammars)(require('../grammar/liquid-html.ohm.js'));
|
|
6
|
+
exports.TextNodeGrammar = exports.liquidHtmlGrammars['Helpers'];
|
|
7
|
+
exports.LiquidDocGrammar = exports.liquidHtmlGrammars['LiquidDoc'];
|
|
8
|
+
exports.strictGrammars = {
|
|
9
|
+
Liquid: exports.liquidHtmlGrammars['StrictLiquid'],
|
|
10
|
+
LiquidHTML: exports.liquidHtmlGrammars['StrictLiquidHTML'],
|
|
11
|
+
LiquidStatement: exports.liquidHtmlGrammars['StrictLiquidStatement'],
|
|
12
|
+
};
|
|
13
|
+
exports.tolerantGrammars = {
|
|
14
|
+
Liquid: exports.liquidHtmlGrammars['Liquid'],
|
|
15
|
+
LiquidHTML: exports.liquidHtmlGrammars['LiquidHTML'],
|
|
16
|
+
LiquidStatement: exports.liquidHtmlGrammars['LiquidStatement'],
|
|
17
|
+
};
|
|
18
|
+
exports.placeholderGrammars = {
|
|
19
|
+
Liquid: exports.liquidHtmlGrammars['WithPlaceholderLiquid'],
|
|
20
|
+
LiquidHTML: exports.liquidHtmlGrammars['WithPlaceholderLiquidHTML'],
|
|
21
|
+
LiquidStatement: exports.liquidHtmlGrammars['WithPlaceholderLiquidStatement'],
|
|
22
|
+
};
|
|
23
|
+
// see ../../grammar/liquid-html.ohm for full list
|
|
24
|
+
exports.BLOCKS = exports.strictGrammars.LiquidHTML.rules.blockName.body.factors[0].terms.map((x) => x.obj);
|
|
25
|
+
// see ../../grammar/liquid-html.ohm for full list
|
|
26
|
+
exports.RAW_TAGS = exports.strictGrammars.LiquidHTML.rules.liquidRawTag.body.terms
|
|
27
|
+
.map((term) => term.args[0].obj)
|
|
28
|
+
.concat('comment');
|
|
29
|
+
// see ../../grammar/liquid-html.ohm for full list
|
|
30
|
+
exports.VOID_ELEMENTS = exports.strictGrammars.LiquidHTML.rules.voidElementName.body.factors[0].terms.map((x) => x.args[0].obj);
|
|
31
|
+
exports.TAGS_WITHOUT_MARKUP = [
|
|
32
|
+
'style',
|
|
33
|
+
'schema',
|
|
34
|
+
'javascript',
|
|
35
|
+
'else',
|
|
36
|
+
'break',
|
|
37
|
+
'continue',
|
|
38
|
+
'comment',
|
|
39
|
+
'raw',
|
|
40
|
+
'doc',
|
|
41
|
+
];
|
|
42
|
+
//# sourceMappingURL=grammar.js.map
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.getConditionalComment = exports.BLOCKS = exports.VOID_ELEMENTS = exports.RAW_TAGS = exports.TAGS_WITHOUT_MARKUP = void 0;
|
|
18
|
+
__exportStar(require("./stage-2-ast"), exports);
|
|
19
|
+
__exportStar(require("./types"), exports);
|
|
20
|
+
__exportStar(require("./errors"), exports);
|
|
21
|
+
var grammar_1 = require("./grammar");
|
|
22
|
+
Object.defineProperty(exports, "TAGS_WITHOUT_MARKUP", { enumerable: true, get: function () { return grammar_1.TAGS_WITHOUT_MARKUP; } });
|
|
23
|
+
Object.defineProperty(exports, "RAW_TAGS", { enumerable: true, get: function () { return grammar_1.RAW_TAGS; } });
|
|
24
|
+
Object.defineProperty(exports, "VOID_ELEMENTS", { enumerable: true, get: function () { return grammar_1.VOID_ELEMENTS; } });
|
|
25
|
+
Object.defineProperty(exports, "BLOCKS", { enumerable: true, get: function () { return grammar_1.BLOCKS; } });
|
|
26
|
+
var conditional_comment_1 = require("./conditional-comment");
|
|
27
|
+
Object.defineProperty(exports, "getConditionalComment", { enumerable: true, get: function () { return conditional_comment_1.getConditionalComment; } });
|
|
28
|
+
//# sourceMappingURL=index.js.map
|