1+ /** @import { Base } from "./productions/base.js" */
2+ /** @import { Token } from "./tokeniser.js" */
3+
4+ /**
5+ * @template T
6+ * @param {T } arg
7+ */
18function noop ( arg ) {
29 return arg ;
310}
411
12+ /**
13+ * @typedef {object } TemplateContext
14+ * @property {Base } data
15+ * @property {Base } parent
16+ */
17+
18+ /**
19+ * @template T
20+ * @typedef {object } WriteTemplates
21+ * @property {(items: (T | string)[]) => T } wrap
22+ * @property {(trivia: string) => T } trivia
23+ * @property {(escaped: string, context: TemplateContext) => T } name
24+ * @property {(escaped: string, unescaped: string, context: Base) => T } reference
25+ * @property {(type: T) => T } type
26+ * @property {(name: string) => T } generic
27+ * @property {(keyword: string, context: TemplateContext) => T } nameless
28+ * @property {(inheritable: T) => T } inheritance
29+ * @property {(content: T, context: TemplateContext) => T } definition
30+ * @property {(content: T) => T } extendedAttribute
31+ * @property {(content: string) => T } extendedAttributeReference
32+ */
33+
34+ /** @type {WriteTemplates<string> } */
535const templates = {
36+ /** @type {(items: any[]) => string } */
637 wrap : ( items ) => items . join ( "" ) ,
738 trivia : noop ,
839 name : noop ,
@@ -16,7 +47,14 @@ const templates = {
1647 extendedAttributeReference : noop ,
1748} ;
1849
50+ /** @template T */
1951export class Writer {
52+ /** @type {WriteTemplates<T> } */
53+ ts ;
54+
55+ /**
56+ * @param {WriteTemplates<T> } ts
57+ */
2058 constructor ( ts ) {
2159 this . ts = Object . assign ( { } , templates , ts ) ;
2260 }
@@ -25,8 +63,7 @@ export class Writer {
2563 * @param {string } raw
2664 * @param {object } options
2765 * @param {string } [options.unescaped]
28- * @param {import("./productions/base.js").Base } [options.context]
29- * @returns
66+ * @param {Base } [options.context]
3067 */
3168 reference ( raw , { unescaped, context } ) {
3269 if ( ! unescaped ) {
@@ -36,16 +73,30 @@ export class Writer {
3673 }
3774
3875 /**
39- * @param {import("./tokeniser.js").Token } t
40- * @param {Function } wrapper
41- * @param {...any } args
42- * @returns
76+ * @overload
77+ * @param {Token } t
78+ * @param {(tokenValue: string, options: { context: Base }) => T | string } wrapper
79+ * @param {object } options
80+ * @param {Base } options.context
81+ * @returns {T | string }
82+ */
83+ /**
84+ * @overload
85+ * @param {Token } t
86+ * @param {(tokenValue: string, context: TemplateContext) => T | string } [wrapper]
87+ * @param {TemplateContext } [context]
88+ * @returns {T | string }
89+ */
90+ /**
91+ * @param {Token } t
92+ * @param {(tokenValue: string, context: any) => T | string } [wrapper]
93+ * @param {any } [context]
4394 */
44- token ( t , wrapper = noop , ... args ) {
95+ token ( t , wrapper = noop , context ) {
4596 if ( ! t ) {
4697 return "" ;
4798 }
48- const value = wrapper ( t . value , ... args ) ;
99+ const value = wrapper ( t . value , context ) ;
49100 return this . ts . wrap ( [ this . ts . trivia ( t . trivia ) , value ] ) ;
50101 }
51102
@@ -65,9 +116,29 @@ export class Writer {
65116 }
66117}
67118
119+ /**
120+ * @overload
121+ * @param {Base[] } ast
122+ * @returns {string }
123+ */
124+ /**
125+ * @template T
126+ * @overload
127+ * @param {Base[] } ast
128+ * @param {object } options
129+ * @param {WriteTemplates<T> } [options.templates]
130+ * @returns {T }
131+ */
132+ /**
133+ * @param {Base[] } ast
134+ * @param {object } options
135+ * @param {WriteTemplates<unknown> } [options.templates]
136+ * @returns {unknown }
137+ */
68138export function write ( ast , { templates : ts = templates } = { } ) {
69139 ts = Object . assign ( { } , templates , ts ) ;
70140
141+ /** @type {Writer<unknown> } */
71142 const w = new Writer ( ts ) ;
72143
73144 return ts . wrap ( ast . map ( ( it ) => it . write ( w ) ) ) ;
0 commit comments