markup is making progress
All checks were successful
Build and Deploy Client / build-and-deploy (push) Successful in 13s
All checks were successful
Build and Deploy Client / build-and-deploy (push) Successful in 13s
This commit is contained in:
@@ -2,7 +2,8 @@
|
|||||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"cli": {
|
"cli": {
|
||||||
"packageManager": "npm"
|
"packageManager": "npm",
|
||||||
|
"analytics": false
|
||||||
},
|
},
|
||||||
"newProjectRoot": "projects",
|
"newProjectRoot": "projects",
|
||||||
"projects": {
|
"projects": {
|
||||||
|
|||||||
6
client/package-lock.json
generated
6
client/package-lock.json
generated
@@ -5874,9 +5874,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.17",
|
"version": "3.3.18",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
|
||||||
"integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==",
|
"integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
<p>markleft works!</p>
|
<p>markleft works!</p>
|
||||||
|
|
||||||
|
<div #markup_container></div>
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
|
|
||||||
|
.format-plain {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
.format-bold {
|
.format-bold {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, ElementRef, Renderer2, ViewChild } from '@angular/core';
|
||||||
|
|
||||||
// type descriptions
|
// type descriptions
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ interface formatDescriptor {
|
|||||||
interface textNode {
|
interface textNode {
|
||||||
type: string;
|
type: string;
|
||||||
text: string;
|
text: string;
|
||||||
styles: formatDescriptor[]
|
styles: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface blockNode {
|
interface blockNode {
|
||||||
@@ -29,6 +29,9 @@ const styles: Record<string, formatDescriptor> = {
|
|||||||
U: {
|
U: {
|
||||||
className: "format-underline"
|
className: "format-underline"
|
||||||
},
|
},
|
||||||
|
P: { // for testing. TODO: right now everything is a style
|
||||||
|
className: "format-plain"
|
||||||
|
},
|
||||||
}; // i.e. %B{...} will apply "format-bold"
|
}; // i.e. %B{...} will apply "format-bold"
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -39,15 +42,102 @@ const styles: Record<string, formatDescriptor> = {
|
|||||||
})
|
})
|
||||||
export class Markleft {
|
export class Markleft {
|
||||||
|
|
||||||
|
@ViewChild('markup_container', { static: true }) container!: ElementRef;
|
||||||
|
|
||||||
|
constructor(private renderer: Renderer2) {
|
||||||
|
console.log("component constructor");
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() { // DOM manipulation can't occur in constructor
|
||||||
|
|
||||||
|
const nodes: textNode[] = this.parsePlaintext("%P{this is a %B{test.} This should be unbolded. But %I{this} should be italicized.}");
|
||||||
|
console.log(nodes);
|
||||||
|
nodes.forEach((node) => {
|
||||||
|
this.renderNode(node);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// full demo right here
|
||||||
plaintext: String = `
|
plaintext: String = `
|
||||||
#H1{Hello World!}
|
#H1{Hello World!}
|
||||||
#P{
|
#P{
|
||||||
This is some markleft text. This is %I{italic} and this is %B{bold}. Some might %I{even be %B{both}}.
|
This is some markleft text. This is %I{italic} and this is %B{bold}. Some might %I{even be %B{both}}.
|
||||||
}
|
}
|
||||||
This should be plain and unstylized.
|
This should be plain and unstylized.
|
||||||
`;
|
`; // TODO: live editor
|
||||||
|
|
||||||
parsePlaintext(input: string): /*structureNode[]*/ void {
|
parsePlaintext(input: string): textNode[] {
|
||||||
|
|
||||||
|
let index: number = 0;
|
||||||
|
let nodes: textNode[] = [];
|
||||||
|
|
||||||
|
// starting with ONLY text styles, no structure blocks yet
|
||||||
|
function parseStyle(parentStyles: string | null = null) {
|
||||||
|
index++; // step onto specifier code
|
||||||
|
const code: string = input[index]; // TODO: validate if this code is a usable code
|
||||||
|
index++;
|
||||||
|
if(input[index] !== "{") { // TODO: implement some expect("{") function to better validate
|
||||||
|
console.log("{ not found following format specifier");
|
||||||
|
// return null node
|
||||||
|
}
|
||||||
|
console.log("Parsing text for format specifier", code);
|
||||||
|
|
||||||
|
let styles: string[] = [];
|
||||||
|
if(parentStyles) {
|
||||||
|
styles = [...parentStyles, code] // append style code to styles list of this node
|
||||||
|
} else {
|
||||||
|
styles = [code];
|
||||||
|
}
|
||||||
|
|
||||||
|
let text: string = "";
|
||||||
|
while(true) { // assemble text
|
||||||
|
index++;
|
||||||
|
console.log(input[index])
|
||||||
|
if(input[index] === "%") { // encountered another style specifier
|
||||||
|
|
||||||
|
// commit the current node
|
||||||
|
const node: textNode = {
|
||||||
|
type: "text",
|
||||||
|
text: text,
|
||||||
|
styles: styles
|
||||||
|
};
|
||||||
|
nodes.push(node);
|
||||||
|
text = ""; // clear the already commited text
|
||||||
|
// and then move to the next
|
||||||
|
parseStyle(); // recursion
|
||||||
|
} else if(input[index] == "}") { // this node has closed
|
||||||
|
const node: textNode = {
|
||||||
|
type: "text",
|
||||||
|
text: text,
|
||||||
|
styles: styles
|
||||||
|
};
|
||||||
|
nodes.push(node);
|
||||||
|
break;
|
||||||
|
} else { // regular text
|
||||||
|
text += input[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(endChar: string | null = null) {
|
||||||
|
console.log("parsing...");
|
||||||
|
while(index < input.length) {
|
||||||
|
if(endChar && (input[index] === endChar)) {
|
||||||
|
index++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(input[index] === "%") { // encountered a style specifier
|
||||||
|
parseStyle();
|
||||||
|
} else if(input[index] === "#") { // encountered a structure specifier
|
||||||
|
// nodes.push(parseStructure());
|
||||||
|
} else if(input[index] === "@") { // encountered an attribute specifier
|
||||||
|
// nodes.push(parseAttribute());
|
||||||
|
} else {
|
||||||
|
// regular character
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* pseudocode (c lol)
|
/* pseudocode (c lol)
|
||||||
|
|
||||||
@@ -89,23 +179,30 @@ export class Markleft {
|
|||||||
... and so on for parseBlock and parseText
|
... and so on for parseBlock and parseText
|
||||||
|
|
||||||
*/
|
*/
|
||||||
return;
|
|
||||||
|
parse();
|
||||||
|
|
||||||
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderNode(node: (textNode | blockNode)): void {
|
renderNode(node: textNode): void {
|
||||||
|
|
||||||
|
console.log("rendering...");
|
||||||
|
|
||||||
/*
|
|
||||||
if(node.type == "text") { // text nodes only need span elements
|
if(node.type == "text") { // text nodes only need span elements
|
||||||
|
|
||||||
element span = html.createElement("span"); // or whatever it is
|
|
||||||
|
|
||||||
// add styles
|
|
||||||
foreach(style style in node.styles) {
|
|
||||||
span.classes.add(styles[style].className);
|
|
||||||
}
|
|
||||||
return span;
|
|
||||||
|
|
||||||
} else if(node.type == "block") {
|
const span = this.renderer.createElement("span"); // create container
|
||||||
|
|
||||||
|
node.styles.forEach((style) => {
|
||||||
|
this.renderer.addClass(span, styles[style].className);
|
||||||
|
});
|
||||||
|
|
||||||
|
const text = this.renderer.createText(node.text); // create text
|
||||||
|
|
||||||
|
this.renderer.appendChild(span, text); // add text to container
|
||||||
|
this.renderer.appendChild(this.container.nativeElement, span); // add container to DOM
|
||||||
|
|
||||||
|
} /* else if(node.type == "block") {
|
||||||
|
|
||||||
element block = html.createElement(node.kind); // or whatever it is
|
element block = html.createElement(node.kind); // or whatever it is
|
||||||
|
|
||||||
@@ -115,9 +212,7 @@ export class Markleft {
|
|||||||
}
|
}
|
||||||
return block;
|
return block;
|
||||||
|
|
||||||
}
|
} */
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user