@salesforcedevs/sfdocs-liquid-lint-filtered-blocks 1.0.0-alpha

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.
@@ -0,0 +1,3 @@
1
+ declare const _default: any;
2
+ export = _default;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAsJA,kBAA2C"}
package/dist/index.js ADDED
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const unified_lint_rule_1 = __importDefault(require("unified-lint-rule"));
6
+ const sfdocs_liquid_lint_utils_1 = require("@salesforcedevs/sfdocs-liquid-lint-utils");
7
+ const SOURCE = 'sfdocs-liquid-lint:liquid-filtered-blocks';
8
+ function findBlockRanges(content, tagName) {
9
+ const ranges = [];
10
+ const tagRe = new RegExp(`{%-?\\s*(${tagName}|end${tagName})\\s*-?%}`, 'g');
11
+ const openStack = [];
12
+ let match;
13
+ while ((match = tagRe.exec(content)) !== null) {
14
+ if (match[1] === tagName) {
15
+ openStack.push({ index: match.index, end: match.index + match[0].length });
16
+ }
17
+ else if (openStack.length > 0) {
18
+ const open = openStack.pop();
19
+ ranges.push({
20
+ openStart: open.index,
21
+ openEnd: open.end,
22
+ closeStart: match.index,
23
+ closeEnd: match.index + match[0].length,
24
+ });
25
+ }
26
+ }
27
+ return ranges;
28
+ }
29
+ function isInsideRange(offset, ranges) {
30
+ return ranges.some(r => offset >= r.openStart && offset < r.closeEnd);
31
+ }
32
+ function isNestedBlock(blockIndex, ranges) {
33
+ const block = ranges[blockIndex];
34
+ for (let i = 0; i < ranges.length; i++) {
35
+ if (i === blockIndex)
36
+ continue;
37
+ const outer = ranges[i];
38
+ if (block.openStart > outer.openStart && block.closeEnd < outer.closeEnd) {
39
+ return true;
40
+ }
41
+ }
42
+ return false;
43
+ }
44
+ function isEntireFileWrapped(content, ranges) {
45
+ if (ranges.length !== 1)
46
+ return false;
47
+ const block = ranges[0];
48
+ const before = content.slice(0, block.openStart);
49
+ const after = content.slice(block.closeEnd);
50
+ return !/\S/.test(before) && !/\S/.test(after);
51
+ }
52
+ function findEmptySections(content, ranges) {
53
+ const lines = content.split('\n');
54
+ const headingPositions = [];
55
+ let offset = 0;
56
+ for (const line of lines) {
57
+ if (/^#{1,6}\s+\S/.test(line) && !isInsideRange(offset, ranges)) {
58
+ headingPositions.push(offset);
59
+ }
60
+ offset += line.length + 1;
61
+ }
62
+ const emptyHeadingOffsets = [];
63
+ for (let i = 0; i < headingPositions.length; i++) {
64
+ const sectionStart = headingPositions[i];
65
+ const sectionEnd = i + 1 < headingPositions.length
66
+ ? headingPositions[i + 1]
67
+ : content.length;
68
+ const headingLine = content.slice(sectionStart, content.indexOf('\n', sectionStart));
69
+ const afterHeading = content.slice(sectionStart + headingLine.length, sectionEnd);
70
+ const stripped = stripFilteredBlocks(afterHeading, ranges, sectionStart + headingLine.length);
71
+ if (!/\S/.test(stripped)) {
72
+ emptyHeadingOffsets.push(sectionStart);
73
+ }
74
+ }
75
+ return emptyHeadingOffsets;
76
+ }
77
+ function stripFilteredBlocks(section, allRanges, sectionOffset) {
78
+ let result = section;
79
+ const relevant = allRanges
80
+ .filter(r => r.openStart >= sectionOffset && r.closeEnd <= sectionOffset + section.length)
81
+ .sort((a, b) => b.openStart - a.openStart);
82
+ for (const range of relevant) {
83
+ const localStart = range.openStart - sectionOffset;
84
+ const localEnd = range.closeEnd - sectionOffset;
85
+ result = result.slice(0, localStart) + result.slice(localEnd);
86
+ }
87
+ return result;
88
+ }
89
+ function checkFilteredBlocks(_tree, file, option) {
90
+ var _a;
91
+ if (!file.path)
92
+ return;
93
+ const raw = String((_a = file.contents) !== null && _a !== void 0 ? _a : '');
94
+ if (!raw)
95
+ return;
96
+ const filterTags = option === null || option === void 0 ? void 0 : option.filterTags;
97
+ if (!filterTags || filterTags.length === 0)
98
+ return;
99
+ const content = (0, sfdocs_liquid_lint_utils_1.protectCodeBlocks)(raw);
100
+ for (const tagName of filterTags) {
101
+ const ranges = findBlockRanges(content, tagName);
102
+ if (ranges.length === 0)
103
+ continue;
104
+ for (let i = 0; i < ranges.length; i++) {
105
+ if (isNestedBlock(i, ranges)) {
106
+ const position = (0, sfdocs_liquid_lint_utils_1.offsetToPosition)(raw, ranges[i].openStart);
107
+ file.message(`Redundant nested ${tagName} block — already inside a ${tagName} block.`, position);
108
+ }
109
+ }
110
+ if (isEntireFileWrapped(content, ranges)) {
111
+ const position = (0, sfdocs_liquid_lint_utils_1.offsetToPosition)(raw, ranges[0].openStart);
112
+ file.message(`All content is inside ${tagName} block — use \`filters: [${tagName}]\` in TOC instead.`, position);
113
+ }
114
+ const emptyHeadingOffsets = findEmptySections(content, ranges);
115
+ for (const offset of emptyHeadingOffsets) {
116
+ const position = (0, sfdocs_liquid_lint_utils_1.offsetToPosition)(raw, offset);
117
+ file.message(`Heading would have no content after ${tagName} block is removed.`, position);
118
+ }
119
+ }
120
+ }
121
+ module.exports = (0, unified_lint_rule_1.default)(SOURCE, checkFilteredBlocks);
122
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAAA,0EAAqC;AAErC,uFAA+F;AAE/F,MAAM,MAAM,GAAG,2CAA2C,CAAC;AAa3D,SAAS,eAAe,CAAC,OAAe,EAAE,OAAe;IACrD,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,YAAY,OAAO,OAAO,OAAO,WAAW,EAAE,GAAG,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAqC,EAAE,CAAC;IAEvD,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE;QAC3C,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE;YACtB,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;SAC9E;aAAM,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;YAC7B,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,EAAG,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC;gBACR,SAAS,EAAE,IAAI,CAAC,KAAK;gBACrB,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,UAAU,EAAE,KAAK,CAAC,KAAK;gBACvB,QAAQ,EAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM;aAC1C,CAAC,CAAC;SACN;KACJ;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,aAAa,CAAC,MAAc,EAAE,MAAoB;IACvD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC,SAAS,IAAI,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,aAAa,CAAC,UAAkB,EAAE,MAAoB;IAC3D,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACpC,IAAI,CAAC,KAAK,UAAU;YAAE,SAAS;QAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,EAAE;YACtE,OAAO,IAAI,CAAC;SACf;KACJ;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe,EAAE,MAAoB;IAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe,EAAE,MAAoB;IAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,gBAAgB,GAAa,EAAE,CAAC;IACtC,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;QACtB,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;YAC7D,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SACjC;QACD,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;KAC7B;IAED,MAAM,mBAAmB,GAAa,EAAE,CAAC;IACzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QAC9C,MAAM,YAAY,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC,MAAM;YAC9C,CAAC,CAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;QAErB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC;QACrF,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,GAAG,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAElF,MAAM,QAAQ,GAAG,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAC9F,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;YACtB,mBAAmB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;SAC1C;KACJ;IACD,OAAO,mBAAmB,CAAC;AAC/B,CAAC;AAED,SAAS,mBAAmB,CAAC,OAAe,EAAE,SAAuB,EAAE,aAAqB;IACxF,IAAI,MAAM,GAAG,OAAO,CAAC;IACrB,MAAM,QAAQ,GAAG,SAAS;SACrB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,aAAa,IAAI,CAAC,CAAC,QAAQ,IAAI,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;SACzF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;IAE/C,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE;QAC1B,MAAM,UAAU,GAAG,KAAK,CAAC,SAAS,GAAG,aAAa,CAAC;QACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,GAAG,aAAa,CAAC;QAChD,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;KACjE;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc,EAAE,IAAW,EAAE,MAA8B;;IACpF,IAAI,CAAC,IAAI,CAAC,IAAI;QAAE,OAAO;IACvB,MAAM,GAAG,GAAG,MAAM,CAAC,MAAA,IAAI,CAAC,QAAQ,mCAAI,EAAE,CAAC,CAAC;IACxC,IAAI,CAAC,GAAG;QAAE,OAAO;IAEjB,MAAM,UAAU,GAAG,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,UAAU,CAAC;IACtC,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEnD,MAAM,OAAO,GAAG,IAAA,4CAAiB,EAAC,GAAG,CAAC,CAAC;IAEvC,KAAK,MAAM,OAAO,IAAI,UAAU,EAAE;QAC9B,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACjD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACpC,IAAI,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE;gBAC1B,MAAM,QAAQ,GAAG,IAAA,2CAAgB,EAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBAC5D,IAAI,CAAC,OAAO,CACR,oBAAoB,OAAO,6BAA6B,OAAO,SAAS,EACxE,QAAQ,CACX,CAAC;aACL;SACJ;QAED,IAAI,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE;YACtC,MAAM,QAAQ,GAAG,IAAA,2CAAgB,EAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAC5D,IAAI,CAAC,OAAO,CACR,yBAAyB,OAAO,4BAA4B,OAAO,qBAAqB,EACxF,QAAQ,CACX,CAAC;SACL;QAED,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC/D,KAAK,MAAM,MAAM,IAAI,mBAAmB,EAAE;YACtC,MAAM,QAAQ,GAAG,IAAA,2CAAgB,EAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAC/C,IAAI,CAAC,OAAO,CACR,uCAAuC,OAAO,oBAAoB,EAClE,QAAQ,CACX,CAAC;SACL;KACJ;AACL,CAAC;AAED,iBAAS,IAAA,2BAAI,EAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC"}
package/jest.config.js ADDED
@@ -0,0 +1,16 @@
1
+ const BASE_CONFIG = require('../../scripts/jest/common.config');
2
+
3
+ module.exports = {
4
+ ...BASE_CONFIG,
5
+ displayName: 'liquid-lint-filtered-blocks',
6
+ collectCoverageFrom: ['<rootDir>/**/src/*.{ts,js}'],
7
+ coveragePathIgnorePatterns: ['/node_modules/', '/dist/'],
8
+ testMatch: ['<rootDir>/**/__tests__/**/*.{test,spec}.ts'],
9
+ testPathIgnorePatterns: ['lib/', 'node_modules/'],
10
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
11
+ preset: 'ts-jest',
12
+ testEnvironment: 'node',
13
+ transform: {
14
+ '^.+\\.ts$': 'ts-jest',
15
+ },
16
+ };
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@salesforcedevs/sfdocs-liquid-lint-filtered-blocks",
3
+ "version": "1.0.0-alpha",
4
+ "description": "Validates structural issues in liquid filter blocks (englishonly, future, etc.).",
5
+ "author": "SFDocs Team",
6
+ "main": "dist/index.js",
7
+ "scripts": {
8
+ "build": "yarn compile",
9
+ "compile": "tsc -p tsconfig.json",
10
+ "prepublish": "yarn build",
11
+ "test": "jest",
12
+ "test:ci": "yarn test --maxWorkers=1 --ci --coverage",
13
+ "watch": "tsc --watch"
14
+ },
15
+ "license": "MIT",
16
+ "dependencies": {
17
+ "@salesforcedevs/sfdocs-liquid-lint-utils": "^1.0.1",
18
+ "unified-lint-rule": "^1.0.6",
19
+ "vfile": "^4.2.1"
20
+ },
21
+ "devDependencies": {
22
+ "@types/jest": "^25.2.2",
23
+ "@types/node": "^15.6.1",
24
+ "dedent": "^0.7.0",
25
+ "jest": "^29.7.0",
26
+ "remark": "^13.0.0",
27
+ "ts-jest": "^29.2.5",
28
+ "typescript": "^4.4.2",
29
+ "unified": "^9.0.0"
30
+ }
31
+ }
@@ -0,0 +1,247 @@
1
+ import dedent from 'dedent';
2
+ import remark from 'remark';
3
+ import unified from 'unified';
4
+ import vfile, { VFile } from 'vfile';
5
+
6
+ import plugin from '../index';
7
+
8
+ const PAGE_PATH = '/repo/content/en-us/project/guides/page.md';
9
+
10
+ const run = (md: string, options?: any, p = PAGE_PATH): VFile =>
11
+ remark()
12
+ .use(plugin as unified.Attacher, options)
13
+ .processSync(vfile({ path: p, contents: md }));
14
+
15
+ describe('sfdocs-lint:liquid-filtered-blocks', () => {
16
+ test('no-op when no filterTags provided', () => {
17
+ const md = dedent`
18
+ {% englishonly %}
19
+ Some content.
20
+ {% endenglishonly %}
21
+ `;
22
+ expect(run(md).messages).toHaveLength(0);
23
+ });
24
+
25
+ test('no-op when filterTags is empty array', () => {
26
+ const md = dedent`
27
+ {% englishonly %}
28
+ Some content.
29
+ {% endenglishonly %}
30
+ `;
31
+ expect(run(md, { filterTags: [] }).messages).toHaveLength(0);
32
+ });
33
+
34
+ test('no messages for valid englishonly block', () => {
35
+ const md = dedent`
36
+ # Heading
37
+
38
+ Regular content.
39
+
40
+ {% englishonly %}
41
+ English-only note here.
42
+ {% endenglishonly %}
43
+
44
+ More content after.
45
+ `;
46
+ expect(run(md, { filterTags: ['englishonly'] }).messages).toHaveLength(0);
47
+ });
48
+
49
+ test('no messages for valid future block', () => {
50
+ const md = dedent`
51
+ # Heading
52
+
53
+ Regular content.
54
+
55
+ {% future %}
56
+ Future content here.
57
+ {% endfuture %}
58
+
59
+ More content after.
60
+ `;
61
+ expect(run(md, { filterTags: ['future'] }).messages).toHaveLength(0);
62
+ });
63
+
64
+ test('warns on nested same-tag blocks (englishonly)', () => {
65
+ const md = dedent`
66
+ {% englishonly %}
67
+ Outer block.
68
+
69
+ {% englishonly %}
70
+ Inner block.
71
+ {% endenglishonly %}
72
+
73
+ {% endenglishonly %}
74
+ `;
75
+ const messages = run(md, { filterTags: ['englishonly'] }).messages;
76
+ expect(messages).toHaveLength(1);
77
+ expect(messages[0].message).toBe(
78
+ 'Redundant nested englishonly block — already inside a englishonly block.',
79
+ );
80
+ expect(messages[0].source).toBe('sfdocs-liquid-lint');
81
+ expect(messages[0].ruleId).toBe('liquid-filtered-blocks');
82
+ });
83
+
84
+ test('warns on nested same-tag blocks (future)', () => {
85
+ const md = dedent`
86
+ {% future %}
87
+ Outer.
88
+
89
+ {% future %}
90
+ Inner.
91
+ {% endfuture %}
92
+
93
+ {% endfuture %}
94
+ `;
95
+ const messages = run(md, { filterTags: ['future'] }).messages;
96
+ expect(messages).toHaveLength(1);
97
+ expect(messages[0].message).toBe(
98
+ 'Redundant nested future block — already inside a future block.',
99
+ );
100
+ });
101
+
102
+ test('does NOT warn on cross-tag nesting (englishonly inside future)', () => {
103
+ const md = dedent`
104
+ # Heading
105
+
106
+ Regular content.
107
+
108
+ {% future %}
109
+ Future content.
110
+
111
+ {% englishonly %}
112
+ English-only inside future.
113
+ {% endenglishonly %}
114
+
115
+ {% endfuture %}
116
+
117
+ More content.
118
+ `;
119
+ expect(run(md, { filterTags: ['englishonly', 'future'] }).messages).toHaveLength(0);
120
+ });
121
+
122
+ test('does NOT warn on cross-tag nesting (future inside englishonly)', () => {
123
+ const md = dedent`
124
+ # Heading
125
+
126
+ Regular content.
127
+
128
+ {% englishonly %}
129
+ English content.
130
+
131
+ {% future %}
132
+ Future inside english.
133
+ {% endfuture %}
134
+
135
+ {% endenglishonly %}
136
+
137
+ More content.
138
+ `;
139
+ expect(run(md, { filterTags: ['englishonly', 'future'] }).messages).toHaveLength(0);
140
+ });
141
+
142
+ test('warns when entire file is wrapped', () => {
143
+ const md = dedent`
144
+ {% englishonly %}
145
+ # Full Content
146
+
147
+ Everything here.
148
+ {% endenglishonly %}
149
+ `;
150
+ const messages = run(md, { filterTags: ['englishonly'] }).messages;
151
+ expect(messages).toHaveLength(1);
152
+ expect(messages[0].message).toBe(
153
+ 'All content is inside englishonly block — use `filters: [englishonly]` in TOC instead.',
154
+ );
155
+ });
156
+
157
+ test('warns on heading with only filtered content beneath it', () => {
158
+ const md = dedent`
159
+ # Main Heading
160
+
161
+ Regular content.
162
+
163
+ ## Empty Section
164
+
165
+ {% future %}
166
+ This is the only content under this heading.
167
+ {% endfuture %}
168
+
169
+ ## Another Section
170
+
171
+ More regular content.
172
+ `;
173
+ const messages = run(md, { filterTags: ['future'] }).messages;
174
+ expect(messages).toHaveLength(1);
175
+ expect(messages[0].message).toBe(
176
+ 'Heading would have no content after future block is removed.',
177
+ );
178
+ });
179
+
180
+ test('does not warn when heading has content outside filtered block', () => {
181
+ const md = dedent`
182
+ ## Section
183
+
184
+ Regular content.
185
+
186
+ {% englishonly %}
187
+ Extra english-only note.
188
+ {% endenglishonly %}
189
+ `;
190
+ expect(run(md, { filterTags: ['englishonly'] }).messages).toHaveLength(0);
191
+ });
192
+
193
+ test('handles whitespace-control syntax', () => {
194
+ const md = dedent`
195
+ {%- future -%}
196
+ {%- future -%}
197
+ Nested.
198
+ {%- endfuture -%}
199
+ {%- endfuture -%}
200
+ `;
201
+ const messages = run(md, { filterTags: ['future'] }).messages;
202
+ expect(messages).toHaveLength(1);
203
+ expect(messages[0].message).toContain('Redundant nested future block');
204
+ });
205
+
206
+ test('ignores tags inside fenced code blocks', () => {
207
+ const md = dedent`
208
+ # Guide
209
+
210
+ Regular content.
211
+
212
+ \`\`\`markdown
213
+ {% englishonly %}
214
+ Example.
215
+ {% endenglishonly %}
216
+ \`\`\`
217
+
218
+ More content.
219
+ `;
220
+ expect(run(md, { filterTags: ['englishonly'] }).messages).toHaveLength(0);
221
+ });
222
+
223
+ test('checks multiple tags independently', () => {
224
+ const md = dedent`
225
+ {% englishonly %}
226
+ # All English
227
+
228
+ Content.
229
+ {% endenglishonly %}
230
+ `;
231
+ const messages = run(md, { filterTags: ['englishonly', 'future'] }).messages;
232
+ expect(messages).toHaveLength(1);
233
+ expect(messages[0].message).toContain('englishonly');
234
+ });
235
+
236
+ test('skips empty file', () => {
237
+ expect(run('', { filterTags: ['englishonly'] }).messages).toHaveLength(0);
238
+ });
239
+
240
+ test('skips file with no path', () => {
241
+ const f = vfile({ contents: '{% englishonly %}test{% endenglishonly %}' });
242
+ const result = remark()
243
+ .use(plugin as unified.Attacher, { filterTags: ['englishonly'] })
244
+ .processSync(f);
245
+ expect(result.messages).toHaveLength(0);
246
+ });
247
+ });
package/src/index.ts ADDED
@@ -0,0 +1,151 @@
1
+ import rule from 'unified-lint-rule';
2
+ import { VFile } from 'vfile';
3
+ import { offsetToPosition, protectCodeBlocks } from '@salesforcedevs/sfdocs-liquid-lint-utils';
4
+
5
+ const SOURCE = 'sfdocs-liquid-lint:liquid-filtered-blocks';
6
+
7
+ interface FilteredBlocksOptions {
8
+ filterTags?: string[];
9
+ }
10
+
11
+ interface BlockRange {
12
+ openStart: number;
13
+ openEnd: number;
14
+ closeStart: number;
15
+ closeEnd: number;
16
+ }
17
+
18
+ function findBlockRanges(content: string, tagName: string): BlockRange[] {
19
+ const ranges: BlockRange[] = [];
20
+ const tagRe = new RegExp(`{%-?\\s*(${tagName}|end${tagName})\\s*-?%}`, 'g');
21
+ const openStack: { index: number; end: number }[] = [];
22
+
23
+ let match: RegExpExecArray | null;
24
+ while ((match = tagRe.exec(content)) !== null) {
25
+ if (match[1] === tagName) {
26
+ openStack.push({ index: match.index, end: match.index + match[0].length });
27
+ } else if (openStack.length > 0) {
28
+ const open = openStack.pop()!;
29
+ ranges.push({
30
+ openStart: open.index,
31
+ openEnd: open.end,
32
+ closeStart: match.index,
33
+ closeEnd: match.index + match[0].length,
34
+ });
35
+ }
36
+ }
37
+ return ranges;
38
+ }
39
+
40
+ function isInsideRange(offset: number, ranges: BlockRange[]): boolean {
41
+ return ranges.some(r => offset >= r.openStart && offset < r.closeEnd);
42
+ }
43
+
44
+ function isNestedBlock(blockIndex: number, ranges: BlockRange[]): boolean {
45
+ const block = ranges[blockIndex];
46
+ for (let i = 0; i < ranges.length; i++) {
47
+ if (i === blockIndex) continue;
48
+ const outer = ranges[i];
49
+ if (block.openStart > outer.openStart && block.closeEnd < outer.closeEnd) {
50
+ return true;
51
+ }
52
+ }
53
+ return false;
54
+ }
55
+
56
+ function isEntireFileWrapped(content: string, ranges: BlockRange[]): boolean {
57
+ if (ranges.length !== 1) return false;
58
+ const block = ranges[0];
59
+ const before = content.slice(0, block.openStart);
60
+ const after = content.slice(block.closeEnd);
61
+ return !/\S/.test(before) && !/\S/.test(after);
62
+ }
63
+
64
+ function findEmptySections(content: string, ranges: BlockRange[]): number[] {
65
+ const lines = content.split('\n');
66
+ const headingPositions: number[] = [];
67
+ let offset = 0;
68
+
69
+ for (const line of lines) {
70
+ if (/^#{1,6}\s+\S/.test(line) && !isInsideRange(offset, ranges)) {
71
+ headingPositions.push(offset);
72
+ }
73
+ offset += line.length + 1;
74
+ }
75
+
76
+ const emptyHeadingOffsets: number[] = [];
77
+ for (let i = 0; i < headingPositions.length; i++) {
78
+ const sectionStart = headingPositions[i];
79
+ const sectionEnd = i + 1 < headingPositions.length
80
+ ? headingPositions[i + 1]
81
+ : content.length;
82
+
83
+ const headingLine = content.slice(sectionStart, content.indexOf('\n', sectionStart));
84
+ const afterHeading = content.slice(sectionStart + headingLine.length, sectionEnd);
85
+
86
+ const stripped = stripFilteredBlocks(afterHeading, ranges, sectionStart + headingLine.length);
87
+ if (!/\S/.test(stripped)) {
88
+ emptyHeadingOffsets.push(sectionStart);
89
+ }
90
+ }
91
+ return emptyHeadingOffsets;
92
+ }
93
+
94
+ function stripFilteredBlocks(section: string, allRanges: BlockRange[], sectionOffset: number): string {
95
+ let result = section;
96
+ const relevant = allRanges
97
+ .filter(r => r.openStart >= sectionOffset && r.closeEnd <= sectionOffset + section.length)
98
+ .sort((a, b) => b.openStart - a.openStart);
99
+
100
+ for (const range of relevant) {
101
+ const localStart = range.openStart - sectionOffset;
102
+ const localEnd = range.closeEnd - sectionOffset;
103
+ result = result.slice(0, localStart) + result.slice(localEnd);
104
+ }
105
+ return result;
106
+ }
107
+
108
+ function checkFilteredBlocks(_tree: unknown, file: VFile, option?: FilteredBlocksOptions): void {
109
+ if (!file.path) return;
110
+ const raw = String(file.contents ?? '');
111
+ if (!raw) return;
112
+
113
+ const filterTags = option?.filterTags;
114
+ if (!filterTags || filterTags.length === 0) return;
115
+
116
+ const content = protectCodeBlocks(raw);
117
+
118
+ for (const tagName of filterTags) {
119
+ const ranges = findBlockRanges(content, tagName);
120
+ if (ranges.length === 0) continue;
121
+
122
+ for (let i = 0; i < ranges.length; i++) {
123
+ if (isNestedBlock(i, ranges)) {
124
+ const position = offsetToPosition(raw, ranges[i].openStart);
125
+ file.message(
126
+ `Redundant nested ${tagName} block — already inside a ${tagName} block.`,
127
+ position,
128
+ );
129
+ }
130
+ }
131
+
132
+ if (isEntireFileWrapped(content, ranges)) {
133
+ const position = offsetToPosition(raw, ranges[0].openStart);
134
+ file.message(
135
+ `All content is inside ${tagName} block — use \`filters: [${tagName}]\` in TOC instead.`,
136
+ position,
137
+ );
138
+ }
139
+
140
+ const emptyHeadingOffsets = findEmptySections(content, ranges);
141
+ for (const offset of emptyHeadingOffsets) {
142
+ const position = offsetToPosition(raw, offset);
143
+ file.message(
144
+ `Heading would have no content after ${tagName} block is removed.`,
145
+ position,
146
+ );
147
+ }
148
+ }
149
+ }
150
+
151
+ export = rule(SOURCE, checkFilteredBlocks);
package/tsconfig.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "../../tsconfig.settings.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist"
6
+ }
7
+ }
@@ -0,0 +1 @@
1
+ {"program":{"fileNames":["../../node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/typescript/lib/lib.es2015.d.ts","../../node_modules/typescript/lib/lib.es2016.d.ts","../../node_modules/typescript/lib/lib.es2017.d.ts","../../node_modules/typescript/lib/lib.es2018.d.ts","../../node_modules/typescript/lib/lib.es2019.d.ts","../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../node_modules/@types/unist/index.d.ts","../../node_modules/vfile-message/types/index.d.ts","../../node_modules/vfile/types/index.d.ts","../liquid-lint-utils/dist/parse-frontmatter.d.ts","../liquid-lint-utils/dist/check-filtered-cross-references.d.ts","../liquid-lint-utils/dist/disabled-tags.d.ts","../liquid-lint-utils/dist/is-liquid-enabled.d.ts","../liquid-lint-utils/dist/offset-to-position.d.ts","../liquid-lint-utils/dist/protect-code-blocks.d.ts","../liquid-lint-utils/dist/resolve-roots.d.ts","../liquid-lint-utils/dist/index.d.ts","./src/index.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostic_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/util/types.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/globals.global.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/ts3.6/base.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/base.d.ts","./node_modules/@types/node/index.d.ts","../../node_modules/@babel/types/lib/index.d.ts","../../node_modules/@types/babel__generator/index.d.ts","../../node_modules/@babel/parser/typings/babel-parser.d.ts","../../node_modules/@types/babel__template/index.d.ts","../../node_modules/@types/babel__traverse/index.d.ts","../../node_modules/@types/babel__core/index.d.ts","../../node_modules/keyv/src/index.d.ts","../../node_modules/@types/http-cache-semantics/index.d.ts","../../node_modules/@types/responselike/index.d.ts","../../node_modules/@types/cacheable-request/index.d.ts","../../node_modules/@types/dedent/index.d.ts","../../node_modules/@types/graceful-fs/index.d.ts","../../node_modules/@types/istanbul-lib-coverage/index.d.ts","../../node_modules/@types/istanbul-lib-report/index.d.ts","../../node_modules/@types/istanbul-reports/index.d.ts","../../node_modules/@types/jest/node_modules/jest-diff/build/cleanupsemantic.d.ts","../../node_modules/@types/jest/node_modules/jest-diff/build/types.d.ts","../../node_modules/@types/jest/node_modules/jest-diff/build/difflines.d.ts","../../node_modules/@types/jest/node_modules/jest-diff/build/printdiffs.d.ts","../../node_modules/@types/jest/node_modules/jest-diff/build/index.d.ts","../../node_modules/@types/jest/node_modules/pretty-format/build/types.d.ts","../../node_modules/@types/jest/node_modules/pretty-format/build/index.d.ts","../../node_modules/@types/jest/index.d.ts","../../node_modules/@types/jest/ts3.2/index.d.ts","../../node_modules/@types/js-yaml/index.d.ts","../../node_modules/@types/json-schema/index.d.ts","../../node_modules/@types/jsonpath-plus/index.d.ts","../../node_modules/@types/keyv/index.d.ts","../../node_modules/@types/mdast/index.d.ts","../../node_modules/@types/minimatch/index.d.ts","../../node_modules/@types/minimist/index.d.ts","../../node_modules/@types/mock-fs/lib/item.d.ts","../../node_modules/@types/mock-fs/lib/file.d.ts","../../node_modules/@types/mock-fs/lib/directory.d.ts","../../node_modules/@types/mock-fs/lib/symlink.d.ts","../../node_modules/@types/mock-fs/lib/filesystem.d.ts","../../node_modules/@types/mock-fs/index.d.ts","../../node_modules/@types/normalize-package-data/index.d.ts","../../node_modules/@types/prettier/index.d.ts","../../node_modules/@types/stack-utils/index.d.ts","../../node_modules/@types/yargs-parser/index.d.ts","../../node_modules/@types/yargs/index.d.ts","../../../node_modules/@types/mute-stream/index.d.ts","../../../node_modules/@types/wrap-ansi/index.d.ts"],"fileInfos":[{"version":"8730f4bf322026ff5229336391a18bcaa1f94d4f82416c8b2f3954e2ccaae2ba","affectsGlobalScope":true},"dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6","7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467","8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9","5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06","4b421cbfb3a38a27c279dec1e9112c3d1da296f77a1a85ddadf7e7a425d45d18",{"version":"adb996790133eb33b33aadb9c09f15c2c575e71fb57a62de8bf74dbf59ec7dfb","affectsGlobalScope":true},{"version":"8cc8c5a3bac513368b0157f3d8b31cfdcfe78b56d3724f30f80ed9715e404af8","affectsGlobalScope":true},{"version":"cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a","affectsGlobalScope":true},{"version":"c5c05907c02476e4bde6b7e76a79ffcd948aedd14b6a8f56e4674221b0417398","affectsGlobalScope":true},{"version":"5f406584aef28a331c36523df688ca3650288d14f39c5d2e555c95f0d2ff8f6f","affectsGlobalScope":true},{"version":"22f230e544b35349cfb3bd9110b6ef37b41c6d6c43c3314a31bd0d9652fcec72","affectsGlobalScope":true},{"version":"7ea0b55f6b315cf9ac2ad622b0a7813315bb6e97bf4bb3fbf8f8affbca7dc695","affectsGlobalScope":true},{"version":"3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93","affectsGlobalScope":true},{"version":"eb26de841c52236d8222f87e9e6a235332e0788af8c87a71e9e210314300410a","affectsGlobalScope":true},{"version":"3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006","affectsGlobalScope":true},{"version":"17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a","affectsGlobalScope":true},{"version":"7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98","affectsGlobalScope":true},{"version":"6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577","affectsGlobalScope":true},{"version":"81cac4cbc92c0c839c70f8ffb94eb61e2d32dc1c3cf6d95844ca099463cf37ea","affectsGlobalScope":true},{"version":"b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e","affectsGlobalScope":true},{"version":"0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a","affectsGlobalScope":true},{"version":"da233fc1c8a377ba9e0bed690a73c290d843c2c3d23a7bd7ec5cd3d7d73ba1e0","affectsGlobalScope":true},{"version":"d154ea5bb7f7f9001ed9153e876b2d5b8f5c2bb9ec02b3ae0d239ec769f1f2ae","affectsGlobalScope":true},{"version":"bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c","affectsGlobalScope":true},{"version":"c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8","affectsGlobalScope":true},{"version":"9d57b2b5d15838ed094aa9ff1299eecef40b190722eb619bac4616657a05f951","affectsGlobalScope":true},{"version":"6c51b5dd26a2c31dbf37f00cfc32b2aa6a92e19c995aefb5b97a3a64f1ac99de","affectsGlobalScope":true},{"version":"6e7997ef61de3132e4d4b2250e75343f487903ddf5370e7ce33cf1b9db9a63ed","affectsGlobalScope":true},{"version":"2ad234885a4240522efccd77de6c7d99eecf9b4de0914adb9a35c0c22433f993","affectsGlobalScope":true},{"version":"5e5e095c4470c8bab227dbbc61374878ecead104c74ab9960d3adcccfee23205","affectsGlobalScope":true},{"version":"09aa50414b80c023553090e2f53827f007a301bc34b0495bfb2c3c08ab9ad1eb","affectsGlobalScope":true},{"version":"2768ef564cfc0689a1b76106c421a2909bdff0acbe87da010785adab80efdd5c","affectsGlobalScope":true},{"version":"52d1bb7ab7a3306fd0375c8bff560feed26ed676a5b0457fa8027b563aecb9a4","affectsGlobalScope":true},"6d09838b65c3c780513878793fc394ae29b8595d9e4729246d14ce69abc71140","eb09cf44043f7d6e0208dca6f0555207015e91fff5ff77b9c21d63672f7d68d5","bbf6f246061b92bb84241897eebfcdb9ce28444ab6acbc32c425388dd27c1011","55fb7da9a36a3d45502aa14b33c55e4f3baa96567978c189a7d6e4dbbfe6cd2d","7b60a10987d3733d2652c5509808f81229ed271bb010a37a6b355c4a7da86eda","36300e1494e25976af66784b85d7bf45afd4d5c71162db0350a603ae0e9e20c8","d4ffd5feb926ecddba6ff81487d9c7d6f4c759620f5145ceea6189671b6fe25d","a08c13d8c556d1c14bcd59d91e87b7e4693979db65c600ff33a069d4aa2df53e","3078a8fa4448f802b3a522b8170be54b14bf3563ac8904504a3304777b1540ff","9860ced5ed4a2a5cd4b994721d82efdf0ec1ae8b6c722a7aa95b0087ac3732aa","5543872bc4277066c5bb6d2ad9f276f44990432be5748234be70b875e5d734cb",{"version":"a9143aa9415bb4b6938ede73c35527f8e9d753edc6cda05d6183f1cddc6f13c7","signature":"5e9d9d2e7b23697c2870a91d308db582f4cf6c6f6113cec425f7ff190a24f120"},"c7bdc99177a2a94d25fb13722adaaf5b3291bf70b4d1b27584ba189dd3889ba3",{"version":"d1c92b66c4105659fcad4eb76a1481f7311033e117d0678a1ec545e8ddb8d4c6","affectsGlobalScope":true},"e23424b97418eca3226fd24de079f1203eb70360622e4e093af2aff14d4be6ec","dee93c07b4df5e26010dc9ec4cdf4d6e4076bb4474d2a8371529217c8b2740a4","ed40f2f184db052dc8df62d1f199823c8bbccc487c0a2a7c54eeea0badcf4378","04eaa93bd75f937f9184dcb95a7983800c5770cf8ddd8ac0f3734dc02f5b20ef",{"version":"c8155caf28fc7b0a564156a5df28ad8a844a3bd32d331d148d8f3ce88025c870","affectsGlobalScope":true},"45ac321f2e15d268fd74a90ddaa6467dcaaff2c5b13f95b4b85831520fb7a491","dfc747ab8dd5f623055a4c26fd35e8cceca869fd3f1cf09701c941ca3679665a","c9f5f2920ff61d7158417b8440d5181ddc34a3dfef811a5677dd8a9fb91471e9","5cc0a492da3602510b8f5ed1852b1e0390002780d8758fbc8c0cd023ca7085f8","ec7dafafe751a5121f8f1c80201ebe7e7238c47e6329280a73c4d1ca4bb7fa28","64debeb10e4b7ae4ec9e89bfb4e04c6101ab98c3cc806d14e5488607cfec2753",{"version":"2866a528b2708aa272ec3eaafd3c980abb23aec1ef831cfc5eb2186b98c37ce5","affectsGlobalScope":true},{"version":"a5782d6cea81fe43d2db7ed41e789458c933ab3ab60602f7b5b14c4da3370496","affectsGlobalScope":true},"f258ba66915f0196ec344bc53afe1888240bbcc855ebd151b6cc072275533319","6194335ee3353f7226ba31f31d6301d0c6be87228419c0a08976ccd9d4f1213e","3ac12a54cfaa84683506db8d4cf779135a271d9f0ec18930cf53e61fbeea0c5d","cf3d3b087d1a8a3355eec47d206162c75e912315b9b5c1cd49fda93e948fb80a","36f316c066c4a72dd6f19fec49a074f935744fc9ccbe75c87ebc07fb2feb9062","42176966283d3835c34278b9b5c0f470d484c0c0c6a55c20a2c916a1ce69b6e8","0cff7901aedfe78e314f7d44088f07e2afa1b6e4f0473a4169b8456ca2fb245d","ec70fd6f8a9a83f850dab2960a6789e93d5b034b354a16814cad5daabf62a360","e2236264a811ed1d09a2487a433e8f5216ae62378cf233954ae220cf886f6717","3ec1e108d587a5661ec790db607f482605ba9f3830e118ce578e3ffa3c42e22b","100b3bb9d39d2b1b5340f1bf45a52e94ef1692b45232b4ba00fac5c3cc56d331",{"version":"04fe7e7d8008887943260af1fde2bfd4877e0dc57bf634e0f0b2f3d1794dfd11","affectsGlobalScope":true},"7f77304372efe3c9967e5f9ea2061f1b4bf41dc3cda3c83cdd676f2e5af6b7e6","992c6f6be16c0a1d2eec13ece33adeea2c747ba27fcd078353a8f4bb5b4fea58","2597718d91e306949d89e285bf34c44192014ef541c3bd7cbb825c022749e974","a6b0abdb67d63ebe964ba5fee31bc3daf10c12eecd46b24d778426010c04c67e","ac4801ebc2355ba32329070123b1cd15891bf71b41dcaf9e75b4744832126a59","fd2298fba0640e7295e7bd545e2dfbfcccbb00c27019e501c87965a02bbdebf6","4fd3c4debadce3e9ab9dec3eb45f7f5e2e3d4ad65cf975a6d938d883cfb25a50","71ddd49185b68f27bfac127ef5d22cb2672c278e53e5370d9020ef50ca9c377d","b1ea7a6eaa7608e0e0529aebd323b526a79c6c05a4e519ae5c779675004dcdf1","9fcb033a6208485d8f3fadde31eb5cbcaf99149cff3e40c0dc53ebc6d0dff4e9","7df562288f949945cf69c21cd912100c2afedeeb7cdb219085f7f4b46cb7dde4","9d16690485ff1eb4f6fc57aebe237728fd8e03130c460919da3a35f4d9bd97f5","dcc6910d95a3625fd2b0487fda055988e46ab46c357a1b3618c27b4a8dd739c9","f4149f1aa299474c7040a35fe8f8ac2ad078cc1b190415adc1fff3ed52d490ea","3730099ed008776216268a97771de31753ef71e0a7d0ec650f588cba2a06ce44","8d649dbc429d7139a1d9a14ea2bf8af1dc089e0a879447539587463d4b6c248c","60c9e27816ec8ac8df7240598bb086e95b47edfb454c5cbf4003c812e0ed6e39","e361aecf17fc4034b4c122a1564471cdcd22ef3a51407803cb5a5fc020c04d02","4926467de88a92a4fc9971d8c6f21b91eca1c0e7fc2a46cc4638ab9440c73875",{"version":"2708349d5a11a5c2e5f3a0765259ebe7ee00cdcc8161cb9990cb4910328442a1","affectsGlobalScope":true},"fc0ae4a8ad3c762b96f9d2c3700cb879a373458cb0bf3175478e3b4f85f7ef2f","fabbec378e1ddd86fcf2662e716c2b8318acedb664ee3a4cba6f9e8ee8269cf1","b3593bd345ebea5e4d0a894c03251a3774b34df3d6db57075c18e089a599ba76","e61a21e9418f279bc480394a94d1581b2dee73747adcbdef999b6737e34d721b","efd55e8ca79171bf26c0d0e30221cb8ee1f5a31dd0c791ec4b2e886f42bab124","c2c2a861a338244d7dd700d0c52a78916b4bb75b98fc8ca5e7c501899fc03796","b6d03c9cfe2cf0ba4c673c209fcd7c46c815b2619fd2aad59fc4229aaef2ed43","adb467429462e3891de5bb4a82a4189b92005d61c7f9367c089baf03997c104e","670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","13b77ab19ef7aadd86a1e54f2f08ea23a6d74e102909e3c00d31f231ed040f62","069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9","42baf4ca38c38deaf411ea73f37bc39ff56c6e5c761a968b64ac1b25c92b5cd8","d7dbe0ad36bdca8a6ecf143422a48e72cc8927bab7b23a1a2485c2f78a7022c6","8718fa41d7cf4aa91de4e8f164c90f88e0bf343aa92a1b9b725a9c675c64e16b","f992cd6cc0bcbaa4e6c810468c90f2d8595f8c6c3cf050c806397d3de8585562","3189093b3543e545bcf0e6d387d60c5cfe5a224b104d15b1639c0c4db9ecf012","afe73051ff6a03a9565cbd8ebb0e956ee3df5e913ad5c1ded64218aabfa3dcb5","035a5df183489c2e22f3cf59fc1ed2b043d27f357eecc0eb8d8e840059d44245","a4809f4d92317535e6b22b01019437030077a76fec1d93b9881c9ed4738fcc54","5f53fa0bd22096d2a78533f94e02c899143b8f0f9891a46965294ee8b91a9434","e222104af6cb9415238ad358488b74d76eceeff238c1268ec6e85655b05341da","69da61a7b5093dac77fa3bec8be95dcf9a74c95a0e9161edb98bb24e30e439d2","eba230221317c985ab1953ccc3edc517f248b37db4fef7875cb2c8d08aff7be7","b83e796810e475da3564c6515bc0ae9577070596a33d89299b7d99f94ecfd921","b4439890c168d646357928431100daac5cbdee1d345a34e6bf6eca9f3abe22bc","5d72971a459517c44c1379dab9ed248e87a61ba0a1e0f25c9d67e1e640cd9a09","02d734976af36f4273d930bea88b3e62adf6b078cf120c1c63d49aa8d8427c5c",{"version":"f624e578325b8c58e55b30c998b1f4c3ec1b61a9fa66373da4250c89b7880d44","affectsGlobalScope":true},{"version":"d3002f620eab4bf6476c9da5c0efb2041d46f7df8b3032a5631bd206abef2c75","affectsGlobalScope":true},"7a1dd1e9c8bf5e23129495b10718b280340c7500570e0cfe5cffcdee51e13e48","f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","9bd81cfc874a2d896326e6d9e7a6963677389a8269b1d032663083b253e21162","fec943fdb3275eb6e006b35e04a8e2e99e9adf3f4b969ddf15315ac7575a93e4","202f8582ee3cd89e06c4a17d8aabb925ff8550370559c771d1cc3ec3934071c2","8841e2aa774b89bd23302dede20663306dc1b9902431ac64b24be8b8d0e3f649","fbca5ffaebf282ec3cdac47b0d1d4a138a8b0bb32105251a38acb235087d3318","b95f2a78de34a873c6dd76dc538b7a5fec77da6a0e0e7efc7aa58f58ddfce270","4b50f58fcf29daaeab0c583da58ee9731a4d5c003f99fd833d91ad99f19a82c3","6692416887d66b903aea54b32163d34318300772cd2b8c7c36f972937a62de74","3e640a0056177a4ccfb819d81b21c9ed0ac0e77d8b7bf580894a3392298a890b","b75cb207f8dfade4120ba3554c5781005c9de85723c76588befd47693342ca50","693c4c9acf5e1c56e30130a90e07bd05122e6194d69018b0b20c6581c1324e0a","22293bd6fa12747929f8dfca3ec1684a3fe08638aa18023dd286ab337e88a592","d88a5e779faf033be3d52142a04fbe1cb96009868e3bbdd296b2bc6c59e06c0e","ab82804a14454734010dcdcd43f564ff7b0389bee4c5692eec76ff5b30d4cf66","bae8d023ef6b23df7da26f51cea44321f95817c190342a36882e93b80d07a960","ae271d475b632ce7b03fea6d9cf6da72439e57a109672671cbc79f54e1386938","dcefc29f25daf56cd69c0a3d3d19f51938efe1e6a15391950be43a76222ee3ed","24112d1a55250f4da7f9edb9dabeac8e3badebdf4a55b421fc7b8ca5ccc03133"],"options":{"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"experimentalDecorators":true,"module":1,"noUnusedLocals":true,"outDir":"./dist","rootDir":"./src","skipLibCheck":true,"sourceMap":true,"strict":false,"target":6},"fileIdsList":[[78,98],[99],[99,100,101,102,103],[99,101],[61,64,86,98,105,106,107],[62,98],[111],[112],[118,120],[114,115],[114,115,116,117],[119],[121],[61,98],[35],[131,132,133,134],[130],[98,130],[130,131,132,133],[64,78,98],[139],[61],[35,36],[96],[95,96],[50,55],[61,62,69,78],[51,61,69],[87],[55,62,70],[78,83],[58,61,69],[59],[58],[61,63,78,86],[61,62,78],[69,78,86],[61,62,64,69,78,83,86],[64,78,83,86],[97],[86],[58,61,78],[71],[49],[85],[76,87,90],[61,79],[78],[81],[55,69],[47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94],[69],[75],[88],[50,55,61,63,72,78,86,90],[37,45],[37],[38,39,40,41,42,43,44]],"referencedMap":[[141,1],[101,2],[104,3],[100,2],[102,4],[103,2],[108,5],[110,6],[112,7],[113,8],[121,9],[116,10],[118,11],[117,10],[120,12],[122,13],[126,14],[127,15],[135,16],[132,17],[131,18],[134,19],[133,17],[107,20],[140,21],[105,22],[36,15],[37,23],[47,24],[97,25],[50,26],[51,27],[52,28],[53,29],[54,30],[55,31],[56,32],[58,33],[59,34],[60,22],[61,22],[62,35],[63,36],[64,37],[65,38],[66,39],[98,40],[67,22],[68,41],[69,42],[71,43],[72,44],[73,45],[76,22],[77,46],[78,47],[79,48],[81,22],[82,49],[83,50],[95,51],[85,52],[86,53],[87,54],[89,48],[91,55],[92,48],[46,56],[39,57],[45,58]],"exportedModulesMap":[[141,1],[101,2],[104,3],[100,2],[102,4],[103,2],[108,5],[110,6],[112,7],[113,8],[121,9],[116,10],[118,11],[117,10],[120,12],[122,13],[126,14],[127,15],[135,16],[132,17],[131,18],[134,19],[133,17],[107,20],[140,21],[105,22],[36,15],[37,23],[47,24],[97,25],[50,26],[51,27],[52,28],[53,29],[54,30],[55,31],[56,32],[58,33],[59,34],[60,22],[61,22],[62,35],[63,36],[64,37],[65,38],[66,39],[98,40],[67,22],[68,41],[69,42],[71,43],[72,44],[73,45],[76,22],[77,46],[78,47],[79,48],[81,22],[82,49],[83,50],[95,51],[85,52],[86,53],[87,54],[89,48],[91,55],[92,48],[39,57],[45,58]],"semanticDiagnosticsPerFile":[141,142,101,99,104,100,102,103,108,109,110,106,111,112,113,121,114,116,118,117,115,120,119,122,123,124,125,126,127,128,129,135,132,131,134,130,133,136,137,107,138,35,139,140,105,8,7,2,9,10,11,12,13,14,15,16,3,4,20,17,18,19,21,22,23,5,24,25,26,27,6,31,28,29,30,32,33,1,34,36,37,96,47,49,97,50,51,52,53,54,55,56,57,58,59,60,61,62,63,48,93,64,65,66,98,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,95,85,86,87,88,89,90,94,91,92,46,39,40,45,41,42,38,43,44],"latestChangedDtsFile":"./dist/index.d.ts"},"version":"4.9.5"}