cleanup and comments
All checks were successful
Build and Deploy Client / build-and-deploy (push) Successful in 8s
All checks were successful
Build and Deploy Client / build-and-deploy (push) Successful in 8s
This commit is contained in:
@@ -1,7 +1,4 @@
|
|||||||
<form [formGroup]="markupInput" (ngSubmit)="onSubmit()">
|
|
||||||
<textarea formControlName="inputText"></textarea>
|
|
||||||
<button>Render</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
<textarea [(ngModel)]="liveText" (ngModelChange)="onTextUpdate($event)"></textarea>
|
||||||
|
|
||||||
<div #markup_container class="markup_container"></div>
|
<div #markup_container class="markup_container"></div>
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
import { Component, ElementRef, Renderer2, ViewChild } from '@angular/core';
|
import { Component, ElementRef, Renderer2, ViewChild } from '@angular/core';
|
||||||
import { ReactiveFormsModule, FormsModule, FormControl, FormGroup, FormBuilder } from '@angular/forms';
|
import { FormsModule } from '@angular/forms'
|
||||||
|
|
||||||
// type descriptions
|
// type descriptions
|
||||||
|
|
||||||
|
// a formatDescriptor contains information for the renderer to apply formatting styles to a node
|
||||||
interface formatDescriptor {
|
interface formatDescriptor {
|
||||||
className: string;
|
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 {
|
interface textNode {
|
||||||
type: string;
|
type: string;
|
||||||
text: string;
|
text: string;
|
||||||
styles: 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 {
|
interface blockNode {
|
||||||
type: string;
|
type: string;
|
||||||
kind: string;
|
kind: string;
|
||||||
@@ -20,6 +26,7 @@ interface blockNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// styles registry: this maps format specifiers to css classes
|
// styles registry: this maps format specifiers to css classes
|
||||||
|
// might move this to its own file
|
||||||
const styles: Record<string, formatDescriptor> = {
|
const styles: Record<string, formatDescriptor> = {
|
||||||
B: {
|
B: {
|
||||||
className: "format-bold"
|
className: "format-bold"
|
||||||
@@ -35,9 +42,10 @@ const styles: Record<string, formatDescriptor> = {
|
|||||||
},
|
},
|
||||||
}; // i.e. %B{...} will apply "format-bold"
|
}; // i.e. %B{...} will apply "format-bold"
|
||||||
|
|
||||||
|
// angular component class
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-markleft',
|
selector: 'app-markleft',
|
||||||
imports: [FormsModule, ReactiveFormsModule],
|
imports: [FormsModule],
|
||||||
templateUrl: './markleft.html',
|
templateUrl: './markleft.html',
|
||||||
styleUrl: './markleft.scss',
|
styleUrl: './markleft.scss',
|
||||||
})
|
})
|
||||||
@@ -45,41 +53,36 @@ export class Markleft {
|
|||||||
|
|
||||||
@ViewChild('markup_container', { static: true }) container!: ElementRef;
|
@ViewChild('markup_container', { static: true }) container!: ElementRef;
|
||||||
|
|
||||||
constructor(private renderer: Renderer2, private fb: FormBuilder) {
|
constructor(private renderer: Renderer2) {
|
||||||
console.log("component constructor");
|
// console.log("component constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() { // DOM manipulation can't occur in constructor
|
ngOnInit() { // DOM manipulation can't occur in constructor
|
||||||
|
|
||||||
this.markupInput = this.fb.group({
|
|
||||||
inputText: [this.liveText],
|
|
||||||
});
|
|
||||||
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
markupInput = new FormGroup({
|
// live update on each text input.
|
||||||
inputText: new FormControl("")
|
onTextUpdate(event: Event) {
|
||||||
});
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
// full demo right here
|
// default text
|
||||||
liveText: string = `
|
liveText: string = `
|
||||||
#H{Hello World!}
|
#H{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 %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.
|
This should be plain and unstylized.
|
||||||
`; // TODO: live editor
|
`; // 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)[] {
|
parsePlaintext(input: string): (textNode | blockNode)[] {
|
||||||
|
|
||||||
let index: number = 0;
|
let index: number = 0; // position in the input string
|
||||||
let nodes: (textNode | blockNode)[] = [];
|
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) {
|
function parseStyle(parentNode: blockNode | null = null, parentStyles: string[] | null = null) {
|
||||||
|
|
||||||
index++; // step onto specifier code
|
index++; // step onto specifier code
|
||||||
@@ -104,19 +107,11 @@ export class Markleft {
|
|||||||
if(input[index] === "%") { // encountered another style specifier
|
if(input[index] === "%") { // encountered another style specifier
|
||||||
|
|
||||||
// commit the current node
|
// commit the current node
|
||||||
const node: textNode = {
|
addTextNode(text, styles, parentNode);
|
||||||
type: "text",
|
|
||||||
text: text,
|
|
||||||
styles: styles
|
|
||||||
};
|
|
||||||
if(parentNode) {
|
|
||||||
parentNode.children.push(node);
|
|
||||||
} else {
|
|
||||||
nodes.push(node);
|
|
||||||
}
|
|
||||||
text = ""; // clear the already commited text
|
text = ""; // clear the already commited text
|
||||||
// and then move to the next
|
// and then move to the next
|
||||||
parseStyle(parentNode ? parentNode : null, styles); // recursion
|
parseStyle(parentNode ? parentNode : null, styles); // recursion
|
||||||
|
|
||||||
} else if(input[index] == "}") { // this node has closed
|
} else if(input[index] == "}") { // this node has closed
|
||||||
addTextNode(text, styles, parentNode);
|
addTextNode(text, styles, parentNode);
|
||||||
//index++; // step to next
|
//index++; // step to next
|
||||||
@@ -127,6 +122,9 @@ export class Markleft {
|
|||||||
text += input[index];
|
text += input[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(index >= input.length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,15 +150,7 @@ export class Markleft {
|
|||||||
index++;
|
index++;
|
||||||
if(input[index] === "%" || input[index] === "#") { // encountered another format specifier
|
if(input[index] === "%" || input[index] === "#") { // encountered another format specifier
|
||||||
|
|
||||||
// commit current plain text to the block
|
addTextNode(text, null, node);
|
||||||
if(text.length !== 0) {
|
|
||||||
const textNode: textNode = {
|
|
||||||
type: "text",
|
|
||||||
text: text,
|
|
||||||
styles: [] // none
|
|
||||||
};
|
|
||||||
node.children.push(textNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
text = ""; // clear the already commited text
|
text = ""; // clear the already commited text
|
||||||
// and then move to the next
|
// and then move to the next
|
||||||
@@ -188,6 +178,9 @@ export class Markleft {
|
|||||||
text += input[index];
|
text += input[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(index >= input.length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +290,6 @@ export class Markleft {
|
|||||||
}
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
if(this.markupInput.value.inputText) {
|
|
||||||
|
|
||||||
// clear children
|
// clear children
|
||||||
const parent = this.container.nativeElement;
|
const parent = this.container.nativeElement;
|
||||||
@@ -306,7 +298,7 @@ export class Markleft {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse text
|
// parse text
|
||||||
const nodes: (textNode | blockNode)[] = this.parsePlaintext(this.markupInput.value.inputText);
|
const nodes: (textNode | blockNode)[] = this.parsePlaintext(this.liveText);
|
||||||
|
|
||||||
// console.log(nodes)
|
// console.log(nodes)
|
||||||
|
|
||||||
@@ -314,6 +306,6 @@ export class Markleft {
|
|||||||
nodes.forEach((node) => {
|
nodes.forEach((node) => {
|
||||||
this.renderNode(node);
|
this.renderNode(node);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user