@funcstache/stache-stream 0.2.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.
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "Tokenize", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return Tokenize;
9
+ }
10
+ });
11
+ const _nodeevents = require("node:events");
12
+ const _logger = require("@funcstache/logger");
13
+ const _Tag = require("../tag/Tag");
14
+ let Tokenize = class Tokenize extends _nodeevents.EventEmitter {
15
+ #TOKEN_ENTER_CHAR;
16
+ #TOKEN_EXIT_CHAR;
17
+ #logger;
18
+ #stateCurrent;
19
+ #statePrevious;
20
+ #leftBuffer;
21
+ #leftTokenBuffer;
22
+ #middleBuffer;
23
+ #rightTokenBuffer;
24
+ #emitTagToken() {
25
+ if (this.#leftTokenBuffer.length === this.#rightTokenBuffer.length) {
26
+ const data = _Tag.Tag.parse(`${this.#leftTokenBuffer}${this.#middleBuffer}${this.#rightTokenBuffer}`);
27
+ data && this.#emitToken({
28
+ data,
29
+ uid: performance.now(),
30
+ type: "tag"
31
+ });
32
+ }
33
+ this.#leftBuffer = "";
34
+ this.#leftTokenBuffer = "";
35
+ this.#middleBuffer = "";
36
+ this.#rightTokenBuffer = "";
37
+ }
38
+ #emitToken(event) {
39
+ this.#logger.debug(()=>[
40
+ `!!! #emitEvent: event=`,
41
+ JSON.stringify(event)
42
+ ]);
43
+ this.emit("token", event);
44
+ }
45
+ async push(char) {
46
+ this.#logger.debug(()=>"-".repeat(80));
47
+ char && this.#updateStatus(char);
48
+ await this.#processChar(char);
49
+ }
50
+ async #processChar(char) {
51
+ this.#logger.debug(()=>`=== #processChar: current=${this.#stateCurrent}, previous=${this.#statePrevious}`);
52
+ if (char === null) {
53
+ if (this.#leftBuffer) {
54
+ this.#emitToken({
55
+ data: this.#leftBuffer,
56
+ type: "text",
57
+ uid: performance.now()
58
+ });
59
+ }
60
+ this.#emitTagToken();
61
+ this.#emitToken(null);
62
+ return;
63
+ }
64
+ // The only state changes that should happen here are resets that need to be done after `char`
65
+ // is processed.
66
+ switch(this.#stateCurrent){
67
+ case "tagEnteringMaybe":
68
+ {
69
+ // This state change happens in the case of nested tags, for example: `{{#a}}{{m}}{{/a}}`
70
+ // It's why we can't set `#leftTokenBuffer` in the `#updateStatus` method.
71
+ if (this.#statePrevious === "tagExitingMaybe") {
72
+ this.#emitTagToken();
73
+ }
74
+ this.#leftTokenBuffer += char;
75
+ break;
76
+ }
77
+ // case "tagExitingMaybe": {
78
+ // break;
79
+ // }
80
+ case "inTagValue":
81
+ {
82
+ if (this.#leftBuffer) {
83
+ this.#emitToken({
84
+ data: this.#leftBuffer,
85
+ type: "text",
86
+ uid: performance.now()
87
+ });
88
+ this.#leftBuffer = "";
89
+ }
90
+ break;
91
+ }
92
+ case "outsideTag":
93
+ {
94
+ if (this.#statePrevious === "tagEnteringMaybe") {
95
+ // Single `{` that was not the start of a mustache tag — treat as plain text.
96
+ // #updateStatus already appended the current char to leftBuffer, so insert
97
+ // leftTokenBuffer before that last char to preserve the correct order.
98
+ this.#leftBuffer = this.#leftBuffer.slice(0, -1) + this.#leftTokenBuffer + this.#leftBuffer.slice(-1);
99
+ this.#leftTokenBuffer = "";
100
+ } else if (this.#leftTokenBuffer && this.#rightTokenBuffer) {
101
+ const data = _Tag.Tag.parse(`${this.#leftTokenBuffer}${this.#middleBuffer}${this.#rightTokenBuffer}`);
102
+ data && this.#emitToken({
103
+ data,
104
+ type: "tag",
105
+ uid: performance.now()
106
+ });
107
+ this.#leftTokenBuffer = "";
108
+ this.#middleBuffer = "";
109
+ this.#rightTokenBuffer = "";
110
+ }
111
+ break;
112
+ }
113
+ }
114
+ this.#logger.debug(()=>`--- #processChar: '${char}' - ${this.#leftBuffer},${this.#leftTokenBuffer ? ` _${this.#leftTokenBuffer}_` : " "}, ${this.#middleBuffer}, ${this.#rightTokenBuffer ? `_${this.#rightTokenBuffer}_` : ""}`);
115
+ }
116
+ #updateStateFromModel(current, options, instantStateCallback) {
117
+ const currentStateData = stateModel[current];
118
+ let nextState = current;
119
+ for (const stateName of Object.keys(currentStateData)){
120
+ const dataArr = currentStateData[stateName];
121
+ if (!dataArr) {
122
+ continue;
123
+ }
124
+ if (dataArr.some((data)=>{
125
+ const allFalse = "isFalse" in data ? data.isFalse.every((optionName)=>options[optionName] === false) : true;
126
+ if (!allFalse) {
127
+ return false;
128
+ }
129
+ const allTrue = "isTrue" in data ? data.isTrue.every((optionName)=>options[optionName] === true) : true;
130
+ if (allTrue) {
131
+ nextState = stateName;
132
+ // If the next state is "instant" invoke the callback then invoke
133
+ // `#updateStateFromModel` function again recursively.
134
+ if ("instant" in data && data.instant) {
135
+ instantStateCallback && instantStateCallback(nextState);
136
+ nextState = this.#updateStateFromModel(nextState, options);
137
+ }
138
+ return true;
139
+ }
140
+ return false;
141
+ })) {
142
+ break;
143
+ }
144
+ }
145
+ return nextState;
146
+ }
147
+ #updateStatus(char) {
148
+ this.#logger.debug(()=>`--- #updateStatus: '${char}' - ${this.#leftBuffer},${this.#leftTokenBuffer ? ` _${this.#leftTokenBuffer}_` : " "}, ${this.#middleBuffer}, ${this.#rightTokenBuffer ? `_${this.#rightTokenBuffer}_` : ""}`);
149
+ this.#statePrevious = this.#stateCurrent;
150
+ // This code sets the state for how `char` should be processed.
151
+ const isEnterToken = char === this.#TOKEN_ENTER_CHAR;
152
+ const isExitToken = char === this.#TOKEN_EXIT_CHAR;
153
+ const options = {
154
+ currentCharEnterToken: isEnterToken,
155
+ currentCharExitToken: isExitToken,
156
+ currentCharNotToken: !isEnterToken && !isExitToken,
157
+ enterTokenCountEqualsOne: 1 === this.#leftTokenBuffer.length,
158
+ enterTokenCountEqualsTwo: 2 === this.#leftTokenBuffer.length,
159
+ enterTokenCountEqualsThree: 3 === this.#leftTokenBuffer.length,
160
+ exitTokenCountEqualsEnterTokenCount: this.#leftTokenBuffer.length === this.#rightTokenBuffer.length
161
+ };
162
+ this.#stateCurrent = this.#updateStateFromModel(this.#stateCurrent, options, (state)=>{
163
+ this.#logger.debug(()=>`>>> #updateStatus: instant;\n #statePrevious='${this.#statePrevious}',\n state='${state}'`);
164
+ });
165
+ // Manage most of the state changes here. a small number of them have to be done in
166
+ // `#processChar` because certain state values have to be reset after the char is processed.
167
+ switch(this.#stateCurrent){
168
+ case "tagEnteringMaybe":
169
+ {
170
+ break;
171
+ }
172
+ case "tagExitingMaybe":
173
+ {
174
+ this.#rightTokenBuffer += char;
175
+ break;
176
+ }
177
+ case "outsideTag":
178
+ {
179
+ this.#leftBuffer += char;
180
+ break;
181
+ }
182
+ case "inTagValue":
183
+ {
184
+ this.#middleBuffer += char;
185
+ break;
186
+ }
187
+ }
188
+ }
189
+ constructor(...args){
190
+ super(...args);
191
+ this.#TOKEN_ENTER_CHAR = "{";
192
+ this.#TOKEN_EXIT_CHAR = "}";
193
+ this.#logger = new _logger.Log({
194
+ category: "TKZ",
195
+ level: process.env.LOG_LEVEL || "warn"
196
+ });
197
+ this.#stateCurrent = "outsideTag";
198
+ this.#leftBuffer = "";
199
+ this.#leftTokenBuffer = "";
200
+ this.#middleBuffer = "";
201
+ this.#rightTokenBuffer = "";
202
+ }
203
+ };
204
+ const stateModel = {
205
+ inTagValue: {
206
+ tagExitingMaybe: [
207
+ {
208
+ isTrue: [
209
+ "currentCharExitToken"
210
+ ]
211
+ }
212
+ ]
213
+ },
214
+ outsideTag: {
215
+ tagEnteringMaybe: [
216
+ {
217
+ isTrue: [
218
+ "currentCharEnterToken"
219
+ ]
220
+ }
221
+ ]
222
+ },
223
+ tagExitingMaybe: {
224
+ tagEnteringMaybe: [
225
+ {
226
+ isTrue: [
227
+ "currentCharEnterToken",
228
+ "exitTokenCountEqualsEnterTokenCount"
229
+ ]
230
+ }
231
+ ],
232
+ outsideTag: [
233
+ {
234
+ isTrue: [
235
+ "currentCharNotToken",
236
+ "exitTokenCountEqualsEnterTokenCount"
237
+ ]
238
+ }
239
+ ]
240
+ },
241
+ tagEnteringMaybe: {
242
+ outsideTag: [
243
+ {
244
+ isFalse: [
245
+ "currentCharEnterToken"
246
+ ],
247
+ isTrue: [
248
+ "enterTokenCountEqualsOne"
249
+ ]
250
+ }
251
+ ],
252
+ inTagValue: [
253
+ {
254
+ isTrue: [
255
+ "currentCharNotToken",
256
+ "enterTokenCountEqualsTwo"
257
+ ]
258
+ },
259
+ {
260
+ isTrue: [
261
+ "enterTokenCountEqualsThree"
262
+ ]
263
+ }
264
+ ]
265
+ }
266
+ };
267
+
268
+ //# sourceMappingURL=Tokenize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/stache-stream/src/lib/tokenize/Tokenize.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { Log } from \"@funcstache/logger\";\nimport { Tag } from \"../tag/Tag\";\n\nexport class Tokenize extends EventEmitter<TokenizeEventMap> {\n readonly #TOKEN_ENTER_CHAR = \"{\";\n readonly #TOKEN_EXIT_CHAR = \"}\";\n\n #logger = new Log({\n category: \"TKZ\",\n level: (process.env as any).LOG_LEVEL || \"warn\",\n });\n\n #stateCurrent: StateNames = \"outsideTag\";\n #statePrevious: StateNames | undefined;\n #leftBuffer = \"\";\n #leftTokenBuffer = \"\";\n #middleBuffer = \"\";\n #rightTokenBuffer = \"\";\n\n #emitTagToken() {\n if (this.#leftTokenBuffer.length === this.#rightTokenBuffer.length) {\n const data = Tag.parse(\n `${this.#leftTokenBuffer}${this.#middleBuffer}${this.#rightTokenBuffer}`\n );\n\n data &&\n this.#emitToken({\n data,\n uid: performance.now(),\n type: \"tag\",\n });\n }\n\n this.#leftBuffer = \"\";\n this.#leftTokenBuffer = \"\";\n this.#middleBuffer = \"\";\n this.#rightTokenBuffer = \"\";\n }\n\n #emitToken(event: TokenizeTagEvent | TokenizeTextEvent | null) {\n this.#logger.debug(() => [`!!! #emitEvent: event=`, JSON.stringify(event)]);\n this.emit(\"token\", event);\n }\n\n async push(char: string | null): Promise<void> {\n this.#logger.debug(() => \"-\".repeat(80));\n\n char && this.#updateStatus(char);\n await this.#processChar(char);\n }\n\n async #processChar(char: string | null): Promise<void> {\n this.#logger.debug(\n () =>\n `=== #processChar: current=${this.#stateCurrent}, previous=${\n this.#statePrevious\n }`\n );\n\n if (char === null) {\n if (this.#leftBuffer) {\n this.#emitToken({\n data: this.#leftBuffer,\n type: \"text\",\n uid: performance.now(),\n });\n }\n this.#emitTagToken();\n this.#emitToken(null);\n return;\n }\n\n // The only state changes that should happen here are resets that need to be done after `char`\n // is processed.\n switch (this.#stateCurrent) {\n case \"tagEnteringMaybe\": {\n // This state change happens in the case of nested tags, for example: `{{#a}}{{m}}{{/a}}`\n // It's why we can't set `#leftTokenBuffer` in the `#updateStatus` method.\n if (this.#statePrevious === \"tagExitingMaybe\") {\n this.#emitTagToken();\n }\n\n this.#leftTokenBuffer += char;\n\n break;\n }\n\n // case \"tagExitingMaybe\": {\n // break;\n // }\n\n case \"inTagValue\": {\n if (this.#leftBuffer) {\n this.#emitToken({\n data: this.#leftBuffer,\n type: \"text\",\n uid: performance.now(),\n });\n this.#leftBuffer = \"\";\n }\n break;\n }\n\n case \"outsideTag\": {\n if (this.#statePrevious === \"tagEnteringMaybe\") {\n // Single `{` that was not the start of a mustache tag — treat as plain text.\n // #updateStatus already appended the current char to leftBuffer, so insert\n // leftTokenBuffer before that last char to preserve the correct order.\n this.#leftBuffer =\n this.#leftBuffer.slice(0, -1) +\n this.#leftTokenBuffer +\n this.#leftBuffer.slice(-1);\n this.#leftTokenBuffer = \"\";\n } else if (this.#leftTokenBuffer && this.#rightTokenBuffer) {\n const data = Tag.parse(\n `${this.#leftTokenBuffer}${this.#middleBuffer}${\n this.#rightTokenBuffer\n }`\n );\n\n data &&\n this.#emitToken({\n data,\n type: \"tag\",\n uid: performance.now(),\n });\n\n this.#leftTokenBuffer = \"\";\n this.#middleBuffer = \"\";\n this.#rightTokenBuffer = \"\";\n }\n break;\n }\n }\n\n this.#logger.debug(\n () =>\n `--- #processChar: '${char}' - ${this.#leftBuffer},${\n this.#leftTokenBuffer ? ` _${this.#leftTokenBuffer}_` : \" \"\n }, ${this.#middleBuffer}, ${\n this.#rightTokenBuffer ? `_${this.#rightTokenBuffer}_` : \"\"\n }`\n );\n }\n\n #updateStateFromModel(\n current: StateNames,\n options: UpdateStateModelOptions,\n instantStateCallback?: (state: StateNames) => void\n ): StateNames {\n const currentStateData = stateModel[current];\n let nextState: StateNames = current;\n for (const stateName of Object.keys(currentStateData) as StateNames[]) {\n const dataArr = currentStateData[stateName];\n if (!dataArr) {\n continue;\n }\n\n if (\n dataArr.some((data) => {\n const allFalse =\n \"isFalse\" in data\n ? data.isFalse.every(\n (optionName) => options[optionName] === false\n )\n : true;\n\n if (!allFalse) {\n return false;\n }\n\n const allTrue =\n \"isTrue\" in data\n ? data.isTrue.every((optionName) => options[optionName] === true)\n : true;\n\n if (allTrue) {\n nextState = stateName;\n\n // If the next state is \"instant\" invoke the callback then invoke\n // `#updateStateFromModel` function again recursively.\n if (\"instant\" in data && data.instant) {\n instantStateCallback && instantStateCallback(nextState);\n nextState = this.#updateStateFromModel(nextState, options);\n }\n\n return true;\n }\n\n return false;\n })\n ) {\n break;\n }\n }\n\n return nextState;\n }\n\n #updateStatus(char: string): void {\n this.#logger.debug(\n () =>\n `--- #updateStatus: '${char}' - ${this.#leftBuffer},${\n this.#leftTokenBuffer ? ` _${this.#leftTokenBuffer}_` : \" \"\n }, ${this.#middleBuffer}, ${\n this.#rightTokenBuffer ? `_${this.#rightTokenBuffer}_` : \"\"\n }`\n );\n\n this.#statePrevious = this.#stateCurrent;\n\n // This code sets the state for how `char` should be processed.\n const isEnterToken = char === this.#TOKEN_ENTER_CHAR;\n const isExitToken = char === this.#TOKEN_EXIT_CHAR;\n\n const options: UpdateStateModelOptions = {\n currentCharEnterToken: isEnterToken,\n currentCharExitToken: isExitToken,\n currentCharNotToken: !isEnterToken && !isExitToken,\n enterTokenCountEqualsOne: 1 === this.#leftTokenBuffer.length,\n enterTokenCountEqualsTwo: 2 === this.#leftTokenBuffer.length,\n enterTokenCountEqualsThree: 3 === this.#leftTokenBuffer.length,\n exitTokenCountEqualsEnterTokenCount:\n this.#leftTokenBuffer.length === this.#rightTokenBuffer.length,\n };\n\n this.#stateCurrent = this.#updateStateFromModel(\n this.#stateCurrent,\n options,\n (state) => {\n this.#logger.debug(\n () =>\n `>>> #updateStatus: instant;\\n #statePrevious='${\n this.#statePrevious\n }',\\n state='${state}'`\n );\n }\n );\n\n // Manage most of the state changes here. a small number of them have to be done in\n // `#processChar` because certain state values have to be reset after the char is processed.\n switch (this.#stateCurrent) {\n case \"tagEnteringMaybe\": {\n //Changing to \"tagEnteringMaybe\" could happen because of nested tags, for example:\n // `{{#a}}{{m}}{{/a}}`. It's why we can't set `#leftTokenBuffer` here, it has to be done as\n // part of #processChar.\n\n // this.#leftTokenBuffer += char;\n break;\n }\n\n case \"tagExitingMaybe\": {\n this.#rightTokenBuffer += char;\n break;\n }\n\n case \"outsideTag\": {\n this.#leftBuffer += char;\n break;\n }\n\n case \"inTagValue\": {\n this.#middleBuffer += char;\n break;\n }\n }\n }\n}\n\ninterface TokenizeEvent {\n uid: number;\n}\n\nexport interface TokenizeTagEvent extends TokenizeEvent {\n data: Tag;\n type: \"tag\";\n}\n\nexport interface TokenizeTextEvent extends TokenizeEvent {\n data: string;\n type: \"text\";\n}\n\nexport type TokenizeEventMap = {\n token: [TokenizeTagEvent | TokenizeTextEvent | null];\n};\n\nexport type StateNames =\n | \"inTagValue\"\n | \"outsideTag\"\n | \"tagExitingMaybe\"\n | \"tagEnteringMaybe\";\n\nconst stateModel: StateModel = {\n inTagValue: {\n tagExitingMaybe: [\n {\n isTrue: [\"currentCharExitToken\"],\n },\n ],\n },\n\n outsideTag: {\n tagEnteringMaybe: [\n {\n isTrue: [\"currentCharEnterToken\"],\n },\n ],\n },\n\n tagExitingMaybe: {\n tagEnteringMaybe: [\n {\n isTrue: [\n \"currentCharEnterToken\",\n \"exitTokenCountEqualsEnterTokenCount\",\n ],\n },\n ],\n outsideTag: [\n {\n isTrue: [\"currentCharNotToken\", \"exitTokenCountEqualsEnterTokenCount\"],\n },\n ],\n },\n\n tagEnteringMaybe: {\n outsideTag: [\n {\n isFalse: [\"currentCharEnterToken\"],\n isTrue: [\"enterTokenCountEqualsOne\"],\n },\n ],\n inTagValue: [\n {\n isTrue: [\"currentCharNotToken\", \"enterTokenCountEqualsTwo\"],\n },\n {\n isTrue: [\"enterTokenCountEqualsThree\"],\n },\n ],\n },\n} as const;\n\ntype StateModel = {\n [currentState in StateNames]: {\n [moveToStateWhen in StateNames]?: (\n | {\n instant?: boolean;\n isFalse: (keyof UpdateStateModelOptions)[];\n isTrue: (keyof UpdateStateModelOptions)[];\n }\n | {\n instant?: boolean;\n isFalse: (keyof UpdateStateModelOptions)[];\n }\n | {\n instant?: boolean;\n isTrue: (keyof UpdateStateModelOptions)[];\n }\n )[];\n };\n};\n\ninterface UpdateStateModelOptions {\n currentCharEnterToken: boolean;\n currentCharExitToken: boolean;\n currentCharNotToken: boolean;\n enterTokenCountEqualsOne: boolean;\n enterTokenCountEqualsTwo: boolean;\n enterTokenCountEqualsThree: boolean;\n exitTokenCountEqualsEnterTokenCount: boolean;\n}\n"],"names":["Tokenize","EventEmitter","TOKEN_ENTER_CHAR","TOKEN_EXIT_CHAR","logger","stateCurrent","statePrevious","leftBuffer","leftTokenBuffer","middleBuffer","rightTokenBuffer","emitTagToken","length","data","Tag","parse","emitToken","uid","performance","now","type","event","debug","JSON","stringify","emit","push","char","repeat","updateStatus","processChar","slice","updateStateFromModel","current","options","instantStateCallback","currentStateData","stateModel","nextState","stateName","Object","keys","dataArr","some","allFalse","isFalse","every","optionName","allTrue","isTrue","instant","isEnterToken","isExitToken","currentCharEnterToken","currentCharExitToken","currentCharNotToken","enterTokenCountEqualsOne","enterTokenCountEqualsTwo","enterTokenCountEqualsThree","exitTokenCountEqualsEnterTokenCount","state","Log","category","level","process","env","LOG_LEVEL","inTagValue","tagExitingMaybe","outsideTag","tagEnteringMaybe"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"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"}
@@ -0,0 +1,224 @@
1
+ import { ReadableStream } from "node:stream/web";
2
+ export type ContentTagTagTypes = (typeof ContentTagTypes)[number];
3
+ export declare const ContentTagTypes: readonly ["block", "end", "inverted", "parent", "section"];
4
+ /**
5
+ * A JavaScript object that supplies replacements for tags in a Mustache template. The Mustache
6
+ * specification uses the term "hash." In stache-stream "hash" and "context" are synonyms.
7
+ * @category Context
8
+ */
9
+ export interface Context {
10
+ readonly [key: string]: ContextTypes | undefined;
11
+ }
12
+ /**
13
+ * When a Mustache template is rendered data needs to be provided to replace tags in the template; a
14
+ * ContextProvider delivers that information. The ContextProvider includes context for a template as
15
+ * well as the method `getContextValue` to search for a value not found in the current context in
16
+ * the parent context.
17
+ *
18
+ * @property context Context for the current template.
19
+ * @property getContextValue If a value is not found in the current context invoke this method to
20
+ * look for a value in parent context.
21
+ */
22
+ export interface ContextProvider {
23
+ readonly context: ContextTypes;
24
+ readonly getContextValue?: <CTX extends ContextTypes>(tag: Tag) => Promise<CTX | undefined>;
25
+ }
26
+ /**
27
+ * Properties in a { @link Context } object implement these types. The specific types to implement
28
+ * are determined by the tag type in a Mustache template.
29
+ * @category Context
30
+ */
31
+ export type ContextTypes = Context | PartialTagContext | SectionTagContext | VariableTagContext;
32
+ /**
33
+ * A primitive JavaScript type that can be serialized in a JSON object.
34
+ */
35
+ export type JsonType = boolean | number | string;
36
+ /**
37
+ * Implement one of these interfaces to provide replacements for
38
+ * {@link https://mustache.github.io/mustache.5.html#Variables Partial tags}. See
39
+ * {@link ContextTypes ContextTypes}.
40
+ * @category Context
41
+ * @category Partial
42
+ */
43
+ export type PartialTagContext = PartialTagContextLambda;
44
+ /**
45
+ * Implement this function to asynchronously return a `ReadableStream` that contains a Mustache
46
+ * template and its associated context that replaces a
47
+ * {@link https://mustache.github.io/mustache.5.html#Variables Partial tag}.
48
+ *
49
+ * @example PartialTagContextLambda
50
+ * ```
51
+ * const lambda: PartialTagContextLambda = (tag) => {
52
+ * context: { title: "On Tyranny" },
53
+ * template: () => bookSummary.getReadableStream()
54
+ * }
55
+ * ```
56
+ *
57
+ * @param tag The partial tag that is being processed. `PartialTagContextLambda` returns the
58
+ * template and the context that the partial tag references which are needed to render the partial
59
+ * replacement.
60
+ * @returns The template and context to render the partial that the `tag` parameter references.
61
+ * @category Context
62
+ * @category Partial
63
+ */
64
+ export interface PartialTagContextLambda {
65
+ (tag: Tag): Promise<PartialTagContextLambdaResult>;
66
+ }
67
+ /**
68
+ * The result of invoking a {@link PartialTagContextLambda}.
69
+ * @category Context
70
+ * @category Partial
71
+ */
72
+ export interface PartialTagContextLambdaResult {
73
+ /** The optional context associated with this template. */
74
+ context?: ContextTypes;
75
+ /** When invoked `input` resolves to a stream containing the Mustache template that replaces a
76
+ * partial tag. */
77
+ input: () => Promise<ReadableStream>;
78
+ }
79
+ /**
80
+ * Implement one of these interfaces to provide replacements for
81
+ * {@link https://mustache.github.io/mustache.5.html#Sections Section tags}. See
82
+ * {@link ContextTypes ContextTypes}.
83
+ * @category Context
84
+ * @category Section
85
+ */
86
+ export type SectionTagContext = SectionTagCallback | SectionTagContextRecord[];
87
+ /**
88
+ * Provides zero or more items that will replace a
89
+ * {@link https://mustache.github.io/mustache.5.html#Sections Section tag}. See
90
+ * {@link SectionTagContext SectionTagContext}.
91
+ * @category Context
92
+ * @category Section
93
+ */
94
+ export interface SectionTagContextRecord {
95
+ [key: string]: JsonType | SectionTagContextRecord;
96
+ }
97
+ /**
98
+ * When provided this callback is invoked when the
99
+ * {@link https://mustache.github.io/mustache.5.html#Sections Section tag} is encountered. The
100
+ * callback is passed the text contained within the section. If the section contains tags those tags
101
+ * will **not** have been replaced.
102
+ *
103
+ * @remarks
104
+ * Note that this is a callback function. The function provider is responsible for returning
105
+ * rendered text that will be written directly to the output.
106
+ *
107
+ * @example
108
+ * ```
109
+ * const callback = context as SectionTagCallback;
110
+ * const replacementText = callback(tag.content);
111
+ * this.writeToOutput(replacementText);
112
+ * ```
113
+ *
114
+ * @param tagContent The unrendered content of the section tag.
115
+ * @returns A string of rendered text that will replace the content of the section tag.
116
+ * @category Context
117
+ * @category Section
118
+ */
119
+ export interface SectionTagCallback {
120
+ (tagContent: string): string;
121
+ }
122
+ /**
123
+ * Represents a tag in a Mustache template providing information about a tag and its
124
+ * characteristics.
125
+ *
126
+ * @remarks
127
+ * Parts of a tag
128
+ *
129
+ * ```txt
130
+ * >------tag------<
131
+ * {{ > header }}
132
+ *
133
+ * >--value--<
134
+ * {{ > header }}
135
+ *
136
+ * >S<>-key--<
137
+ * {{ > header }}
138
+ *
139
+ * >TO< >TC<
140
+ * {{ > header }}
141
+ *
142
+ * >-------------------tag--------------------<
143
+ * {{ # section }} Hello! {{ / section }}
144
+ *
145
+ * >---start tag----< >----end tag----<
146
+ * {{ # section }} Hello! {{ / section }}
147
+ *
148
+ * >--content--<
149
+ * {{ # section }} Hello! {{ / section }}
150
+ *
151
+ * S = sigil or tag type
152
+ * TO = tag open
153
+ * TC = tag close
154
+ * ```
155
+ *
156
+ * @property content When a "tag" has a start and end tag (e.g. a Section tag) `content` contains
157
+ * the string between the two tags. When a tag is a single tag (like a Variable tag) `content` will
158
+ * be `null`.
159
+ * @property key The value that will be used to lookup a value in context. This key will have its
160
+ * sigil removed, for example, if the template is "{{ &title }}" the `key` value is "title".
161
+ * @property raw True when the tag has either three braces (e.g. "{{{ name }}}") or an ampersand
162
+ * (like "{{ &name }}").
163
+ * @property type The Tag type as described in the Mustache spec.
164
+ * @property value The string between a tag's opening "{{" and its closing "}}". If the template is
165
+ * "{{ #items }}" the `value` is "#items".
166
+ */
167
+ export interface Tag {
168
+ readonly content: string | null;
169
+ readonly key: string;
170
+ readonly raw: boolean;
171
+ readonly type: ContentTagTagTypes | ValueTagTagTypes;
172
+ readonly value: string;
173
+ }
174
+ /**
175
+ * Defines how to access a template file.
176
+ * - string: The name of a template file in the same directory as this module file. The name must
177
+ * **not** include an extension.
178
+ * - tuple: An array of two strings: the first element is the name of the template, as described
179
+ * in the "string" type above. The second element is a relative path to the directory where the
180
+ * template file is located; the path is relative to the location of this module file.
181
+ */
182
+ export type TemplateName = string | [templateName: string, templateFilename: string];
183
+ export type ValueTagTagTypes = (typeof ValueTagTypes)[number];
184
+ export declare const ValueTagTypes: readonly ["comment", "implicit", "partial", "variable"];
185
+ /**
186
+ * Interfaces that can supply replacements for
187
+ * {@link https://mustache.github.io/mustache.5.html#Variables variable tags}. See
188
+ * {@link ContextTypes ContextTypes}.
189
+ * @category Context
190
+ * @category Variable
191
+ */
192
+ export type VariableTagContext = VariableTagContextPrimitive | VariableTagContextLambda | VariableTagContextRecord;
193
+ /**
194
+ * A function that resolves to the value that replaces a
195
+ * {@link https://mustache.github.io/mustache.5.html#Variables variable tag}. See
196
+ * {@link VariableTagContext VariableTagContext}.
197
+ * @category Context
198
+ * @category Variable
199
+ */
200
+ export interface VariableTagContextLambda {
201
+ (): Promise<VariableTagContextPrimitive | VariableTagContextRecord>;
202
+ }
203
+ /**
204
+ * A {@link https://mustache.github.io/mustache.5.html#Variables variable tag} can be replaced by
205
+ * these JavaScript primitives. See {@link VariableTagContext VariableTagContext}.
206
+ * @category Context
207
+ * @category Variable
208
+ */
209
+ export type VariableTagContextPrimitive = JsonType | Array<boolean | number | string>;
210
+ /**
211
+ * A {@link https://mustache.github.io/mustache.5.html#Variables variable tag} with a "dotted name"
212
+ * can be replaced by a JavaScript object. See {@link VariableTagContext VariableTagContext}.
213
+ * @category Context
214
+ * @category Variable
215
+ */
216
+ export interface VariableTagContextRecord {
217
+ [key: string]: unknown;
218
+ }
219
+ /**
220
+ * Invoke this function to write to the output `WritableStream`.
221
+ */
222
+ export interface WriteToOutput {
223
+ (text: string): Promise<void>;
224
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ ContentTagTypes: function() {
13
+ return ContentTagTypes;
14
+ },
15
+ ValueTagTypes: function() {
16
+ return ValueTagTypes;
17
+ }
18
+ });
19
+ const ContentTagTypes = [
20
+ "block",
21
+ "end",
22
+ "inverted",
23
+ "parent",
24
+ "section"
25
+ ];
26
+ const ValueTagTypes = [
27
+ "comment",
28
+ "implicit",
29
+ "partial",
30
+ "variable"
31
+ ];
32
+
33
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../libs/stache-stream/src/lib/types.ts"],"sourcesContent":["import { ReadableStream } from \"node:stream/web\";\n\nexport type ContentTagTagTypes = (typeof ContentTagTypes)[number];\n\nexport const ContentTagTypes = [\n \"block\", // `{{$tag}}{{/tag}}`\n \"end\", // `{{/tag}}`\n \"inverted\", // `{{^tag}}{{/tag}}`\n \"parent\", // `{{<tag}}{{/tag}}`\n \"section\", // `{{#tag}}{{/tag}}`\n] as const;\n\n/**\n * A JavaScript object that supplies replacements for tags in a Mustache template. The Mustache\n * specification uses the term \"hash.\" In stache-stream \"hash\" and \"context\" are synonyms.\n * @category Context\n */\nexport interface Context {\n readonly [key: string]: ContextTypes | undefined;\n}\n\n/**\n * When a Mustache template is rendered data needs to be provided to replace tags in the template; a\n * ContextProvider delivers that information. The ContextProvider includes context for a template as\n * well as the method `getContextValue` to search for a value not found in the current context in\n * the parent context.\n *\n * @property context Context for the current template.\n * @property getContextValue If a value is not found in the current context invoke this method to\n * look for a value in parent context.\n */\nexport interface ContextProvider {\n readonly context: ContextTypes;\n readonly getContextValue?: <CTX extends ContextTypes>(\n tag: Tag\n ) => Promise<CTX | undefined>;\n}\n\n/**\n * Properties in a { @link Context } object implement these types. The specific types to implement\n * are determined by the tag type in a Mustache template.\n * @category Context\n */\nexport type ContextTypes =\n | Context\n // | JsonType\n | PartialTagContext\n | SectionTagContext\n | VariableTagContext;\n// | (Context | JsonType | SectionTagContextList)[];\n\n/**\n * A primitive JavaScript type that can be serialized in a JSON object.\n */\nexport type JsonType = boolean | number | string;\n\n/**\n * Implement one of these interfaces to provide replacements for\n * {@link https://mustache.github.io/mustache.5.html#Variables Partial tags}. See\n * {@link ContextTypes ContextTypes}.\n * @category Context\n * @category Partial\n */\nexport type PartialTagContext = PartialTagContextLambda;\n\n/**\n * Implement this function to asynchronously return a `ReadableStream` that contains a Mustache\n * template and its associated context that replaces a\n * {@link https://mustache.github.io/mustache.5.html#Variables Partial tag}.\n *\n * @example PartialTagContextLambda\n * ```\n * const lambda: PartialTagContextLambda = (tag) => {\n * context: { title: \"On Tyranny\" },\n * template: () => bookSummary.getReadableStream()\n * }\n * ```\n *\n * @param tag The partial tag that is being processed. `PartialTagContextLambda` returns the\n * template and the context that the partial tag references which are needed to render the partial\n * replacement.\n * @returns The template and context to render the partial that the `tag` parameter references.\n * @category Context\n * @category Partial\n */\nexport interface PartialTagContextLambda {\n (tag: Tag): Promise<PartialTagContextLambdaResult>;\n}\n\n/**\n * The result of invoking a {@link PartialTagContextLambda}.\n * @category Context\n * @category Partial\n */\nexport interface PartialTagContextLambdaResult {\n /** The optional context associated with this template. */\n context?: ContextTypes;\n /** When invoked `input` resolves to a stream containing the Mustache template that replaces a\n * partial tag. */\n input: () => Promise<ReadableStream>;\n}\n\n/**\n * Implement one of these interfaces to provide replacements for\n * {@link https://mustache.github.io/mustache.5.html#Sections Section tags}. See\n * {@link ContextTypes ContextTypes}.\n * @category Context\n * @category Section\n */\nexport type SectionTagContext = SectionTagCallback | SectionTagContextRecord[];\n\n/**\n * Provides zero or more items that will replace a\n * {@link https://mustache.github.io/mustache.5.html#Sections Section tag}. See\n * {@link SectionTagContext SectionTagContext}.\n * @category Context\n * @category Section\n */\nexport interface SectionTagContextRecord {\n [key: string]: JsonType | SectionTagContextRecord;\n}\n\n/**\n * When provided this callback is invoked when the\n * {@link https://mustache.github.io/mustache.5.html#Sections Section tag} is encountered. The\n * callback is passed the text contained within the section. If the section contains tags those tags\n * will **not** have been replaced.\n *\n * @remarks\n * Note that this is a callback function. The function provider is responsible for returning\n * rendered text that will be written directly to the output.\n *\n * @example\n * ```\n * const callback = context as SectionTagCallback;\n * const replacementText = callback(tag.content);\n * this.writeToOutput(replacementText);\n * ```\n *\n * @param tagContent The unrendered content of the section tag.\n * @returns A string of rendered text that will replace the content of the section tag.\n * @category Context\n * @category Section\n */\nexport interface SectionTagCallback {\n (tagContent: string): string;\n}\n\n/**\n * Represents a tag in a Mustache template providing information about a tag and its\n * characteristics.\n *\n * @remarks\n * Parts of a tag\n *\n * ```txt\n * >------tag------<\n * {{ > header }}\n *\n * >--value--<\n * {{ > header }}\n *\n * >S<>-key--<\n * {{ > header }}\n *\n * >TO< >TC<\n * {{ > header }}\n *\n * >-------------------tag--------------------<\n * {{ # section }} Hello! {{ / section }}\n *\n * >---start tag----< >----end tag----<\n * {{ # section }} Hello! {{ / section }}\n *\n * >--content--<\n * {{ # section }} Hello! {{ / section }}\n *\n * S = sigil or tag type\n * TO = tag open\n * TC = tag close\n * ```\n *\n * @property content When a \"tag\" has a start and end tag (e.g. a Section tag) `content` contains\n * the string between the two tags. When a tag is a single tag (like a Variable tag) `content` will\n * be `null`.\n * @property key The value that will be used to lookup a value in context. This key will have its\n * sigil removed, for example, if the template is \"{{ &title }}\" the `key` value is \"title\".\n * @property raw True when the tag has either three braces (e.g. \"{{{ name }}}\") or an ampersand\n * (like \"{{ &name }}\").\n * @property type The Tag type as described in the Mustache spec.\n * @property value The string between a tag's opening \"{{\" and its closing \"}}\". If the template is\n * \"{{ #items }}\" the `value` is \"#items\".\n */\nexport interface Tag {\n readonly content: string | null;\n readonly key: string;\n readonly raw: boolean;\n readonly type: ContentTagTagTypes | ValueTagTagTypes;\n readonly value: string;\n // process: () => Promise<void>;\n}\n\n/**\n * Defines how to access a template file.\n * - string: The name of a template file in the same directory as this module file. The name must\n * **not** include an extension.\n * - tuple: An array of two strings: the first element is the name of the template, as described\n * in the \"string\" type above. The second element is a relative path to the directory where the\n * template file is located; the path is relative to the location of this module file.\n */\nexport type TemplateName =\n | string\n | [templateName: string, templateFilename: string];\n\nexport type ValueTagTagTypes = (typeof ValueTagTypes)[number];\n\nexport const ValueTagTypes = [\n \"comment\", // {{!text}}\n \"implicit\", // `{{.}}`\n \"partial\", // `{{>tag}}`\n \"variable\",\n] as const;\n\n/**\n * Interfaces that can supply replacements for\n * {@link https://mustache.github.io/mustache.5.html#Variables variable tags}. See\n * {@link ContextTypes ContextTypes}.\n * @category Context\n * @category Variable\n */\nexport type VariableTagContext =\n | VariableTagContextPrimitive\n | VariableTagContextLambda\n | VariableTagContextRecord;\n\n/**\n * A function that resolves to the value that replaces a\n * {@link https://mustache.github.io/mustache.5.html#Variables variable tag}. See\n * {@link VariableTagContext VariableTagContext}.\n * @category Context\n * @category Variable\n */\nexport interface VariableTagContextLambda {\n (): Promise<VariableTagContextPrimitive | VariableTagContextRecord>;\n}\n\n/**\n * A {@link https://mustache.github.io/mustache.5.html#Variables variable tag} can be replaced by\n * these JavaScript primitives. See {@link VariableTagContext VariableTagContext}.\n * @category Context\n * @category Variable\n */\nexport type VariableTagContextPrimitive =\n | JsonType\n | Array<boolean | number | string>;\n\n/**\n * A {@link https://mustache.github.io/mustache.5.html#Variables variable tag} with a \"dotted name\"\n * can be replaced by a JavaScript object. See {@link VariableTagContext VariableTagContext}.\n * @category Context\n * @category Variable\n */\nexport interface VariableTagContextRecord {\n [key: string]: unknown;\n}\n\n/**\n * Invoke this function to write to the output `WritableStream`.\n */\nexport interface WriteToOutput {\n (text: string): Promise<void>;\n}\n"],"names":["ContentTagTypes","ValueTagTypes"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";;;;;;;;;;;IAIaA,eAAe;eAAfA;;IAoNAC,aAAa;eAAbA;;;AApNN,MAAMD,kBAAkB;IAC7B;IACA;IACA;IACA;IACA;CACD;AA8MM,MAAMC,gBAAgB;IAC3B;IACA;IACA;IACA;CACD"}