From f751b57ab9f292d39a2928792e6000cf02f40d9d Mon Sep 17 00:00:00 2001 From: Fenris Wolf Date: Thu, 8 Feb 2024 18:10:46 +0100 Subject: [PATCH] [int] --- misc/example-polyhedra.sd.json | 354 ++++++++++++--------- source/document.ts | 51 +++ source/elements/base.ts | 61 ---- source/elements/implementations/group.ts | 30 -- source/elements/implementations/list.ts | 30 -- source/elements/implementations/section.ts | 32 -- source/elements/implementations/text.ts | 30 -- source/main.ts | 7 +- source/objects/base.ts | 61 ++++ source/objects/implementations/group.ts | 30 ++ source/objects/implementations/list.ts | 30 ++ source/objects/implementations/section.ts | 32 ++ source/objects/implementations/text.ts | 30 ++ source/outputs/base.ts | 12 +- source/outputs/implementations/html.ts | 89 +++++- source/outputs/implementations/json.ts | 20 +- tools/makefile | 11 +- 17 files changed, 540 insertions(+), 370 deletions(-) create mode 100644 source/document.ts delete mode 100644 source/elements/base.ts delete mode 100644 source/elements/implementations/group.ts delete mode 100644 source/elements/implementations/list.ts delete mode 100644 source/elements/implementations/section.ts delete mode 100644 source/elements/implementations/text.ts create mode 100644 source/objects/base.ts create mode 100644 source/objects/implementations/group.ts create mode 100644 source/objects/implementations/list.ts create mode 100644 source/objects/implementations/section.ts create mode 100644 source/objects/implementations/text.ts diff --git a/misc/example-polyhedra.sd.json b/misc/example-polyhedra.sd.json index 7954476..1c10b26 100644 --- a/misc/example-polyhedra.sd.json +++ b/misc/example-polyhedra.sd.json @@ -1,169 +1,207 @@ { - "kind": "section", - "data": { - "title": "Polyhedra", - "content": { - "kind": "group", + "definitions": { + "tetrahedron": { + "kind": "section", "data": { - "members": [ - { - "kind": "section", - "data": { - "title": "Tetrahedron", - "content": { - "kind": "list", + "title": "Tetrahedron", + "content": { + "kind": "list", + "data": { + "items": [ + { + "kind": "text", "data": { - "items": [ - { - "kind": "text", - "data": { - "content": "vertices: 4" - } - }, - { - "kind": "text", - "data": { - "content": "faces: 4" - } - }, - { - "kind": "text", - "data": { - "content": "edges: 6" - } - } - ] + "content": "vertices: 4" + } + }, + { + "kind": "text", + "data": { + "content": "faces: 4" + } + }, + { + "kind": "text", + "data": { + "content": "edges: 6" } } - } - }, - { - "kind": "section", - "data": { - "title": "Hexahedron", - "content": { - "kind": "list", - "data": { - "items": [ - { - "kind": "text", - "data": { - "content": "vertices: 6" - } - }, - { - "kind": "text", - "data": { - "content": "faces: 8" - } - }, - { - "kind": "text", - "data": { - "content": "edges: 12" - } - } - ] - } - } - } - }, - { - "kind": "section", - "data": { - "title": "Octahedron", - "content": { - "kind": "list", - "data": { - "items": [ - { - "kind": "text", - "data": { - "content": "vertices: 6" - } - }, - { - "kind": "text", - "data": { - "content": "faces: 8" - } - }, - { - "kind": "text", - "data": { - "content": "edges: 12" - } - } - ] - } - } - } - }, - { - "kind": "section", - "data": { - "title": "Dodecahedron", - "content": { - "kind": "list", - "data": { - "items": [ - { - "kind": "text", - "data": { - "content": "vertices: 20" - } - }, - { - "kind": "text", - "data": { - "content": "faces: 12" - } - }, - { - "kind": "text", - "data": { - "content": "edges: 30" - } - } - ] - } - } - } - }, - { - "kind": "section", - "data": { - "title": "Icosahedron", - "content": { - "kind": "list", - "data": { - "items": [ - { - "kind": "text", - "data": { - "content": "vertices: 12" - } - }, - { - "kind": "text", - "data": { - "content": "faces: 20" - } - }, - { - "kind": "text", - "data": { - "content": "edges: 30" - } - } - ] - } - } - } + ] } - ] + } + } + }, + "hexahedron": { + "kind": "section", + "data": { + "title": "Hexahedron", + "content": { + "kind": "list", + "data": { + "items": [ + { + "kind": "text", + "data": { + "content": "vertices: 6" + } + }, + { + "kind": "text", + "data": { + "content": "faces: 8" + } + }, + { + "kind": "text", + "data": { + "content": "edges: 12" + } + } + ] + } + } + } + }, + "octahedron": { + "kind": "section", + "data": { + "title": "Octahedron", + "content": { + "kind": "list", + "data": { + "items": [ + { + "kind": "text", + "data": { + "content": "vertices: 6" + } + }, + { + "kind": "text", + "data": { + "content": "faces: 8" + } + }, + { + "kind": "text", + "data": { + "content": "edges: 12" + } + } + ] + } + } + } + }, + "dodecahedron": { + "kind": "section", + "data": { + "title": "Dodecahedron", + "content": { + "kind": "list", + "data": { + "items": [ + { + "kind": "text", + "data": { + "content": "vertices: 20" + } + }, + { + "kind": "text", + "data": { + "content": "faces: 12" + } + }, + { + "kind": "text", + "data": { + "content": "edges: 30" + } + } + ] + } + } + } + }, + "icosahedron": { + "kind": "section", + "data": { + "title": "Icosahedron", + "content": { + "kind": "list", + "data": { + "items": [ + { + "kind": "text", + "data": { + "content": "vertices: 12" + } + }, + { + "kind": "text", + "data": { + "content": "faces: 20" + } + }, + { + "kind": "text", + "data": { + "content": "edges: 30" + } + } + ] + } + } } } + }, + "content": { + "title": "Polyhedra", + "main": { + "kind": "section", + "data": { + "title": "Polyhedra", + "content": { + "kind": "group", + "data": { + "members": [ + { + "kind": "reference", + "data": { + "name": "tetrahedron" + } + }, + { + "kind": "reference", + "data": { + "name": "hexahedron" + } + }, + { + "kind": "reference", + "data": { + "name": "octahedron" + } + }, + { + "kind": "reference", + "data": { + "name": "dodecahedron" + } + }, + { + "kind": "reference", + "data": { + "name": "icosahedron" + } + } + ] + } + } + } + } + } } diff --git a/source/document.ts b/source/document.ts new file mode 100644 index 0000000..4503ed2 --- /dev/null +++ b/source/document.ts @@ -0,0 +1,51 @@ +/** + */ +class type_document +{ + + /** + */ + public readonly definitions : Record; + + + /** + */ + public readonly content_title : string; + + + /** + */ + public readonly content_main : type_object; + + + /** + */ + public constructor( + definitions : Record, + content_title : string, + content_main : type_object + ) + { + this.definitions = definitions; + this.content_title = content_title; + this.content_main = content_main; + } + + + /** + */ + public static from_raw( + document_raw : any + ) : type_document + { + return (new type_document( + Object.fromEntries( + Object.entries(document_raw["definitions"]) + .map(([name, object_raw]) => ([name, object_make(object_raw)])) + ), + document_raw["content"]["title"], + object_make(document_raw["content"]["main"]) + )); + } + +} diff --git a/source/elements/base.ts b/source/elements/base.ts deleted file mode 100644 index 117e380..0000000 --- a/source/elements/base.ts +++ /dev/null @@ -1,61 +0,0 @@ - -/** - */ -interface type_element extends lib_plankton.call.type_coproduct -{ -} - - -/** - */ -let element_kind_pool : Record< - string, - ( - ( - data : any, - make : ((raw : any) => type_element) - ) - => - type_element - ) -> = {}; - - -/** - */ -function element_kind_register( - name : string, - factory : ( - (data : any, make : ((raw : any) => type_element)) - => - type_element - ) -) : void -{ - if (name in element_kind_pool) - { - throw (new Error("kind '" + name + "' already registered")); - } - else - { - element_kind_pool[name] = factory; - } -} - - -/** - */ -function element_make( - raw : any -) : type_element -{ - if (! (raw["kind"] in element_kind_pool)) - { - throw (new Error("kind '" + raw["kind"] + "' not registered")); - } - else - { - return element_kind_pool[raw["kind"]](raw["data"], element_make); - } -} - diff --git a/source/elements/implementations/group.ts b/source/elements/implementations/group.ts deleted file mode 100644 index 094b629..0000000 --- a/source/elements/implementations/group.ts +++ /dev/null @@ -1,30 +0,0 @@ - -/** - */ -type type_element_group_data = { - members : type_element; -}; - - -/** - */ -class type_element_group implements type_element -{ - public readonly kind : string = "group"; - public readonly data : type_element_group_data; - public constructor(data : type_element_group_data) {this.data = data;} -} - - -/** - */ -element_kind_register( - "group", - (data, sub) => ( - new type_element_group( - { - "members": data["members"].map(x => sub(x)) - } - ) - ) -); diff --git a/source/elements/implementations/list.ts b/source/elements/implementations/list.ts deleted file mode 100644 index 90bf32a..0000000 --- a/source/elements/implementations/list.ts +++ /dev/null @@ -1,30 +0,0 @@ - -/** - */ -type type_element_list_data = { - items : Array; -}; - - -/** - */ -class type_element_list implements type_element -{ - public readonly kind : string = "list"; - public readonly data : type_element_list_data; - public constructor(data : type_element_list_data) {this.data = data;} -} - - -/** - */ -element_kind_register( - "list", - (data) => ( - new type_element_list( - { - "items": data["items"], - } - ) - ) -); diff --git a/source/elements/implementations/section.ts b/source/elements/implementations/section.ts deleted file mode 100644 index 942759c..0000000 --- a/source/elements/implementations/section.ts +++ /dev/null @@ -1,32 +0,0 @@ - -/** - */ -type type_element_section_data = { - title : string; - content : type_element; -}; - - -/** - */ -class type_element_section implements type_element -{ - public readonly kind : string = "section"; - public readonly data : type_element_section_data; - public constructor(data : type_element_section_data) {this.data = data;} -} - - -/** - */ -element_kind_register( - "section", - (data) => ( - new type_element_section( - { - "title": data["title"], - "content": data["content"], - } - ) - ) -); diff --git a/source/elements/implementations/text.ts b/source/elements/implementations/text.ts deleted file mode 100644 index e3a5a80..0000000 --- a/source/elements/implementations/text.ts +++ /dev/null @@ -1,30 +0,0 @@ - -/** - */ -type type_element_text_data = { - content : string; -}; - - -/** - */ -class type_element_text implements type_element -{ - public readonly kind : string = "text"; - public readonly data : type_element_text_data; - public constructor(data : type_element_text_data) {this.data = data;} -} - - -/** - */ -element_kind_register( - "text", - (data) => ( - new type_element_text( - { - "content": data["content"], - } - ) - ) -); diff --git a/source/main.ts b/source/main.ts index 6ac89bf..cd55061 100644 --- a/source/main.ts +++ b/source/main.ts @@ -46,12 +46,13 @@ async function main(args_raw : Array) : Promise } else { - const element_raw : string = lib_plankton.json.decode(await lib_plankton.file.read(args.input)) - let element : type_element = element_make(element_raw); + const document_raw : string = lib_plankton.json.decode(await lib_plankton.file.read(args.input)) + const document : type_document = type_document.from_raw(document_raw); + // let object : type_object = object_make(document_raw["content"]["main"]); const output : type_output = output_make({"kind": args.output, "data": {}}); - const result : string = output.render_element(element); + const result : string = output.render_document(document); process.stdout.write(result + "\n"); } } diff --git a/source/objects/base.ts b/source/objects/base.ts new file mode 100644 index 0000000..1c8badc --- /dev/null +++ b/source/objects/base.ts @@ -0,0 +1,61 @@ + +/** + */ +interface type_object extends lib_plankton.call.type_coproduct +{ +} + + +/** + */ +let object_kind_pool : Record< + string, + ( + ( + data : any, + make : ((raw : any) => type_object) + ) + => + type_object + ) +> = {}; + + +/** + */ +function object_kind_register( + name : string, + factory : ( + (data : any, make : ((raw : any) => type_object)) + => + type_object + ) +) : void +{ + if (name in object_kind_pool) + { + throw (new Error("kind '" + name + "' already registered")); + } + else + { + object_kind_pool[name] = factory; + } +} + + +/** + */ +function object_make( + raw : any +) : type_object +{ + if (! (raw["kind"] in object_kind_pool)) + { + throw (new Error("kind '" + raw["kind"] + "' not registered")); + } + else + { + return object_kind_pool[raw["kind"]](raw["data"], object_make); + } +} + diff --git a/source/objects/implementations/group.ts b/source/objects/implementations/group.ts new file mode 100644 index 0000000..dbcbc3c --- /dev/null +++ b/source/objects/implementations/group.ts @@ -0,0 +1,30 @@ + +/** + */ +type type_object_group_data = { + members : type_object; +}; + + +/** + */ +class type_object_group implements type_object +{ + public readonly kind : string = "group"; + public readonly data : type_object_group_data; + public constructor(data : type_object_group_data) {this.data = data;} +} + + +/** + */ +object_kind_register( + "group", + (data, sub) => ( + new type_object_group( + { + "members": data["members"].map(x => sub(x)) + } + ) + ) +); diff --git a/source/objects/implementations/list.ts b/source/objects/implementations/list.ts new file mode 100644 index 0000000..5895742 --- /dev/null +++ b/source/objects/implementations/list.ts @@ -0,0 +1,30 @@ + +/** + */ +type type_object_list_data = { + items : Array; +}; + + +/** + */ +class type_object_list implements type_object +{ + public readonly kind : string = "list"; + public readonly data : type_object_list_data; + public constructor(data : type_object_list_data) {this.data = data;} +} + + +/** + */ +object_kind_register( + "list", + (data) => ( + new type_object_list( + { + "items": data["items"], + } + ) + ) +); diff --git a/source/objects/implementations/section.ts b/source/objects/implementations/section.ts new file mode 100644 index 0000000..b58b8a8 --- /dev/null +++ b/source/objects/implementations/section.ts @@ -0,0 +1,32 @@ + +/** + */ +type type_object_section_data = { + title : string; + content : type_object; +}; + + +/** + */ +class type_object_section implements type_object +{ + public readonly kind : string = "section"; + public readonly data : type_object_section_data; + public constructor(data : type_object_section_data) {this.data = data;} +} + + +/** + */ +object_kind_register( + "section", + (data) => ( + new type_object_section( + { + "title": data["title"], + "content": data["content"], + } + ) + ) +); diff --git a/source/objects/implementations/text.ts b/source/objects/implementations/text.ts new file mode 100644 index 0000000..908f274 --- /dev/null +++ b/source/objects/implementations/text.ts @@ -0,0 +1,30 @@ + +/** + */ +type type_object_text_data = { + content : string; +}; + + +/** + */ +class type_object_text implements type_object +{ + public readonly kind : string = "text"; + public readonly data : type_object_text_data; + public constructor(data : type_object_text_data) {this.data = data;} +} + + +/** + */ +object_kind_register( + "text", + (data) => ( + new type_object_text( + { + "content": data["content"], + } + ) + ) +); diff --git a/source/outputs/base.ts b/source/outputs/base.ts index 8205ec3..aff8408 100644 --- a/source/outputs/base.ts +++ b/source/outputs/base.ts @@ -6,8 +6,16 @@ interface type_output extends lib_plankton.call.type_coproduct /** */ - render_element( - element : type_element + render_object( + object : type_object + ) : type_result + ; + + + /** + */ + render_document( + document : type_document ) : type_result ; diff --git a/source/outputs/implementations/html.ts b/source/outputs/implementations/html.ts index 9b0f754..3c8834f 100644 --- a/source/outputs/implementations/html.ts +++ b/source/outputs/implementations/html.ts @@ -9,23 +9,23 @@ class type_output_html implements type_output /** */ - private render_element_internal( - element : type_element, + private render_object_internal( + object : type_object, options : { - depth ?: int; level ?: int; + depth ?: int; } = {} ) : lib_plankton.xml.class_node { options = Object.assign( { - "depth": 0, "level": 0, + "depth": 0, }, options ); return lib_plankton.call.distinguish( - element, + object, { "text": ({"content": content}) => new lib_plankton.xml.class_node_complex( "span", @@ -44,7 +44,7 @@ class type_output_html implements type_output ( members .map( - x => this.render_element_internal( + x => this.render_object_internal( x, { "depth": options.depth, @@ -67,11 +67,11 @@ class type_output_html implements type_output new lib_plankton.xml.class_node_text(title), ] ), - this.render_element_internal( + this.render_object_internal( content, { - "depth": (options.depth + 1), "level": (options.level + 1), + "depth": (options.depth + 1), } ), ] @@ -88,7 +88,7 @@ class type_output_html implements type_output "li", {}, [ - this.render_element_internal( + this.render_object_internal( item, { "level": options.level, @@ -102,15 +102,15 @@ class type_output_html implements type_output ), }, { - "fallback": (element) => new lib_plankton.xml.class_node_complex( + "fallback": (object) => new lib_plankton.xml.class_node_complex( "pre", { "class": "sd-unhandled", - "rel": element.kind, + "rel": object.kind, }, [ new lib_plankton.xml.class_node_text( - JSON.stringify(element, undefined, " "), + JSON.stringify(object, undefined, " "), ) ] ), @@ -122,11 +122,70 @@ class type_output_html implements type_output /** * @implementation */ - public render_element( - element : type_element + public render_object( + object : type_object ) : string { - return this.render_element_internal(element).compile(); + return this.render_object_internal(object).compile(); + } + + + /** + * @implementation + */ + public render_document( + document : type_document + ) : string + { + return lib_plankton.string.coin( + "\n{{html}}", + { + "html": new lib_plankton.xml.class_node_complex( + "html", + {}, + [ + new lib_plankton.xml.class_node_complex( + "head", + { + }, + [ + new lib_plankton.xml.class_node_complex( + "meta", + { + "charset": "utf-8", + }, + [ + ] + ), + new lib_plankton.xml.class_node_complex( + "title", + { + }, + [ + new lib_plankton.xml.class_node_text( + document.content_title + ), + ] + ), + ] + ), + new lib_plankton.xml.class_node_complex( + "body", + { + }, + [ + this.render_object_internal( + document.content_main, + { + "depth": 1, + } + ), + ] + ) + ] + ).compile() + } + ); } } diff --git a/source/outputs/implementations/json.ts b/source/outputs/implementations/json.ts index 84a0b61..f1056a8 100644 --- a/source/outputs/implementations/json.ts +++ b/source/outputs/implementations/json.ts @@ -9,20 +9,32 @@ class type_output_json implements type_output /** */ - public render_element( - element : type_element + public render_object( + object : type_object ) : string { return lib_plankton.call.distinguish( - element, + object, { }, { - "fallback": (element) => JSON.stringify(element, undefined, "\t"), + "fallback": (object) => JSON.stringify(object, undefined, "\t"), } ); } + + /** + * @todo + * @implementation + */ + public render_document( + document : type_document + ) : string + { + return "" + } + } diff --git a/tools/makefile b/tools/makefile index 93a6c27..ef34c32 100644 --- a/tools/makefile +++ b/tools/makefile @@ -24,11 +24,12 @@ _default: ${dir_build}/sd ${dir_temp}/sd-unlinked.js: \ ${dir_lib}/plankton/plankton.d.ts \ ${dir_source}/base.ts \ - ${dir_source}/elements/base.ts \ - ${dir_source}/elements/implementations/text.ts \ - ${dir_source}/elements/implementations/group.ts \ - ${dir_source}/elements/implementations/section.ts \ - ${dir_source}/elements/implementations/list.ts \ + ${dir_source}/objects/base.ts \ + ${dir_source}/objects/implementations/text.ts \ + ${dir_source}/objects/implementations/group.ts \ + ${dir_source}/objects/implementations/section.ts \ + ${dir_source}/objects/implementations/list.ts \ + ${dir_source}/document.ts \ ${dir_source}/outputs/base.ts \ ${dir_source}/outputs/implementations/json.ts \ ${dir_source}/outputs/implementations/html.ts \