diff --git a/client/src/app/markleft/markleft.html b/client/src/app/markleft/markleft.html
index 5699a3f..97bab6f 100644
--- a/client/src/app/markleft/markleft.html
+++ b/client/src/app/markleft/markleft.html
@@ -1,7 +1,4 @@
-
+
diff --git a/client/src/app/markleft/markleft.ts b/client/src/app/markleft/markleft.ts
index cda9e87..a089383 100644
--- a/client/src/app/markleft/markleft.ts
+++ b/client/src/app/markleft/markleft.ts
@@ -1,18 +1,24 @@
import { Component, ElementRef, Renderer2, ViewChild } from '@angular/core';
-import { ReactiveFormsModule, FormsModule, FormControl, FormGroup, FormBuilder } from '@angular/forms';
+import { FormsModule } from '@angular/forms'
// type descriptions
+// a formatDescriptor contains information for the renderer to apply formatting styles to a node
interface formatDescriptor {
className: string;
};
+// a textNode is an element produced by the parser to link text to applied format specifiers. The renderer will
+// apply each style to the text in the node according to the styles registry.
interface textNode {
type: string;
text: string;
styles: string[]
}
+// a blockNode is an element produced by the parser to structure nodes by blocks. blocks contain child nodes, either
+// other blocks or text nodes at the bottom. A block node's html element type is described by kind: p, h1, h2, div, etc
+// Maybe we blocks can also have styles, and then we can join textNode and blockNode into a single type.
interface blockNode {
type: string;
kind: string;
@@ -20,6 +26,7 @@ interface blockNode {
}
// styles registry: this maps format specifiers to css classes
+// might move this to its own file
const styles: Record = {
B: {
className: "format-bold"
@@ -35,9 +42,10 @@ const styles: Record = {
},
}; // i.e. %B{...} will apply "format-bold"
+// angular component class
@Component({
selector: 'app-markleft',
- imports: [FormsModule, ReactiveFormsModule],
+ imports: [FormsModule],
templateUrl: './markleft.html',
styleUrl: './markleft.scss',
})
@@ -45,41 +53,36 @@ export class Markleft {
@ViewChild('markup_container', { static: true }) container!: ElementRef;
- constructor(private renderer: Renderer2, private fb: FormBuilder) {
- console.log("component constructor");
+ constructor(private renderer: Renderer2) {
+ // console.log("component constructor");
}
ngOnInit() { // DOM manipulation can't occur in constructor
-
- this.markupInput = this.fb.group({
- inputText: [this.liveText],
- });
-
this.refresh();
}
- markupInput = new FormGroup({
- inputText: new FormControl("")
- });
-
- onSubmit() {
+ // live update on each text input.
+ onTextUpdate(event: Event) {
this.refresh();
}
- // full demo right here
+ // default text
liveText: string = `
#H{Hello World!}
#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 %B{PhAML} (%I{%B{Ph}ish %B{A}mazing %B{M}arkup %B{L}anguage}) text. This is %I{italic} and this is %B{bold}. Some might %I{even be %B{both}}.
}
This should be plain and unstylized.
`; // TODO: live editor
+ // parses a single string into an array of nodes
+ // like noted at parseStyle, maybe can return a single node which itself contains the array of children.
parsePlaintext(input: string): (textNode | blockNode)[] {
- let index: number = 0;
+ let index: number = 0; // position in the input string
let nodes: (textNode | blockNode)[] = [];
+ // TODO: I might restructure the node parsing so that it starts with a generic top level node and can process all children under that node
function parseStyle(parentNode: blockNode | null = null, parentStyles: string[] | null = null) {
index++; // step onto specifier code
@@ -104,19 +107,11 @@ export class Markleft {
if(input[index] === "%") { // encountered another style specifier
// commit the current node
- const node: textNode = {
- type: "text",
- text: text,
- styles: styles
- };
- if(parentNode) {
- parentNode.children.push(node);
- } else {
- nodes.push(node);
- }
+ addTextNode(text, styles, parentNode);
text = ""; // clear the already commited text
// and then move to the next
parseStyle(parentNode ? parentNode : null, styles); // recursion
+
} else if(input[index] == "}") { // this node has closed
addTextNode(text, styles, parentNode);
//index++; // step to next
@@ -127,6 +122,9 @@ export class Markleft {
text += input[index];
}
}
+ if(index >= input.length) {
+ break;
+ }
}
}
@@ -152,15 +150,7 @@ export class Markleft {
index++;
if(input[index] === "%" || input[index] === "#") { // encountered another format specifier
- // commit current plain text to the block
- if(text.length !== 0) {
- const textNode: textNode = {
- type: "text",
- text: text,
- styles: [] // none
- };
- node.children.push(textNode);
- }
+ addTextNode(text, null, node);
text = ""; // clear the already commited text
// and then move to the next
@@ -188,6 +178,9 @@ export class Markleft {
text += input[index];
}
}
+ if(index >= input.length) {
+ break;
+ }
}
}
@@ -297,23 +290,22 @@ export class Markleft {
}
refresh() {
- if(this.markupInput.value.inputText) {
- // clear children
- const parent = this.container.nativeElement;
- while (parent.firstChild) {
- this.renderer.removeChild(parent, parent.firstChild);
- }
-
- // parse text
- const nodes: (textNode | blockNode)[] = this.parsePlaintext(this.markupInput.value.inputText);
-
- // console.log(nodes)
-
- // render nodes
- nodes.forEach((node) => {
- this.renderNode(node);
- });
+ // clear children
+ const parent = this.container.nativeElement;
+ while (parent.firstChild) {
+ this.renderer.removeChild(parent, parent.firstChild);
}
+
+ // parse text
+ const nodes: (textNode | blockNode)[] = this.parsePlaintext(this.liveText);
+
+ // console.log(nodes)
+
+ // render nodes
+ nodes.forEach((node) => {
+ this.renderNode(node);
+ });
+
}
}