This commit is contained in:
fenris 2024-02-08 18:10:46 +01:00
parent 95469e839f
commit f751b57ab9
17 changed files with 540 additions and 370 deletions

View file

@ -1,12 +1,6 @@
{ {
"kind": "section", "definitions": {
"data": { "tetrahedron": {
"title": "Polyhedra",
"content": {
"kind": "group",
"data": {
"members": [
{
"kind": "section", "kind": "section",
"data": { "data": {
"title": "Tetrahedron", "title": "Tetrahedron",
@ -37,7 +31,7 @@
} }
} }
}, },
{ "hexahedron": {
"kind": "section", "kind": "section",
"data": { "data": {
"title": "Hexahedron", "title": "Hexahedron",
@ -68,7 +62,7 @@
} }
} }
}, },
{ "octahedron": {
"kind": "section", "kind": "section",
"data": { "data": {
"title": "Octahedron", "title": "Octahedron",
@ -99,7 +93,7 @@
} }
} }
}, },
{ "dodecahedron": {
"kind": "section", "kind": "section",
"data": { "data": {
"title": "Dodecahedron", "title": "Dodecahedron",
@ -130,7 +124,7 @@
} }
} }
}, },
{ "icosahedron": {
"kind": "section", "kind": "section",
"data": { "data": {
"title": "Icosahedron", "title": "Icosahedron",
@ -161,9 +155,53 @@
} }
} }
} }
},
"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"
}
}
] ]
} }
} }
} }
} }
}
}

51
source/document.ts Normal file
View file

@ -0,0 +1,51 @@
/**
*/
class type_document
{
/**
*/
public readonly definitions : Record<string, type_object>;
/**
*/
public readonly content_title : string;
/**
*/
public readonly content_main : type_object;
/**
*/
public constructor(
definitions : Record<string, type_object>,
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"])
));
}
}

View file

@ -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);
}
}

View file

@ -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))
}
)
)
);

View file

@ -1,30 +0,0 @@
/**
*/
type type_element_list_data = {
items : Array<type_element>;
};
/**
*/
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"],
}
)
)
);

View file

@ -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"],
}
)
)
);

View file

@ -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"],
}
)
)
);

View file

@ -46,12 +46,13 @@ async function main(args_raw : Array<string>) : Promise<void>
} }
else else
{ {
const element_raw : string = lib_plankton.json.decode(await lib_plankton.file.read(args.input)) const document_raw : string = lib_plankton.json.decode(await lib_plankton.file.read(args.input))
let element : type_element = element_make(element_raw); const document : type_document = type_document.from_raw(document_raw);
// let object : type_object = object_make(document_raw["content"]["main"]);
const output : type_output<string> = output_make<string>({"kind": args.output, "data": {}}); const output : type_output<string> = output_make<string>({"kind": args.output, "data": {}});
const result : string = output.render_element(element); const result : string = output.render_document(document);
process.stdout.write(result + "\n"); process.stdout.write(result + "\n");
} }
} }

61
source/objects/base.ts Normal file
View file

@ -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);
}
}

View file

@ -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))
}
)
)
);

View file

@ -0,0 +1,30 @@
/**
*/
type type_object_list_data = {
items : Array<type_object>;
};
/**
*/
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"],
}
)
)
);

View file

@ -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"],
}
)
)
);

View file

@ -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"],
}
)
)
);

View file

@ -6,8 +6,16 @@ interface type_output<type_result> extends lib_plankton.call.type_coproduct
/** /**
*/ */
render_element( render_object(
element : type_element object : type_object
) : type_result
;
/**
*/
render_document(
document : type_document
) : type_result ) : type_result
; ;

View file

@ -9,23 +9,23 @@ class type_output_html implements type_output<string>
/** /**
*/ */
private render_element_internal( private render_object_internal(
element : type_element, object : type_object,
options : { options : {
depth ?: int;
level ?: int; level ?: int;
depth ?: int;
} = {} } = {}
) : lib_plankton.xml.class_node ) : lib_plankton.xml.class_node
{ {
options = Object.assign( options = Object.assign(
{ {
"depth": 0,
"level": 0, "level": 0,
"depth": 0,
}, },
options options
); );
return lib_plankton.call.distinguish<lib_plankton.xml.class_node>( return lib_plankton.call.distinguish<lib_plankton.xml.class_node>(
element, object,
{ {
"text": ({"content": content}) => new lib_plankton.xml.class_node_complex( "text": ({"content": content}) => new lib_plankton.xml.class_node_complex(
"span", "span",
@ -44,7 +44,7 @@ class type_output_html implements type_output<string>
( (
members members
.map( .map(
x => this.render_element_internal( x => this.render_object_internal(
x, x,
{ {
"depth": options.depth, "depth": options.depth,
@ -67,11 +67,11 @@ class type_output_html implements type_output<string>
new lib_plankton.xml.class_node_text(title), new lib_plankton.xml.class_node_text(title),
] ]
), ),
this.render_element_internal( this.render_object_internal(
content, content,
{ {
"depth": (options.depth + 1),
"level": (options.level + 1), "level": (options.level + 1),
"depth": (options.depth + 1),
} }
), ),
] ]
@ -88,7 +88,7 @@ class type_output_html implements type_output<string>
"li", "li",
{}, {},
[ [
this.render_element_internal( this.render_object_internal(
item, item,
{ {
"level": options.level, "level": options.level,
@ -102,15 +102,15 @@ class type_output_html implements type_output<string>
), ),
}, },
{ {
"fallback": (element) => new lib_plankton.xml.class_node_complex( "fallback": (object) => new lib_plankton.xml.class_node_complex(
"pre", "pre",
{ {
"class": "sd-unhandled", "class": "sd-unhandled",
"rel": element.kind, "rel": object.kind,
}, },
[ [
new lib_plankton.xml.class_node_text( 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<string>
/** /**
* @implementation * @implementation
*/ */
public render_element( public render_object(
element : type_element object : type_object
) : string ) : 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(
"<!DOCTYPE html>\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()
}
);
} }
} }

View file

@ -9,20 +9,32 @@ class type_output_json implements type_output<string>
/** /**
*/ */
public render_element( public render_object(
element : type_element object : type_object
) : string ) : string
{ {
return lib_plankton.call.distinguish<string>( return lib_plankton.call.distinguish<string>(
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 ""
}
} }

View file

@ -24,11 +24,12 @@ _default: ${dir_build}/sd
${dir_temp}/sd-unlinked.js: \ ${dir_temp}/sd-unlinked.js: \
${dir_lib}/plankton/plankton.d.ts \ ${dir_lib}/plankton/plankton.d.ts \
${dir_source}/base.ts \ ${dir_source}/base.ts \
${dir_source}/elements/base.ts \ ${dir_source}/objects/base.ts \
${dir_source}/elements/implementations/text.ts \ ${dir_source}/objects/implementations/text.ts \
${dir_source}/elements/implementations/group.ts \ ${dir_source}/objects/implementations/group.ts \
${dir_source}/elements/implementations/section.ts \ ${dir_source}/objects/implementations/section.ts \
${dir_source}/elements/implementations/list.ts \ ${dir_source}/objects/implementations/list.ts \
${dir_source}/document.ts \
${dir_source}/outputs/base.ts \ ${dir_source}/outputs/base.ts \
${dir_source}/outputs/implementations/json.ts \ ${dir_source}/outputs/implementations/json.ts \
${dir_source}/outputs/implementations/html.ts \ ${dir_source}/outputs/implementations/html.ts \