Skip to content

Commit 30ece9b

Browse files
committed
com: drop depreacted Page component, add initial CodeBlock and InlineFrame components
1 parent 5a53961 commit 30ece9b

File tree

5 files changed

+162
-34
lines changed

5 files changed

+162
-34
lines changed

lib/com/codeblock.tsx

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { component } from "../model/components.ts";
2+
import { Node } from "../model/mod.ts";
3+
4+
5+
export interface CodeExecutor {
6+
// executes the source and returns an output string.
7+
// exceptions in execution should be caught and returned as a string.
8+
execute(source: string, options: ExecuteOptions): string;
9+
}
10+
11+
export interface ExecuteOptions {
12+
language: string;
13+
}
14+
15+
// defaultExecutor can be replaced with an external service, etc
16+
export let defaultExecutor: CodeExecutor = {
17+
execute: (source: string, options: ExecuteOptions): string => {
18+
if (options.language !== "javascript") {
19+
return `Unsupported language: ${options.language}`;
20+
}
21+
return JSON.stringify(window.eval(source));
22+
}
23+
}
24+
25+
26+
27+
@component
28+
export class CodeBlock {
29+
code: string;
30+
31+
constructor() {
32+
this.code = "";
33+
}
34+
35+
childrenView() {
36+
return CodeEditor;
37+
}
38+
39+
handleIcon(collapsed: boolean = false): any {
40+
return (
41+
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="node-bullet">
42+
<polyline points="16 18 22 12 16 6"></polyline>
43+
<polyline points="8 6 2 12 8 18"></polyline>
44+
</svg>
45+
);
46+
}
47+
48+
static initialize(workbench: Workbench) {
49+
workbench.commands.registerCommand({
50+
id: "make-code-snippet",
51+
title: "Make Code Snippet",
52+
when: (ctx: Context) => {
53+
if (!ctx.node) return false;
54+
if (ctx.node.raw.Rel === "Fields") return false;
55+
if (ctx.node.parent && ctx.node.parent.hasComponent(Document)) return false;
56+
return true;
57+
},
58+
action: (ctx: Context) => {
59+
const com = new CodeBlock();
60+
ctx.node.addComponent(com);
61+
ctx.node.changed();
62+
workbench.workspace.setExpanded(ctx.path.head, ctx.path.node, true);
63+
}
64+
});
65+
}
66+
67+
}
68+
69+
70+
const CodeEditor = {
71+
oncreate({dom, attrs: {path}}) {
72+
const snippet = path.node.getComponent(CodeBlock);
73+
dom.jarEditor = new window.CodeJar(dom, (editor) => {
74+
// highlight.js does not trim old tags,
75+
// let's do it by this hack.
76+
editor.textContent = editor.textContent;
77+
window.hljs.highlightBlock(editor);
78+
});
79+
dom.jarEditor.updateCode(snippet.code);
80+
dom.jarEditor.onUpdate(code => {
81+
snippet.code = code;
82+
path.node.changed();
83+
});
84+
},
85+
86+
view({attrs: {workbench, path}}) {
87+
// this cancels the keydown on the outline node
88+
// so you can use arrow keys normally
89+
const onkeydown = (e) => e.stopPropagation();
90+
91+
return (
92+
<div class="code-editor" onkeydown={onkeydown}></div>
93+
)
94+
}
95+
}

lib/com/iframe.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { component } from "../model/components.ts";
2+
import { Node } from "../model/mod.ts";
3+
4+
@component
5+
export class InlineFrame {
6+
url: string;
7+
8+
constructor() {
9+
this.url = "https://example.com";
10+
}
11+
12+
childrenView() {
13+
return InlineFrameView;
14+
}
15+
handleIcon(collapsed: boolean = false): any {
16+
return (
17+
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="node-bullet">
18+
<circle cx="12" cy="12" r="10"></circle>
19+
<line x1="2" y1="12" x2="22" y2="12"></line>
20+
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
21+
</svg>
22+
);
23+
}
24+
25+
26+
static initialize(workbench: Workbench) {
27+
workbench.commands.registerCommand({
28+
id: "make-iframe",
29+
title: "Make Inline Frame",
30+
when: (ctx: Context) => {
31+
if (!ctx.node) return false;
32+
if (ctx.node.raw.Rel === "Fields") return false;
33+
if (ctx.node.parent && ctx.node.parent.hasComponent(Document)) return false;
34+
return true;
35+
},
36+
action: (ctx: Context) => {
37+
const frame = new InlineFrame();
38+
if (ctx.node.name.startsWith("http://") ||
39+
ctx.node.name.startsWith("https://")) {
40+
frame.url = ctx.node.name;
41+
ctx.node.addComponent(frame);
42+
workbench.defocus();
43+
ctx.node.name = ctx.node.name.replaceAll("https://", "").replaceAll("http://");
44+
workbench.workspace.setExpanded(ctx.path.head, ctx.node, true);
45+
workbench.focus(ctx.path);
46+
}
47+
48+
}
49+
});
50+
}
51+
52+
}
53+
54+
const InlineFrameView = {
55+
view({attrs: {path}}) {
56+
const iframe = path.node.getComponent(InlineFrame);
57+
return (
58+
<div class="iframe-view">
59+
<iframe src={iframe.url} style={{width: "100%", height: "500px", border: "0", marginLeft: "-0.5rem"}}></iframe>
60+
</div>
61+
)
62+
}
63+
}

lib/com/page.tsx

Lines changed: 0 additions & 13 deletions
This file was deleted.

lib/mod.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
import { Path, Workbench } from "./workbench/mod.ts";
2020
import { App } from "./ui/app.tsx";
2121
import { Backend } from "./backend/mod.ts";
22+
import { CodeBlock } from "./com/codeblock.tsx";
23+
import { InlineFrame } from "./com/iframe.tsx";
2224
import { SmartNode } from "./com/smartnode.tsx";
2325
import { Checkbox } from "./com/checkbox.tsx";
24-
import { Page } from "./com/page.tsx";
2526
import { TextField } from "./com/textfield.tsx";
2627
import { Clock } from "./com/clock.tsx";
2728
import { Tag } from "./com/tag.tsx";
@@ -56,13 +57,14 @@ export async function setup(document: Document, target: HTMLElement, backend: Ba
5657
[
5758
Clock,
5859
TextField,
59-
Page,
6060
Document,
6161
Checkbox,
6262
Tag,
6363
Template,
6464
SmartNode,
6565
Description,
66+
InlineFrame,
67+
CodeBlock,
6668
].forEach(com => {
6769
if (com.initialize) {
6870
com.initialize(workbench);

lib/ui/panel.tsx

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { OutlineEditor } from "./outline.tsx";
22
import { NodeEditor } from "./node/editor.tsx";
3-
import { Page } from "../com/page.tsx";
43

54
export const Panel = {
65
view({ attrs }) {
@@ -24,10 +23,6 @@ export const Panel = {
2423
workbench.panels = [path];
2524
workbench.context.path = path;
2625
}
27-
const editMarkdown = (e) => {
28-
node.getComponent(Page).markdown = e.target.value;
29-
node.changed();
30-
}
3126
function calcHeight(value = "") {
3227
let numberOfLineBreaks = (value.match(/\n/g) || []).length;
3328
// min-height + lines x line-height + padding + border
@@ -64,20 +59,6 @@ export const Panel = {
6459
<div class="title-node" oncontextmenu={(e) => workbench.showMenu(e, { node, path })} data-menu="node">
6560
<NodeEditor workbench={workbench} path={path} disallowEmpty={true} />
6661
</div>
67-
{(node.hasComponent(Page)) ?
68-
<textarea oninput={editMarkdown}
69-
value={node.getComponent(Page).markdown}
70-
placeholder="Enter Markdown text here"
71-
style={{
72-
marginLeft: "var(--padding)",
73-
padding: "var(--padding)",
74-
outline: "0",
75-
height: `${calcHeight(node.getComponent(Page).markdown)}px`,
76-
border: "0",
77-
}}>
78-
{node.getComponent(Page).markdown}
79-
</textarea>
80-
: null}
8162
<OutlineEditor workbench={workbench} path={path.sub()} alwaysShowNew={true} />
8263
</div>
8364
</div>

0 commit comments

Comments
 (0)