Skip to content

Commit

Permalink
feat(compile): replace the XML parser and JSON data format
Browse files Browse the repository at this point in the history
  • Loading branch information
lc-soft committed Aug 21, 2023
1 parent 8ac47d8 commit c067504
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 89 deletions.
67 changes: 26 additions & 41 deletions lib/compiler/json.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,22 @@ function toIdent(str) {
return str.replace(/[^a-zA-Z0-9]/g, "_");
}

function compile(jsonData, { filePath, indent = 8 }) {
function compileData(rootNode, { filePath, indent = 8 }) {
let count = 0;
const { name: fileName, base: fileBase } = path.parse(filePath);
const identPrefix = toIdent(fileName);
const refs = [];
const globalLines = [];
const resourceLines = [];
const refs = [];
const templateLines = [];
const indentStr = " ".repeat(indent);

function translateNode(name, data) {
function translateNode(node) {
let ident;
let type;
let text = "";
let attrs = {};
let children = [];
let widgetType;
const attrs = node.attributes || {};

if (typeof data === "string") {
text = data;
} else if (data) {
Object.keys(data).forEach((k) => {
if (k.startsWith("@")) {
attrs[k.substring(1)] = data[k];
return;
}
if (k.startsWith("#")) {
if (k === "#text") {
text = data[k];
}
return;
}
if (Array.isArray(data[k])) {
children.push(...data[k].map((item) => [k, item]));
return;
}
children.push([k, data[k]]);
});
}
switch (name) {
switch (node.name) {
case "ui":
ident = `${identPrefix}_parent`;
case "lcui-app":
Expand All @@ -59,7 +36,7 @@ function compile(jsonData, { filePath, indent = 8 }) {
}
if (["text/css", "text/scss", "text/sass"].includes(attrs.type)) {
const options = { filePath };
let cssText = text;
let cssText = node.text;

if (attrs.src) {
options.filePath = path.resolve(filePath, "..", attrs.src);
Expand All @@ -72,6 +49,9 @@ function compile(jsonData, { filePath, indent = 8 }) {
? css.compile(cssText, options)
: sass.compile(cssText, options);
ident = cssCode.substring("static const char *".length).split(" ")[0];
if (node.comment) {
globalLines.push(`/** ${node.comment} */`);
}
globalLines.push(cssCode);
resourceLines.push(
`ui_load_css_string(${ident}, ${JSON.stringify(
Expand All @@ -81,10 +61,10 @@ function compile(jsonData, { filePath, indent = 8 }) {
}
return;
default:
if (["w", "widget"].includes(name)) {
type = attrs.type;
if (["w", "widget"].includes(node.name)) {
widgetType = attrs.type;
} else {
type = name;
widgetType = node.name;
}
if (attrs.ref && typeof attrs.ref === "string") {
ident = toIdent(attrs.ref);
Expand All @@ -94,7 +74,9 @@ function compile(jsonData, { filePath, indent = 8 }) {
ident = `w[${count++}]`;
}
templateLines.push(
`${ident} = ui_create_widget(${type ? `"${type}"` : "NULL"});`
`${ident} = ui_create_widget(${
widgetType ? `"${widgetType}"` : "NULL"
});`
);
Object.keys(attrs).forEach((attrName) => {
if (attrName === "class") {
Expand All @@ -114,23 +96,23 @@ function compile(jsonData, { filePath, indent = 8 }) {
)});`
);
});
if (text) {
if (node.text) {
templateLines.push(
`ui_widget_set_text(${ident}, ${JSON.stringify(text)});`
`ui_widget_set_text(${ident}, ${JSON.stringify(node.text)});`
);
}
break;
}
children
.map(([childName, childData]) => translateNode(childName, childData))
.forEach((childIdent) => {
if (Array.isArray(node.children)) {
node.children.map(translateNode).forEach((childIdent) => {
if (ident && childIdent) {
templateLines.push(`ui_widget_append(${ident}, ${childIdent});`);
}
});
}
return ident;
}
translateNode("lcui-app", jsonData);
translateNode(rootNode);
return [
`/** This file is generated from ${fileBase} */`,
"",
Expand Down Expand Up @@ -169,5 +151,8 @@ function compile(jsonData, { filePath, indent = 8 }) {

export default {
test: /\.json$/,
compile,
compileData,
compile(input, options) {
return compileData(JSON.parse(input), options);
},
};
17 changes: 9 additions & 8 deletions lib/compiler/xml.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { XMLParser } from "fast-xml-parser";
import { xml2js } from "xml-js";
import json from "./json.js";

export default {
test: /\.xml$/,
compile(input, options) {
const parser = new XMLParser({
ignoreAttributes: false,
ignorePiTags: true,
allowBooleanAttributes: true,
attributeNamePrefix: "@",
const data = xml2js(input, {
ignoreCdata: true,
ignoreDeclaration: true,
ignoreComment: true,
ignoreInstruction: true,
ignoreDoctype: true,
elementsKey: 'children'
});
const xmlData = parser.parse(input);
return json.compile(xmlData["lcui-app"], options);
return json.compileData(data, options);
},
};
2 changes: 1 addition & 1 deletion lib/compiler/yaml.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ export default {
test: /\.ya?ml$/,
compile(input, options) {
const data = parse(input);
return json.compile(data, options);
return json.compileData(data, options);
},
};
58 changes: 36 additions & 22 deletions test/fixtures/resource/src/ui/home.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,44 @@
{
"resource": [
"name": "lcui-app",
"children": [
{
"@type": "text/css",
"@src": "home.css"
"name": "resource",
"attributes": { "type": "text/css", "src": "home.css" }
},
{
"@type": "application/font-ttf",
"@src": "iconfont.ttf"
}
],
"ui": {
"text": [
"Enter a message and save it.",
{
"#text": "Message has been saved!",
"@ref": "feedback",
"@class": "feedback"
"name": "resource",
"attributes": {
"type": "application/font-ttf",
"src": "iconfont.ttf"
}
],
"textedit": {
"@ref": "input-message",
"@placeholder": "eg: hello, world!"
},
"button": {
"#text": "Save",
"@ref": "btn-save-message"
{
"name": "ui",
"children": [
{
"name": "text",
"children": [
{ "type": "text", "text": "Enter a message and save it." }
]
},
{
"name": "textedit",
"attributes": {
"ref": "input-message",
"placeholder": "eg: hello, world!"
}
},
{
"name": "button",
"attributes": { "ref": "btn-save-message" },
"children": [{ "type": "text", "text": "Save" }]
},
{
"name": "text",
"attributes": { "ref": "feedback", "class": "feedback" },
"children": [{ "type": "text", "text": "Message has been saved!" }]
}
]
}
}
]
}
54 changes: 54 additions & 0 deletions test/fixtures/resource/src/ui/home.json.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/** This file is generated from Home.json */

#include <ui.h>

typedef struct {
ui_widget_t *input_message;
ui_widget_t *btn_save_message;
ui_widget_t *feedback;
} Home_refs_t;

static const char *css_str_0 = "\
root {\
background-color: #f6f8fa;\
}\
\
.feedback {\
color: #28a745;\
font-size: 12px;\
margin-top: 5px;\
}\
\
";


static void Home_load_template(ui_widget_t *Home_parent, Home_refs_t *refs)
{
ui_widget_t *w[4];

w[0] = ui_create_widget("text");
w[1] = ui_create_widget(NULL);
ui_widget_set_text(w[1], "Enter a message and save it.");
ui_widget_append(w[0], w[1]);
refs->input_message = ui_create_widget("textedit");
ui_widget_set_attr(refs->input_message, "placeholder", "eg: hello, world!");
refs->btn_save_message = ui_create_widget("button");
w[2] = ui_create_widget(NULL);
ui_widget_set_text(w[2], "Save");
ui_widget_append(refs->btn_save_message, w[2]);
refs->feedback = ui_create_widget("text");
ui_widget_add_class(refs->feedback, "feedback");
w[3] = ui_create_widget(NULL);
ui_widget_set_text(w[3], "Message has been saved!");
ui_widget_append(refs->feedback, w[3]);
ui_widget_append(Home_parent, w[0]);
ui_widget_append(Home_parent, refs->input_message);
ui_widget_append(Home_parent, refs->btn_save_message);
ui_widget_append(Home_parent, refs->feedback);
}

static void Home_load_resources(void)
{
ui_load_css_string(css_str_0, "home.css");
pd_font_library_load_file("iconfont.ttf");
}
55 changes: 55 additions & 0 deletions test/fixtures/resource/src/ui/home.xml.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/** This file is generated from home.xml */

#include <ui.h>

typedef struct {
ui_widget_t *input_message;
ui_widget_t *btn_save_message;
ui_widget_t *feedback;
} home_refs_t;

static const char *css_str_0 = "\
root {\
background-color: #f6f8fa;\
}\
\
.feedback {\
color: #28a745;\
font-size: 12px;\
margin-top: 5px;\
}\
\
";


static void home_load_template(ui_widget_t *home_parent, home_refs_t *refs)
{
ui_widget_t *w[5];

w[0] = ui_create_widget(NULL);
w[1] = ui_create_widget("text");
w[2] = ui_create_widget(NULL);
ui_widget_set_text(w[2], "Enter a message and save it.");
ui_widget_append(w[1], w[2]);
refs->input_message = ui_create_widget("textedit");
ui_widget_set_attr(refs->input_message, "placeholder", "eg: hello, world!");
refs->btn_save_message = ui_create_widget("button");
w[3] = ui_create_widget(NULL);
ui_widget_set_text(w[3], "Save");
ui_widget_append(refs->btn_save_message, w[3]);
refs->feedback = ui_create_widget("text");
ui_widget_add_class(refs->feedback, "feedback");
w[4] = ui_create_widget(NULL);
ui_widget_set_text(w[4], "Message has been saved!");
ui_widget_append(refs->feedback, w[4]);
ui_widget_append(home_parent, w[1]);
ui_widget_append(home_parent, refs->input_message);
ui_widget_append(home_parent, refs->btn_save_message);
ui_widget_append(home_parent, refs->feedback);
}

static void home_load_resources(void)
{
ui_load_css_string(css_str_0, "home.css");
pd_font_library_load_file("iconfont.ttf");
}
50 changes: 33 additions & 17 deletions test/fixtures/resource/src/ui/home.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
resource:
- "@type": text/css
"@src": home.css
- "@type": application/font-ttf
"@src": iconfont.ttf
ui:
text:
- Enter a message and save it.
- "#text": Message has been saved!
"@ref": feedback
"@class": feedback
textedit:
"@ref": input-message
"@placeholder": "eg: hello, world!"
button:
"#text": Save
"@ref": btn-save-message
name: lcui-app
children:
- name: resource
attributes:
type: text/css
src: home.css
- name: resource
attributes:
type: application/font-ttf
src: iconfont.ttf
- name: ui
children:
- name: text
children:
- type: text
text: Enter a message and save it.
- name: textedit
attributes:
ref: input-message
placeholder: "eg: hello, world!"
- name: button
attributes:
ref: btn-save-message
children:
- type: text
text: Save
- name: text
attributes:
ref: feedback
class: feedback
children:
- type: text
text: Message has been saved!
Loading

0 comments on commit c067504

Please sign in to comment.