@formfeed/engine 0.3.9 → 0.3.11
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/index.cjs +2471 -354
- package/index.js +2471 -354
- package/package.json +1 -1
- package/types/frame/fit.d.cts +13 -0
- package/types/frame/fit.d.ts +13 -0
- package/types/frame/fit.entry.d.cts +1 -0
- package/types/frame/fit.entry.d.ts +1 -0
- package/types/frame/stage.d.cts +22 -0
- package/types/frame/stage.d.ts +22 -0
- package/types/frame/stage.entry.d.cts +1 -0
- package/types/frame/stage.entry.d.ts +1 -0
- package/types/frame/text-edit.d.cts +75 -0
- package/types/frame/text-edit.d.ts +75 -0
- package/types/frame/text-edit.entry.d.cts +1 -0
- package/types/frame/text-edit.entry.d.ts +1 -0
- package/types/index.d.cts +21 -14
- package/types/index.d.ts +21 -14
- package/types/lib/assemble.d.cts +5 -0
- package/types/lib/assemble.d.ts +5 -0
- package/types/lib/design/emit.d.cts +20 -0
- package/types/lib/design/emit.d.ts +20 -0
- package/types/lib/design/fonts.d.cts +27 -0
- package/types/lib/design/fonts.d.ts +27 -0
- package/types/lib/design/hash.d.cts +6 -0
- package/types/lib/design/hash.d.ts +6 -0
- package/types/lib/design/index.d.cts +12 -0
- package/types/lib/design/index.d.ts +12 -0
- package/types/lib/design/layers.d.cts +12 -0
- package/types/lib/design/layers.d.ts +12 -0
- package/types/lib/design/parse.d.cts +25 -0
- package/types/lib/design/parse.d.ts +25 -0
- package/types/lib/design/starters.d.cts +14 -0
- package/types/lib/design/starters.d.ts +14 -0
- package/types/lib/design/types.d.cts +171 -0
- package/types/lib/design/types.d.ts +171 -0
- package/types/lib/dialect.d.cts +32 -0
- package/types/lib/dialect.d.ts +32 -0
- package/types/lib/generated/frames.d.cts +6 -0
- package/types/lib/generated/frames.d.ts +6 -0
- package/types/lib/preview.d.cts +16 -2
- package/types/lib/preview.d.ts +16 -2
- package/types/lib/source-edit.d.cts +112 -0
- package/types/lib/source-edit.d.ts +112 -0
- package/types/lib/source-positions.d.cts +12 -3
- package/types/lib/source-positions.d.ts +12 -3
- package/types/lib/source-scan.d.cts +61 -0
- package/types/lib/source-scan.d.ts +61 -0
- package/types/lib/translation.d.cts +17 -0
- package/types/lib/translation.d.ts +17 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { EngineId } from './types.cjs';
|
|
2
|
+
/**
|
|
3
|
+
* Editing text from the preview (plan 16 §3). An element whose content is literal text, output tags,
|
|
4
|
+
* inline children and line breaks — nothing that decides what is printed — is an *editable region*:
|
|
5
|
+
* the preview shows its text editable and everything else as atomic chips, and the edit comes back
|
|
6
|
+
* here to be written into the source. Text the user did not change keeps its source bytes, so
|
|
7
|
+
* indentation, line breaks and character references survive a one-word edit; changed text is
|
|
8
|
+
* HTML-escaped, and a `{` that could open template syntax is written as `{`. Every result is
|
|
9
|
+
* parsed again and compared with what the user typed before it is returned.
|
|
10
|
+
*/
|
|
11
|
+
export type RegionRefusal = 'not-an-element' | 'dynamic-tag' | 'void' | 'raw-text' | 'control-flow' | 'block-child' | 'unclosed' | 'no-text' | 'too-large';
|
|
12
|
+
export type ChipKind = 'expression' | 'element' | 'comment' | 'entity';
|
|
13
|
+
export type RegionPart = {
|
|
14
|
+
kind: 'text';
|
|
15
|
+
start: number;
|
|
16
|
+
end: number;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'break';
|
|
19
|
+
start: number;
|
|
20
|
+
end: number;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'chip';
|
|
23
|
+
start: number;
|
|
24
|
+
end: number;
|
|
25
|
+
chip: ChipKind;
|
|
26
|
+
label: string;
|
|
27
|
+
inner?: string;
|
|
28
|
+
};
|
|
29
|
+
export interface EditableRegion {
|
|
30
|
+
/** `t`: the whole content is one `t()` call, and the edit goes into the dictionary. */
|
|
31
|
+
kind: 'text' | 't';
|
|
32
|
+
tag: string;
|
|
33
|
+
/** Offset of the start tag's `<`. */
|
|
34
|
+
tagStart: number;
|
|
35
|
+
/** First character of the content, and the `<` of the end tag. */
|
|
36
|
+
start: number;
|
|
37
|
+
end: number;
|
|
38
|
+
/** After the end tag's `>`. */
|
|
39
|
+
outerEnd: number;
|
|
40
|
+
parts: RegionPart[];
|
|
41
|
+
/** `t` regions: the dictionary key and each parameter's expression by name. */
|
|
42
|
+
key?: string;
|
|
43
|
+
params?: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
/** What the preview shows and sends back: text, a chip by its index among the region's chips, a line break. */
|
|
46
|
+
export type EditItem = {
|
|
47
|
+
kind: 'text';
|
|
48
|
+
text: string;
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'chip';
|
|
51
|
+
index: number;
|
|
52
|
+
} | {
|
|
53
|
+
kind: 'break';
|
|
54
|
+
};
|
|
55
|
+
export interface RegionChip {
|
|
56
|
+
index: number;
|
|
57
|
+
kind: ChipKind;
|
|
58
|
+
/** What the chip stands for: the expression, `<strong>`, a character reference. */
|
|
59
|
+
label: string;
|
|
60
|
+
source: string;
|
|
61
|
+
}
|
|
62
|
+
export type ApplyResult = {
|
|
63
|
+
source: string;
|
|
64
|
+
} | {
|
|
65
|
+
error: 'chips' | 'invalid';
|
|
66
|
+
};
|
|
67
|
+
/** A region, or why the element at that place is none. */
|
|
68
|
+
export type RegionLookup = EditableRegion | {
|
|
69
|
+
reason: RegionRefusal;
|
|
70
|
+
};
|
|
71
|
+
/** The region whose start tag's `<` is at `line`/`column` (1-based, as `data-ff-src` names it). */
|
|
72
|
+
export declare function editableRegion(source: string, engine: EngineId, location: {
|
|
73
|
+
line: number;
|
|
74
|
+
column: number;
|
|
75
|
+
}): RegionLookup;
|
|
76
|
+
/** The region whose start tag's `<` is at `at`. */
|
|
77
|
+
export declare function editableRegionAt(source: string, engine: EngineId, at: number): RegionLookup;
|
|
78
|
+
/**
|
|
79
|
+
* The region again after the source changed around it (someone typed in the code editor while the
|
|
80
|
+
* preview was being edited): found by its unique original markup, or null.
|
|
81
|
+
*/
|
|
82
|
+
export declare function findRegionAgain(source: string, engine: EngineId, outer: string): EditableRegion | null;
|
|
83
|
+
/** The chips of a region in order, with what they stand for. */
|
|
84
|
+
export declare function regionChips(source: string, region: EditableRegion): RegionChip[];
|
|
85
|
+
/** What the preview shows while editing: decoded text (whitespace as written), chips and breaks. */
|
|
86
|
+
export declare function regionItems(source: string, region: EditableRegion): EditItem[];
|
|
87
|
+
/**
|
|
88
|
+
* Writes edited items back into the region. Chips may be deleted, never reordered or repeated. Text
|
|
89
|
+
* between the same two chips is diffed against what it was, so only the changed stretch is
|
|
90
|
+
* rewritten; if the result does not read back as the items (a kept `{` meeting a typed `%`), the
|
|
91
|
+
* whole content is written anew with every brace escaped.
|
|
92
|
+
*/
|
|
93
|
+
export declare function applyRegionEdit(source: string, engine: EngineId, region: EditableRegion, items: EditItem[]): ApplyResult;
|
|
94
|
+
/** A dictionary text as items: `{name}` placeholders become chips, in order of appearance. */
|
|
95
|
+
export declare function translationItems(text: string): {
|
|
96
|
+
items: EditItem[];
|
|
97
|
+
names: string[];
|
|
98
|
+
};
|
|
99
|
+
/** Edited dictionary items back into text: chips become their placeholders again, breaks spaces. */
|
|
100
|
+
export declare function translationText(items: EditItem[], names: string[]): string;
|
|
101
|
+
/**
|
|
102
|
+
* The value each chip shows while editing, read off the element's rendered text: the text between
|
|
103
|
+
* the chips must appear in it in order, and exactly one way of placing them must exist. Null when
|
|
104
|
+
* there is none or more than one (an empty value, a value that repeats a literal): the chips then
|
|
105
|
+
* show their labels.
|
|
106
|
+
*/
|
|
107
|
+
export declare function chipValues(rendered: string, items: EditItem[]): string[] | null;
|
|
108
|
+
/**
|
|
109
|
+
* Literal text for a template's HTML, as the design emitter writes it: escaped like an edit from the
|
|
110
|
+
* preview, so a `{` that could open template syntax is written as `{`.
|
|
111
|
+
*/
|
|
112
|
+
export declare function encodeTemplateText(text: string): string;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { EngineId } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Editing text from the preview (plan 16 §3). An element whose content is literal text, output tags,
|
|
4
|
+
* inline children and line breaks — nothing that decides what is printed — is an *editable region*:
|
|
5
|
+
* the preview shows its text editable and everything else as atomic chips, and the edit comes back
|
|
6
|
+
* here to be written into the source. Text the user did not change keeps its source bytes, so
|
|
7
|
+
* indentation, line breaks and character references survive a one-word edit; changed text is
|
|
8
|
+
* HTML-escaped, and a `{` that could open template syntax is written as `{`. Every result is
|
|
9
|
+
* parsed again and compared with what the user typed before it is returned.
|
|
10
|
+
*/
|
|
11
|
+
export type RegionRefusal = 'not-an-element' | 'dynamic-tag' | 'void' | 'raw-text' | 'control-flow' | 'block-child' | 'unclosed' | 'no-text' | 'too-large';
|
|
12
|
+
export type ChipKind = 'expression' | 'element' | 'comment' | 'entity';
|
|
13
|
+
export type RegionPart = {
|
|
14
|
+
kind: 'text';
|
|
15
|
+
start: number;
|
|
16
|
+
end: number;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'break';
|
|
19
|
+
start: number;
|
|
20
|
+
end: number;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'chip';
|
|
23
|
+
start: number;
|
|
24
|
+
end: number;
|
|
25
|
+
chip: ChipKind;
|
|
26
|
+
label: string;
|
|
27
|
+
inner?: string;
|
|
28
|
+
};
|
|
29
|
+
export interface EditableRegion {
|
|
30
|
+
/** `t`: the whole content is one `t()` call, and the edit goes into the dictionary. */
|
|
31
|
+
kind: 'text' | 't';
|
|
32
|
+
tag: string;
|
|
33
|
+
/** Offset of the start tag's `<`. */
|
|
34
|
+
tagStart: number;
|
|
35
|
+
/** First character of the content, and the `<` of the end tag. */
|
|
36
|
+
start: number;
|
|
37
|
+
end: number;
|
|
38
|
+
/** After the end tag's `>`. */
|
|
39
|
+
outerEnd: number;
|
|
40
|
+
parts: RegionPart[];
|
|
41
|
+
/** `t` regions: the dictionary key and each parameter's expression by name. */
|
|
42
|
+
key?: string;
|
|
43
|
+
params?: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
/** What the preview shows and sends back: text, a chip by its index among the region's chips, a line break. */
|
|
46
|
+
export type EditItem = {
|
|
47
|
+
kind: 'text';
|
|
48
|
+
text: string;
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'chip';
|
|
51
|
+
index: number;
|
|
52
|
+
} | {
|
|
53
|
+
kind: 'break';
|
|
54
|
+
};
|
|
55
|
+
export interface RegionChip {
|
|
56
|
+
index: number;
|
|
57
|
+
kind: ChipKind;
|
|
58
|
+
/** What the chip stands for: the expression, `<strong>`, a character reference. */
|
|
59
|
+
label: string;
|
|
60
|
+
source: string;
|
|
61
|
+
}
|
|
62
|
+
export type ApplyResult = {
|
|
63
|
+
source: string;
|
|
64
|
+
} | {
|
|
65
|
+
error: 'chips' | 'invalid';
|
|
66
|
+
};
|
|
67
|
+
/** A region, or why the element at that place is none. */
|
|
68
|
+
export type RegionLookup = EditableRegion | {
|
|
69
|
+
reason: RegionRefusal;
|
|
70
|
+
};
|
|
71
|
+
/** The region whose start tag's `<` is at `line`/`column` (1-based, as `data-ff-src` names it). */
|
|
72
|
+
export declare function editableRegion(source: string, engine: EngineId, location: {
|
|
73
|
+
line: number;
|
|
74
|
+
column: number;
|
|
75
|
+
}): RegionLookup;
|
|
76
|
+
/** The region whose start tag's `<` is at `at`. */
|
|
77
|
+
export declare function editableRegionAt(source: string, engine: EngineId, at: number): RegionLookup;
|
|
78
|
+
/**
|
|
79
|
+
* The region again after the source changed around it (someone typed in the code editor while the
|
|
80
|
+
* preview was being edited): found by its unique original markup, or null.
|
|
81
|
+
*/
|
|
82
|
+
export declare function findRegionAgain(source: string, engine: EngineId, outer: string): EditableRegion | null;
|
|
83
|
+
/** The chips of a region in order, with what they stand for. */
|
|
84
|
+
export declare function regionChips(source: string, region: EditableRegion): RegionChip[];
|
|
85
|
+
/** What the preview shows while editing: decoded text (whitespace as written), chips and breaks. */
|
|
86
|
+
export declare function regionItems(source: string, region: EditableRegion): EditItem[];
|
|
87
|
+
/**
|
|
88
|
+
* Writes edited items back into the region. Chips may be deleted, never reordered or repeated. Text
|
|
89
|
+
* between the same two chips is diffed against what it was, so only the changed stretch is
|
|
90
|
+
* rewritten; if the result does not read back as the items (a kept `{` meeting a typed `%`), the
|
|
91
|
+
* whole content is written anew with every brace escaped.
|
|
92
|
+
*/
|
|
93
|
+
export declare function applyRegionEdit(source: string, engine: EngineId, region: EditableRegion, items: EditItem[]): ApplyResult;
|
|
94
|
+
/** A dictionary text as items: `{name}` placeholders become chips, in order of appearance. */
|
|
95
|
+
export declare function translationItems(text: string): {
|
|
96
|
+
items: EditItem[];
|
|
97
|
+
names: string[];
|
|
98
|
+
};
|
|
99
|
+
/** Edited dictionary items back into text: chips become their placeholders again, breaks spaces. */
|
|
100
|
+
export declare function translationText(items: EditItem[], names: string[]): string;
|
|
101
|
+
/**
|
|
102
|
+
* The value each chip shows while editing, read off the element's rendered text: the text between
|
|
103
|
+
* the chips must appear in it in order, and exactly one way of placing them must exist. Null when
|
|
104
|
+
* there is none or more than one (an empty value, a value that repeats a literal): the chips then
|
|
105
|
+
* show their labels.
|
|
106
|
+
*/
|
|
107
|
+
export declare function chipValues(rendered: string, items: EditItem[]): string[] | null;
|
|
108
|
+
/**
|
|
109
|
+
* Literal text for a template's HTML, as the design emitter writes it: escaped like an edit from the
|
|
110
|
+
* preview, so a `{` that could open template syntax is written as `{`.
|
|
111
|
+
*/
|
|
112
|
+
export declare function encodeTemplateText(text: string): string;
|
|
@@ -5,16 +5,21 @@ import type { EngineId } from './types.cjs';
|
|
|
5
5
|
* rendered element says where it came from instead of the editor searching the template for it.
|
|
6
6
|
* Elements from a loop all point at the loop body, which is the line that wrote them.
|
|
7
7
|
*
|
|
8
|
+
* With `editable`, a start tag whose content is a region the preview can edit (plan 16 §3.1,
|
|
9
|
+
* `editableRegionAt`) also gets `data-ff-edit="text"`, or `data-ff-edit="t"` when its whole content
|
|
10
|
+
* is one `t()` call.
|
|
11
|
+
*
|
|
8
12
|
* The annotation must never change what the template means: tags inside template syntax, in
|
|
9
13
|
* blocks whose output is captured or filtered as a string (`{% set %}…{% endset %}`, `{% filter %}`,
|
|
10
14
|
* `{% capture %}`), in raw and comment blocks, in `<script>`/`<style>`/`<textarea>`/`<title>` and
|
|
11
15
|
* HTML comments, closing tags, declarations, tags whose name is built by template syntax and tags
|
|
12
|
-
* that already carry the attribute stay untouched. Removing the
|
|
16
|
+
* that already carry the attribute stay untouched. Removing the attributes from the rendered output
|
|
13
17
|
* gives the document of the original source. Preview only: saved versions, API renders and the
|
|
14
|
-
* render-worker never see
|
|
18
|
+
* render-worker never see them.
|
|
15
19
|
*/
|
|
16
20
|
export type SourceFile = 'body' | 'header' | 'footer';
|
|
17
21
|
export declare const sourceAttribute = "data-ff-src";
|
|
22
|
+
export declare const editAttribute = "data-ff-edit";
|
|
18
23
|
export interface SourceLocation {
|
|
19
24
|
file: SourceFile;
|
|
20
25
|
/** 1-based, as Monaco counts. */
|
|
@@ -22,6 +27,10 @@ export interface SourceLocation {
|
|
|
22
27
|
/** 1-based UTF-16 column of the tag's `<`. */
|
|
23
28
|
column: number;
|
|
24
29
|
}
|
|
30
|
+
export interface AnnotateOptions {
|
|
31
|
+
/** Mark editable regions with `data-ff-edit` as well (the preview's edit mode). */
|
|
32
|
+
editable?: boolean;
|
|
33
|
+
}
|
|
25
34
|
/** Parses a `data-ff-src` value; null when it is not one. */
|
|
26
35
|
export declare function parseSourceAttribute(value: string | null | undefined): SourceLocation | null;
|
|
27
|
-
export declare function annotateSourcePositions(source: string, engine: EngineId, file: SourceFile): string;
|
|
36
|
+
export declare function annotateSourcePositions(source: string, engine: EngineId, file: SourceFile, options?: AnnotateOptions): string;
|
|
@@ -5,16 +5,21 @@ import type { EngineId } from './types.js';
|
|
|
5
5
|
* rendered element says where it came from instead of the editor searching the template for it.
|
|
6
6
|
* Elements from a loop all point at the loop body, which is the line that wrote them.
|
|
7
7
|
*
|
|
8
|
+
* With `editable`, a start tag whose content is a region the preview can edit (plan 16 §3.1,
|
|
9
|
+
* `editableRegionAt`) also gets `data-ff-edit="text"`, or `data-ff-edit="t"` when its whole content
|
|
10
|
+
* is one `t()` call.
|
|
11
|
+
*
|
|
8
12
|
* The annotation must never change what the template means: tags inside template syntax, in
|
|
9
13
|
* blocks whose output is captured or filtered as a string (`{% set %}…{% endset %}`, `{% filter %}`,
|
|
10
14
|
* `{% capture %}`), in raw and comment blocks, in `<script>`/`<style>`/`<textarea>`/`<title>` and
|
|
11
15
|
* HTML comments, closing tags, declarations, tags whose name is built by template syntax and tags
|
|
12
|
-
* that already carry the attribute stay untouched. Removing the
|
|
16
|
+
* that already carry the attribute stay untouched. Removing the attributes from the rendered output
|
|
13
17
|
* gives the document of the original source. Preview only: saved versions, API renders and the
|
|
14
|
-
* render-worker never see
|
|
18
|
+
* render-worker never see them.
|
|
15
19
|
*/
|
|
16
20
|
export type SourceFile = 'body' | 'header' | 'footer';
|
|
17
21
|
export declare const sourceAttribute = "data-ff-src";
|
|
22
|
+
export declare const editAttribute = "data-ff-edit";
|
|
18
23
|
export interface SourceLocation {
|
|
19
24
|
file: SourceFile;
|
|
20
25
|
/** 1-based, as Monaco counts. */
|
|
@@ -22,6 +27,10 @@ export interface SourceLocation {
|
|
|
22
27
|
/** 1-based UTF-16 column of the tag's `<`. */
|
|
23
28
|
column: number;
|
|
24
29
|
}
|
|
30
|
+
export interface AnnotateOptions {
|
|
31
|
+
/** Mark editable regions with `data-ff-edit` as well (the preview's edit mode). */
|
|
32
|
+
editable?: boolean;
|
|
33
|
+
}
|
|
25
34
|
/** Parses a `data-ff-src` value; null when it is not one. */
|
|
26
35
|
export declare function parseSourceAttribute(value: string | null | undefined): SourceLocation | null;
|
|
27
|
-
export declare function annotateSourcePositions(source: string, engine: EngineId, file: SourceFile): string;
|
|
36
|
+
export declare function annotateSourcePositions(source: string, engine: EngineId, file: SourceFile, options?: AnnotateOptions): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { EngineId } from './types.cjs';
|
|
2
|
+
/**
|
|
3
|
+
* A template source read as HTML with template constructs in it: the scanner that finds start tags
|
|
4
|
+
* for click-to-source (`source-positions.ts`) and the regions text can be edited in from the preview
|
|
5
|
+
* (`source-edit.ts`). It knows each engine's delimiters, string literals inside expressions, raw and
|
|
6
|
+
* comment blocks, and blocks whose output is captured as a string. Internal to the engine.
|
|
7
|
+
*/
|
|
8
|
+
export declare const tagName: RegExp;
|
|
9
|
+
/** Elements whose content the HTML parser reads as text, so a `<b>` inside is not an element. */
|
|
10
|
+
export declare const rawTextElements: Set<string>;
|
|
11
|
+
/**
|
|
12
|
+
* What a template construct is, for a reader that has to tell output from control flow: `output` is
|
|
13
|
+
* a value printed in place (`{{ x }}`, `{{{ x }}}`, `{{t 'k'}}`), `comment` prints nothing, and
|
|
14
|
+
* `statement` is everything that decides what is printed (`{% if %}`, `{{#each}}`, `{{else}}`,
|
|
15
|
+
* `{{> partial}}`, raw blocks).
|
|
16
|
+
*/
|
|
17
|
+
export type TemplateConstruct = {
|
|
18
|
+
type: 'output';
|
|
19
|
+
end: number;
|
|
20
|
+
inner: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'comment';
|
|
23
|
+
end: number;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'statement';
|
|
26
|
+
end: number;
|
|
27
|
+
keyword?: string;
|
|
28
|
+
};
|
|
29
|
+
export declare class Scanner {
|
|
30
|
+
private readonly source;
|
|
31
|
+
private readonly engine;
|
|
32
|
+
private readonly n;
|
|
33
|
+
private readonly escapes;
|
|
34
|
+
constructor(source: string, engine: EngineId);
|
|
35
|
+
/** End of the template construct starting at `at` (with a capturing block's body), or null. */
|
|
36
|
+
skipTemplate(at: number): number | null;
|
|
37
|
+
/** The construct starting at `at` and what kind it is, or null when `{` starts none. */
|
|
38
|
+
classify(at: number): TemplateConstruct | null;
|
|
39
|
+
/** Index after `close`, stepping over template constructs; the end of the source when missing. */
|
|
40
|
+
skipTo(from: number, close: string): number;
|
|
41
|
+
/** Index after the `>` that ends a tag, stepping over quoted values and template constructs. */
|
|
42
|
+
tagEnd(from: number): number;
|
|
43
|
+
/** Index of the `</name` that closes a raw text element. */
|
|
44
|
+
skipToClosingTag(from: number, name: string): number;
|
|
45
|
+
private captures;
|
|
46
|
+
private blockEnd;
|
|
47
|
+
private templateTag;
|
|
48
|
+
/** `{{{{raw}}}} … {{{{/raw}}}}`: the content is never parsed. */
|
|
49
|
+
private handlebarsRawBlock;
|
|
50
|
+
private indexAfter;
|
|
51
|
+
/** End of an expression or statement; a `close` inside a string literal does not end it. */
|
|
52
|
+
private expressionEnd;
|
|
53
|
+
}
|
|
54
|
+
/** Offsets where lines start; `\r\n`, `\n` and a lone `\r` all end a line, as in Monaco. */
|
|
55
|
+
export declare function lineStarts(source: string): number[];
|
|
56
|
+
export declare function locate(starts: number[], offset: number): {
|
|
57
|
+
line: number;
|
|
58
|
+
column: number;
|
|
59
|
+
};
|
|
60
|
+
/** The offset of a 1-based line and column, or null when the source has no such place. */
|
|
61
|
+
export declare function offsetOf(starts: number[], sourceLength: number, line: number, column: number): number | null;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { EngineId } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A template source read as HTML with template constructs in it: the scanner that finds start tags
|
|
4
|
+
* for click-to-source (`source-positions.ts`) and the regions text can be edited in from the preview
|
|
5
|
+
* (`source-edit.ts`). It knows each engine's delimiters, string literals inside expressions, raw and
|
|
6
|
+
* comment blocks, and blocks whose output is captured as a string. Internal to the engine.
|
|
7
|
+
*/
|
|
8
|
+
export declare const tagName: RegExp;
|
|
9
|
+
/** Elements whose content the HTML parser reads as text, so a `<b>` inside is not an element. */
|
|
10
|
+
export declare const rawTextElements: Set<string>;
|
|
11
|
+
/**
|
|
12
|
+
* What a template construct is, for a reader that has to tell output from control flow: `output` is
|
|
13
|
+
* a value printed in place (`{{ x }}`, `{{{ x }}}`, `{{t 'k'}}`), `comment` prints nothing, and
|
|
14
|
+
* `statement` is everything that decides what is printed (`{% if %}`, `{{#each}}`, `{{else}}`,
|
|
15
|
+
* `{{> partial}}`, raw blocks).
|
|
16
|
+
*/
|
|
17
|
+
export type TemplateConstruct = {
|
|
18
|
+
type: 'output';
|
|
19
|
+
end: number;
|
|
20
|
+
inner: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'comment';
|
|
23
|
+
end: number;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'statement';
|
|
26
|
+
end: number;
|
|
27
|
+
keyword?: string;
|
|
28
|
+
};
|
|
29
|
+
export declare class Scanner {
|
|
30
|
+
private readonly source;
|
|
31
|
+
private readonly engine;
|
|
32
|
+
private readonly n;
|
|
33
|
+
private readonly escapes;
|
|
34
|
+
constructor(source: string, engine: EngineId);
|
|
35
|
+
/** End of the template construct starting at `at` (with a capturing block's body), or null. */
|
|
36
|
+
skipTemplate(at: number): number | null;
|
|
37
|
+
/** The construct starting at `at` and what kind it is, or null when `{` starts none. */
|
|
38
|
+
classify(at: number): TemplateConstruct | null;
|
|
39
|
+
/** Index after `close`, stepping over template constructs; the end of the source when missing. */
|
|
40
|
+
skipTo(from: number, close: string): number;
|
|
41
|
+
/** Index after the `>` that ends a tag, stepping over quoted values and template constructs. */
|
|
42
|
+
tagEnd(from: number): number;
|
|
43
|
+
/** Index of the `</name` that closes a raw text element. */
|
|
44
|
+
skipToClosingTag(from: number, name: string): number;
|
|
45
|
+
private captures;
|
|
46
|
+
private blockEnd;
|
|
47
|
+
private templateTag;
|
|
48
|
+
/** `{{{{raw}}}} … {{{{/raw}}}}`: the content is never parsed. */
|
|
49
|
+
private handlebarsRawBlock;
|
|
50
|
+
private indexAfter;
|
|
51
|
+
/** End of an expression or statement; a `close` inside a string literal does not end it. */
|
|
52
|
+
private expressionEnd;
|
|
53
|
+
}
|
|
54
|
+
/** Offsets where lines start; `\r\n`, `\n` and a lone `\r` all end a line, as in Monaco. */
|
|
55
|
+
export declare function lineStarts(source: string): number[];
|
|
56
|
+
export declare function locate(starts: number[], offset: number): {
|
|
57
|
+
line: number;
|
|
58
|
+
column: number;
|
|
59
|
+
};
|
|
60
|
+
/** The offset of a 1-based line and column, or null when the source has no such place. */
|
|
61
|
+
export declare function offsetOf(starts: number[], sourceLength: number, line: number, column: number): number | null;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Template-level dictionaries: locale → key → text (USP-8). */
|
|
2
|
+
export type Dictionaries = Record<string, Record<string, string>>;
|
|
3
|
+
/**
|
|
4
|
+
* The `t` helper's lookup, with where the text came from: the exact locale (`de-DE`), its language
|
|
5
|
+
* (`de`), English, or — `from: null` — nowhere, in which case the key itself is shown. The editor uses
|
|
6
|
+
* `from` to write an edited translation where the reader will find it (plan 16 §3.1).
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveTranslation(dictionaries: Dictionaries | undefined, locale: string, key: string): {
|
|
9
|
+
text: string;
|
|
10
|
+
from: string | null;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The dictionary an edit of `key` shown in `locale` belongs in: the one the text came from when that
|
|
14
|
+
* is the reader's own language, otherwise the reader's locale (when it has a dictionary) or language —
|
|
15
|
+
* never English on behalf of someone reading German.
|
|
16
|
+
*/
|
|
17
|
+
export declare function translationTarget(dictionaries: Dictionaries | undefined, locale: string, key: string): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Template-level dictionaries: locale → key → text (USP-8). */
|
|
2
|
+
export type Dictionaries = Record<string, Record<string, string>>;
|
|
3
|
+
/**
|
|
4
|
+
* The `t` helper's lookup, with where the text came from: the exact locale (`de-DE`), its language
|
|
5
|
+
* (`de`), English, or — `from: null` — nowhere, in which case the key itself is shown. The editor uses
|
|
6
|
+
* `from` to write an edited translation where the reader will find it (plan 16 §3.1).
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveTranslation(dictionaries: Dictionaries | undefined, locale: string, key: string): {
|
|
9
|
+
text: string;
|
|
10
|
+
from: string | null;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* The dictionary an edit of `key` shown in `locale` belongs in: the one the text came from when that
|
|
14
|
+
* is the reader's own language, otherwise the reader's locale (when it has a dictionary) or language —
|
|
15
|
+
* never English on behalf of someone reading German.
|
|
16
|
+
*/
|
|
17
|
+
export declare function translationTarget(dictionaries: Dictionaries | undefined, locale: string, key: string): string;
|