diff --git a/angular.json b/angular.json
index fe4034c..3baab77 100644
--- a/angular.json
+++ b/angular.json
@@ -48,9 +48,15 @@
},
{
"input": "src/assets/font/fonts.css"
+ },
+ {
+ "input": "node_modules/katex/dist/katex.min.css"
}
],
- "scripts": []
+ "scripts": [
+ "node_modules/marked/lib/marked.js",
+ "node_modules/katex/dist/katex.min.js"
+ ]
},
"configurations": {
"production": {
diff --git a/package-lock.json b/package-lock.json
index 70c5219..ec39923 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2126,6 +2126,11 @@
"integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==",
"dev": true
},
+ "@types/marked": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@types/marked/-/marked-1.1.0.tgz",
+ "integrity": "sha512-j8XXj6/l9kFvCwMyVqozznqpd/nk80krrW+QiIJN60Uu9gX5Pvn4/qPJ2YngQrR3QREPwmrE1f9/EWKVTFzoEw=="
+ },
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -3636,6 +3641,17 @@
"integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
"dev": true
},
+ "clipboard": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
+ "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
+ "optional": true,
+ "requires": {
+ "good-listener": "^1.2.2",
+ "select": "^1.1.2",
+ "tiny-emitter": "^2.0.0"
+ }
+ },
"cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
@@ -3795,8 +3811,7 @@
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"commondir": {
"version": "1.0.1",
@@ -4758,6 +4773,12 @@
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"dev": true
},
+ "delegate": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
+ "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
+ "optional": true
+ },
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -4992,6 +5013,11 @@
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
+ "emoji-toolkit": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/emoji-toolkit/-/emoji-toolkit-6.0.1.tgz",
+ "integrity": "sha512-QZZq0beHg753JxcBt89UBFqzwYNuMtXhNO+jY3viSAndewmn9biTE5glaro1RA0uWJ4hKqw4k1Mboe1M6sGkMA=="
+ },
"emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
@@ -6003,6 +6029,15 @@
"slash": "^3.0.0"
}
},
+ "good-listener": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
+ "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
+ "optional": true,
+ "requires": {
+ "delegate": "^3.1.2"
+ }
+ },
"graceful-fs": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
@@ -7830,6 +7865,14 @@
"source-map-support": "^0.5.5"
}
},
+ "katex": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/katex/-/katex-0.12.0.tgz",
+ "integrity": "sha512-y+8btoc/CK70XqcHqjxiGWBOeIL8upbS0peTPXTvgrh21n1RiWWcIpSWM+4uXq+IAgNh9YYQWdc7LVDPDAEEAg==",
+ "requires": {
+ "commander": "^2.19.0"
+ }
+ },
"killable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@@ -8227,6 +8270,11 @@
"object-visit": "^1.0.0"
}
},
+ "marked": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.0.tgz",
+ "integrity": "sha512-tiRxakgbNPBr301ihe/785NntvYyhxlqcL3YaC8CaxJQh7kiaEtrN9B/eK2I2943Yjkh5gw25chYFDQhOMCwMA=="
+ },
"md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@@ -8652,6 +8700,26 @@
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true
},
+ "ngx-markdown": {
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/ngx-markdown/-/ngx-markdown-10.1.1.tgz",
+ "integrity": "sha512-bUVgN6asb35d5U4xM5CNfo7pSpuwqJSdTgK0PhNZzLiaiyPIK2owtLF6sWGhxTThJu+LngJPjj4MQ+AFe/s8XQ==",
+ "requires": {
+ "@types/marked": "^1.1.0",
+ "emoji-toolkit": "^6.0.1",
+ "katex": "^0.12.0",
+ "marked": "^1.1.0",
+ "prismjs": "^1.20.0",
+ "tslib": "^2.0.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz",
+ "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ=="
+ }
+ }
+ },
"ngx-monaco-editor": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/ngx-monaco-editor/-/ngx-monaco-editor-8.1.1.tgz",
@@ -10480,6 +10548,14 @@
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
"dev": true
},
+ "prismjs": {
+ "version": "1.22.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.22.0.tgz",
+ "integrity": "sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w==",
+ "requires": {
+ "clipboard": "^2.0.0"
+ }
+ },
"process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -11582,6 +11658,12 @@
}
}
},
+ "select": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
+ "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=",
+ "optional": true
+ },
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -12970,6 +13052,12 @@
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
"dev": true
},
+ "tiny-emitter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+ "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
+ "optional": true
+ },
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
diff --git a/package.json b/package.json
index a8230b0..e6d4459 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
"ag-grid-community": "^22.1.1",
"core-js": "^2.5.4",
"moment": "^2.24.0",
+ "ngx-markdown": "^10.1.1",
"ngx-monaco-editor": "^8.1.1",
"rxjs": "~6.6.3",
"tslib": "^1.9.0",
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 0cb284f..e7629ad 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -14,6 +14,7 @@ import { TreeModule } from '@circlon/angular-tree-component';
import {AgGridModule} from 'ag-grid-angular';
import {MonacoEditorModule} from 'ngx-monaco-editor';
import { APP_BASE_HREF, PlatformLocation } from '@angular/common';
+import { MarkdownModule } from 'ngx-markdown';
/**
* This function is used internal to get a string instance of the `` value from `index.html`.
@@ -42,6 +43,7 @@ export function getBaseHref(platformLocation: PlatformLocation): string {
TreeModule,
AgGridModule.withComponents([]),
MonacoEditorModule.forRoot(),
+ MarkdownModule.forRoot(),
],
providers: [
StatusBar,
diff --git a/src/app/components/components.module.ts b/src/app/components/components.module.ts
index 5d4b644..49632ed 100644
--- a/src/app/components/components.module.ts
+++ b/src/app/components/components.module.ts
@@ -27,7 +27,9 @@ import {BooleanRendererComponent} from './editor/database/renderers/boolean-rend
import {SearchComponent} from './search/Search.component';
import {NormComponent} from './nodes/norm/norm.component';
+import {MarkdownComponent as MarkdownEditorComponent} from './nodes/markdown/markdown.component';
import {DirectivesModule} from '../directives/directives.module';
+import {MarkdownModule} from "ngx-markdown";
@NgModule({
declarations: [
@@ -53,17 +55,19 @@ import {DirectivesModule} from '../directives/directives.module';
SearchComponent,
NormComponent,
+ MarkdownEditorComponent,
],
- imports: [
- CommonModule,
- IonicModule,
- AgGridModule,
- FormsModule,
- ReactiveFormsModule,
- ContenteditableModule,
- MonacoEditorModule,
- DirectivesModule,
- ],
+ imports: [
+ CommonModule,
+ IonicModule,
+ AgGridModule,
+ FormsModule,
+ ReactiveFormsModule,
+ ContenteditableModule,
+ MonacoEditorModule,
+ DirectivesModule,
+ MarkdownModule,
+ ],
entryComponents: [
NodePickerComponent,
DatabaseComponent,
@@ -87,6 +91,7 @@ import {DirectivesModule} from '../directives/directives.module';
SearchComponent,
NormComponent,
+ MarkdownEditorComponent,
],
exports: [
NodePickerComponent,
@@ -111,6 +116,7 @@ import {DirectivesModule} from '../directives/directives.module';
SearchComponent,
NormComponent,
+ MarkdownEditorComponent,
]
})
export class ComponentsModule {}
diff --git a/src/app/components/editor/node-picker/node-picker.component.html b/src/app/components/editor/node-picker/node-picker.component.html
index 41df36f..a319230 100644
--- a/src/app/components/editor/node-picker/node-picker.component.html
+++ b/src/app/components/editor/node-picker/node-picker.component.html
@@ -3,6 +3,10 @@
Paragraph
+
+
+ Markdown
+
Database
diff --git a/src/app/components/editor/node-picker/node-picker.component.scss b/src/app/components/editor/node-picker/node-picker.component.scss
index a7f2b95..f5582b4 100644
--- a/src/app/components/editor/node-picker/node-picker.component.scss
+++ b/src/app/components/editor/node-picker/node-picker.component.scss
@@ -25,3 +25,9 @@ i {
color: var(--noded-background-files);
}
}
+
+.markdown {
+ i {
+ color: var(--noded-background-markdown);
+ }
+}
diff --git a/src/app/components/nodes/markdown/markdown.component.html b/src/app/components/nodes/markdown/markdown.component.html
new file mode 100644
index 0000000..8977e90
--- /dev/null
+++ b/src/app/components/nodes/markdown/markdown.component.html
@@ -0,0 +1,11 @@
+
\ No newline at end of file
diff --git a/src/app/components/nodes/markdown/markdown.component.scss b/src/app/components/nodes/markdown/markdown.component.scss
new file mode 100644
index 0000000..5be88bd
--- /dev/null
+++ b/src/app/components/nodes/markdown/markdown.component.scss
@@ -0,0 +1,23 @@
+.container {
+ display: flex;
+ min-height: 600px;
+ flex-direction: row;
+
+ .editor-container, .display {
+ flex: 1;
+ }
+
+ .editor-container {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .editor {
+ border: 1px solid lightgrey;
+ flex: 1;
+ }
+
+ .display {
+ margin-left: 10px;
+ }
+}
diff --git a/src/app/components/nodes/markdown/markdown.component.ts b/src/app/components/nodes/markdown/markdown.component.ts
new file mode 100644
index 0000000..758ceae
--- /dev/null
+++ b/src/app/components/nodes/markdown/markdown.component.ts
@@ -0,0 +1,77 @@
+import {Component, HostListener, Input, OnInit, ViewChild} from '@angular/core';
+import {EditorNodeContract} from '../EditorNode.contract';
+import {EditorService} from '../../../service/editor.service';
+import {v4} from 'uuid';
+
+@Component({
+ selector: 'editor-markdown',
+ templateUrl: './markdown.component.html',
+ styleUrls: ['./markdown.component.scss'],
+})
+export class MarkdownComponent extends EditorNodeContract implements OnInit {
+ // @ViewChild('editable') editable;
+ @Input() nodeId: string;
+
+ // public isFocused = false;
+ public initialValue = 'Click to edit...';
+ protected savedValue = 'Click to edit...';
+ public contents = '';
+ private dirtyOverride = false;
+ public showEditor = false;
+
+ public editorOptions = {
+ language: 'markdown',
+ uri: v4(),
+ readOnly: false,
+ automaticLayout: true,
+ };
+
+ constructor(
+ public readonly editorService: EditorService,
+ ) {
+ super();
+ this.contents = this.initialValue;
+ this.savedValue = this.initialValue;
+ }
+
+ ngOnInit() {
+ this.editorService.registerNodeEditor(this.nodeId, this).then(() => {
+ if ( !this.node.Value ) {
+ this.node.Value = {};
+ }
+
+ if ( this.node.Value.Value ) {
+ this.initialValue = this.node.Value.Value;
+ this.savedValue = this.node.Value.Value;
+ }
+
+ this.contents = this.initialValue;
+ });
+ }
+
+ public isDirty(): boolean | Promise {
+ return this.dirtyOverride || this.contents !== this.savedValue;
+ }
+
+ public writeChangesToNode(): void | Promise {
+ this.node.Value.Mode = 'code';
+ this.node.Value.Value = this.contents;
+ this.node.value = this.contents;
+ this.savedValue = this.contents;
+ }
+
+ onContentsChanged(event) {
+ if ( event !== this.savedValue ) {
+ this.editorService.triggerSave();
+ }
+ }
+
+ onFocusIn() {
+ this.showEditor = true;
+ }
+
+ @HostListener('document:keyup.escape', ['$event'])
+ onFocusOut(event) {
+ this.showEditor = false;
+ }
+}
diff --git a/src/app/pages/editor/editor.page.html b/src/app/pages/editor/editor.page.html
index 3c0e3ea..0bc96e8 100644
--- a/src/app/pages/editor/editor.page.html
+++ b/src/app/pages/editor/editor.page.html
@@ -37,6 +37,9 @@
+
+
+
diff --git a/src/app/pages/editor/editor.page.scss b/src/app/pages/editor/editor.page.scss
index e5d6a1a..1b6beb4 100644
--- a/src/app/pages/editor/editor.page.scss
+++ b/src/app/pages/editor/editor.page.scss
@@ -32,6 +32,10 @@ ion-icon.invisible {
&.file_ref {
color: var(--noded-background-files);
}
+
+ &.markdown {
+ color: var(--noded-background-markdown);
+ }
}
.host-add-button {
diff --git a/src/app/structures/HostRecord.ts b/src/app/structures/HostRecord.ts
index 9fca377..a53453d 100644
--- a/src/app/structures/HostRecord.ts
+++ b/src/app/structures/HostRecord.ts
@@ -1,6 +1,6 @@
export default class HostRecord {
public value = '';
- public type: 'paragraph'|'database_ref'|'code_ref'|'file_ref' = 'paragraph';
+ public type: 'paragraph'|'database_ref'|'code_ref'|'file_ref'|'markdown' = 'paragraph';
public CreatedAt: string;
public PageId: string;
diff --git a/src/app/structures/node-types.ts b/src/app/structures/node-types.ts
index e7397c6..c21b1bd 100644
--- a/src/app/structures/node-types.ts
+++ b/src/app/structures/node-types.ts
@@ -9,4 +9,5 @@ export const NodeTypeIcons = {
code_ref: 'fa fa-code',
file_ref: 'fa fa-archive',
files: 'fa fa-archive',
+ markdown: 'fab fa-markdown',
};
diff --git a/src/global.scss b/src/global.scss
index 5e09cc6..e7180d5 100644
--- a/src/global.scss
+++ b/src/global.scss
@@ -29,6 +29,7 @@
@import "~ag-grid-community/dist/styles/ag-grid.css";
@import "~ag-grid-community/dist/styles/ag-theme-balham.css";
@import "~@fortawesome/fontawesome-free/css/all.min.css";
+@import "~@fortawesome/fontawesome-free/css/brands.min.css";
:root {
--noded-background-note: #3A86FF;
@@ -50,6 +51,10 @@
--noded-background-files: #0E7B81;
--noded-color-files: white;
--noded-background-files-hover: #14AFB8;
+
+ --noded-background-markdown: #5F4D30;
+ --noded-color-markdown: white;
+ --noded-color-markdown-hover: #7A633E;
}
div.picker-wrapper {