initial parser logic. still needs fixing for Text
This commit is contained in:
parent
71acab3e54
commit
b81ac470c5
2 changed files with 243 additions and 26 deletions
|
|
@ -8,6 +8,7 @@ export const api = new Elysia({ prefix: '/api' })
|
|||
const releaseYear = movie.release_date.substring(0, 4);
|
||||
const voteAverage = movie.vote_average.toFixed(2);
|
||||
|
||||
// return Gin.render("card", movie);
|
||||
return Yuck.renderMoviePage(
|
||||
movie.id,
|
||||
movie.title,
|
||||
|
|
@ -22,6 +23,7 @@ export const api = new Elysia({ prefix: '/api' })
|
|||
const releaseYear = movie.release_date.substring(0, 4);
|
||||
const voteAverage = movie.vote_average.toFixed(2);
|
||||
|
||||
// return Gin.render("movie", movie);
|
||||
return Yuck.renderMoviePage(
|
||||
movie.id,
|
||||
movie.title,
|
||||
|
|
@ -33,5 +35,6 @@ export const api = new Elysia({ prefix: '/api' })
|
|||
})
|
||||
.get("providers/watch/:id", async ({ params: { id } }) => {
|
||||
const providers = await API.providers(parseInt(id));
|
||||
// return Gin.render("providers", movie);
|
||||
return Yuck.renderProviderPage()
|
||||
});
|
||||
|
|
|
|||
266
src/util/gin.ts
266
src/util/gin.ts
|
|
@ -1,39 +1,253 @@
|
|||
// TODO: Finish template engine and parse the data like god intended
|
||||
type GinNode = {
|
||||
|
||||
path: string;
|
||||
children: GinNode[];
|
||||
const example =
|
||||
`Dear {{.Name}},
|
||||
{{if .Attended}}
|
||||
It was a pleasure to see you at the wedding.
|
||||
{{- else}}
|
||||
It is a shame you couldn't make it to the wedding.
|
||||
{{- end}}
|
||||
{{with .Gift -}}
|
||||
Thank you for the lovely {{.}}.
|
||||
{{end}}
|
||||
Best wishes,
|
||||
Josie`;
|
||||
|
||||
type Node = {
|
||||
type: 'Text' | 'Data' | 'Conditional' | 'Marker' | 'Container' | 'Empty'
|
||||
|
||||
// Text
|
||||
startIndex?: number;
|
||||
endIndex?: number;
|
||||
text?: string;
|
||||
|
||||
// Data
|
||||
key?: string;
|
||||
|
||||
// Conditional
|
||||
conditionType?: 'if' | 'with';
|
||||
condition?: Node;
|
||||
consequent?: Node;
|
||||
alternative?: Node;
|
||||
|
||||
// Marker
|
||||
markerType?: 'else' | 'end';
|
||||
|
||||
// Container
|
||||
placeholders?: Node[],
|
||||
|
||||
// Scoping
|
||||
parent?: Node;
|
||||
};
|
||||
|
||||
function parse(text: string): Node {
|
||||
let root: Node = {
|
||||
type: 'Container',
|
||||
placeholders: []
|
||||
};
|
||||
return _parse(text, root);
|
||||
}
|
||||
|
||||
class Gin {
|
||||
function _parse(text: string, root: Node): Node {
|
||||
if (!text || text.length < 1) {
|
||||
return root;
|
||||
};
|
||||
|
||||
/**
|
||||
* Preprocess template files from a given path into some data structure that tags them and notes substitutable areas
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
setup(path: string) {}
|
||||
let i = 0;
|
||||
const open = [];
|
||||
let prevScope = root;
|
||||
let scope = root;
|
||||
|
||||
/**
|
||||
* Creates HTML string from named template and supplied data
|
||||
*
|
||||
* @param name
|
||||
* @param mappings
|
||||
*/
|
||||
render(name: string, data: Record<string, string | number>): string {
|
||||
return '';
|
||||
let textNode: Node = {
|
||||
type: 'Text',
|
||||
startIndex: 0,
|
||||
endIndex: 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs actual dependency tree. Parsing is prob gonna be some recursive business
|
||||
*
|
||||
* @param path
|
||||
*/
|
||||
private crawl(path: string): GinNode | undefined {
|
||||
return;
|
||||
|
||||
let altPath = false;
|
||||
while (i < text.length) {
|
||||
textNode.endIndex = i;
|
||||
|
||||
if (text.substring(i, i+2) == '{{') {
|
||||
open.push(i);
|
||||
}
|
||||
|
||||
if (text.substring(i, i+2) == '}}') {
|
||||
textNode.parent = scope;
|
||||
textNode.text = text.substring(textNode.startIndex!, textNode.endIndex!)
|
||||
switch (scope.type) {
|
||||
case 'Container':
|
||||
scope.placeholders!.push(textNode)
|
||||
break;
|
||||
case 'Conditional':
|
||||
const placeholders = (altPath) ? scope.alternative!.placeholders! : scope.consequent!.placeholders!;
|
||||
placeholders.push(textNode);
|
||||
}
|
||||
|
||||
const j = open.pop()!;
|
||||
|
||||
textNode = {
|
||||
type: 'Text',
|
||||
startIndex: j+2,
|
||||
endIndex: i
|
||||
};
|
||||
|
||||
const command = parseCommand(text, j+2, i);
|
||||
command.parent = scope;
|
||||
|
||||
if (command.type == 'Marker') {
|
||||
switch (command.markerType) {
|
||||
case 'end':
|
||||
scope = prevScope;
|
||||
altPath = false;
|
||||
break;
|
||||
case 'else':
|
||||
altPath = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (command.type == 'Conditional') {
|
||||
scope.placeholders!.push(command)
|
||||
prevScope = scope;
|
||||
scope = command!;
|
||||
} else {
|
||||
switch (scope.type) {
|
||||
case 'Container':
|
||||
scope.placeholders!.push(command)
|
||||
break;
|
||||
case 'Conditional':
|
||||
const placeholders = (altPath) ? scope.alternative!.placeholders! : scope.consequent!.placeholders!;
|
||||
placeholders.push(command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (textNode.startIndex! < textNode.endIndex!) {
|
||||
textNode.parent = scope;
|
||||
textNode.text = text.substring(textNode.startIndex!, textNode.endIndex!)
|
||||
scope.placeholders!.push(textNode);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
function parseCommand(text: string, i: number, j: number): Node {
|
||||
let node: Node = {
|
||||
type: 'Empty'
|
||||
};
|
||||
|
||||
if (i >= j) {
|
||||
return node;
|
||||
};
|
||||
|
||||
let view = text.substring(i, j);
|
||||
|
||||
|
||||
// not supported
|
||||
if (view.startsWith("- ")) {
|
||||
i += 2;
|
||||
view = text.substring(i, j);
|
||||
}
|
||||
|
||||
// not supported
|
||||
if (view.endsWith(" -")) {
|
||||
j -= 2;
|
||||
view = text.substring(i, j);
|
||||
}
|
||||
|
||||
if (view.startsWith('.')) {
|
||||
node = parseDataText(view);
|
||||
}
|
||||
|
||||
if (view.startsWith('if') || view.trim().startsWith('with')) {
|
||||
node = parseConditionalText(text, i, j);
|
||||
}
|
||||
|
||||
if (view == 'else' || view == 'end') {
|
||||
node.type = 'Marker';
|
||||
node.markerType = view;
|
||||
}
|
||||
return node;
|
||||
};
|
||||
|
||||
function parseConditionalText(text: string, i: number, j: number): Node {
|
||||
const view = text.substring(i, j);
|
||||
|
||||
let node: Node = {
|
||||
type: 'Conditional',
|
||||
conditionType: view.startsWith('if') ? 'if' : 'with',
|
||||
consequent: {
|
||||
type: 'Container',
|
||||
placeholders: []
|
||||
},
|
||||
alternative: {
|
||||
type: 'Container',
|
||||
placeholders: []
|
||||
},
|
||||
};
|
||||
node.consequent!.parent = node;
|
||||
node.alternative!.parent = node;
|
||||
|
||||
const pipelineStart = i + view.indexOf(' ') + 1;
|
||||
const pipelineView = text.substring(pipelineStart, j)
|
||||
|
||||
if (pipelineView.startsWith('.')) {
|
||||
node.condition = {
|
||||
type: 'Data',
|
||||
key: pipelineView,
|
||||
parent: node,
|
||||
}
|
||||
} else {
|
||||
node.condition = {
|
||||
type: 'Text',
|
||||
startIndex: pipelineStart,
|
||||
endIndex: j,
|
||||
text: pipelineView,
|
||||
parent: node,
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function parseDataText(text: string): Node {
|
||||
return {
|
||||
type: 'Data',
|
||||
key: text.trim()
|
||||
};
|
||||
}
|
||||
|
||||
function printNode(node: Node, offset='') {
|
||||
switch (node.type) {
|
||||
case 'Conditional':
|
||||
console.log(`${offset}${node.conditionType}`);
|
||||
console.log(`${offset}Condition:\n`)
|
||||
printNode(node.condition!, offset + '\t')
|
||||
console.log(`${offset}Then:\n`)
|
||||
printNode(node.consequent!, offset + '\t')
|
||||
console.log(offset + 'Else:\n')
|
||||
printNode(node.alternative!, offset + '\t')
|
||||
break;
|
||||
case 'Container':
|
||||
console.log(offset + node.type)
|
||||
for (let p of node.placeholders ?? []) {
|
||||
printNode(p, offset + '|__');
|
||||
}
|
||||
break;
|
||||
case 'Data':
|
||||
console.log(`${offset}${node.type} [key=${node.key}]`);
|
||||
break;
|
||||
case 'Text':
|
||||
console.log(`${offset}${node.type} [text=${JSON.stringify(node.text)}]`);
|
||||
default:
|
||||
console.log(`${offset}${node.type}`);
|
||||
}
|
||||
}
|
||||
|
||||
printNode(parse(example));
|
||||
/**
|
||||
* Stopgap :(
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue