1
0
Fork 0
mirror of https://github.com/kou029w/quot.git synced 2025-01-31 14:28:06 +00:00

Compare commits

..

No commits in common. "b725b250d332ff1649e49a927dde33e73ea04fbe" and "23e6bf327bc2c79fca62e79b38920016f299ee9a" have entirely different histories.

7 changed files with 33 additions and 109 deletions

View file

@ -12,7 +12,7 @@ async function views(fastify: FastifyInstance) {
}, },
{ {
bundle: true, bundle: true,
minify: process.env.NODE_ENV !== "development", minify: true,
entryPoints: [entryPoint], entryPoints: [entryPoint],
define: { define: {
"import.meta.env.QUOT_API_ENDPOINT": JSON.stringify( "import.meta.env.QUOT_API_ENDPOINT": JSON.stringify(

34
app/package-lock.json generated
View file

@ -11,8 +11,7 @@
"@exampledev/new.css": "^1.1.3", "@exampledev/new.css": "^1.1.3",
"@fastify/http-proxy": "^8.2.2", "@fastify/http-proxy": "^8.2.2",
"@lexical/history": "^0.4.1", "@lexical/history": "^0.4.1",
"@lexical/link": "^0.4.1", "@lexical/plain-text": "^0.4.1",
"@lexical/rich-text": "^0.4.1",
"@tsconfig/node18-strictest-esm": "^1.0.1", "@tsconfig/node18-strictest-esm": "^1.0.1",
"esbuild": "^0.15.7", "esbuild": "^0.15.7",
"esbuild-register": "^3.3.3", "esbuild-register": "^3.3.3",
@ -139,17 +138,6 @@
"lexical": "0.4.1" "lexical": "0.4.1"
} }
}, },
"node_modules/@lexical/link": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@lexical/link/-/link-0.4.1.tgz",
"integrity": "sha512-566lQymmuBe3Y7UDyaaTs+VDlElbu1WhnjT9lVDk0BXag7MA8tv/f60XptWnTK1pv/Dobm/CyLmyLae55OuflQ==",
"dependencies": {
"@lexical/utils": "0.4.1"
},
"peerDependencies": {
"lexical": "0.4.1"
}
},
"node_modules/@lexical/list": { "node_modules/@lexical/list": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/@lexical/list/-/list-0.4.1.tgz", "resolved": "https://registry.npmjs.org/@lexical/list/-/list-0.4.1.tgz",
@ -161,10 +149,10 @@
"lexical": "0.4.1" "lexical": "0.4.1"
} }
}, },
"node_modules/@lexical/rich-text": { "node_modules/@lexical/plain-text": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.4.1.tgz", "resolved": "https://registry.npmjs.org/@lexical/plain-text/-/plain-text-0.4.1.tgz",
"integrity": "sha512-EI4ul3y1hqMp0VS/4D8aOyR41ysz1KaYgkm6PyrRXEMyK8uKmVubJP83RkOU2fWkTVtdrMjM6aeT1qX849LetA==", "integrity": "sha512-cNFLXhOfR0coUFGA6aPGcHr6a+Y9ZrkETMM78+XV9J8iVsKij4/katFhsqACQDna4vSfXuqjTitCRtiFaDevDg==",
"peerDependencies": { "peerDependencies": {
"@lexical/clipboard": "0.4.1", "@lexical/clipboard": "0.4.1",
"@lexical/selection": "0.4.1", "@lexical/selection": "0.4.1",
@ -1211,14 +1199,6 @@
"@lexical/selection": "0.4.1" "@lexical/selection": "0.4.1"
} }
}, },
"@lexical/link": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@lexical/link/-/link-0.4.1.tgz",
"integrity": "sha512-566lQymmuBe3Y7UDyaaTs+VDlElbu1WhnjT9lVDk0BXag7MA8tv/f60XptWnTK1pv/Dobm/CyLmyLae55OuflQ==",
"requires": {
"@lexical/utils": "0.4.1"
}
},
"@lexical/list": { "@lexical/list": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/@lexical/list/-/list-0.4.1.tgz", "resolved": "https://registry.npmjs.org/@lexical/list/-/list-0.4.1.tgz",
@ -1227,10 +1207,10 @@
"@lexical/utils": "0.4.1" "@lexical/utils": "0.4.1"
} }
}, },
"@lexical/rich-text": { "@lexical/plain-text": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/@lexical/rich-text/-/rich-text-0.4.1.tgz", "resolved": "https://registry.npmjs.org/@lexical/plain-text/-/plain-text-0.4.1.tgz",
"integrity": "sha512-EI4ul3y1hqMp0VS/4D8aOyR41ysz1KaYgkm6PyrRXEMyK8uKmVubJP83RkOU2fWkTVtdrMjM6aeT1qX849LetA==", "integrity": "sha512-cNFLXhOfR0coUFGA6aPGcHr6a+Y9ZrkETMM78+XV9J8iVsKij4/katFhsqACQDna4vSfXuqjTitCRtiFaDevDg==",
"requires": {} "requires": {}
}, },
"@lexical/selection": { "@lexical/selection": {

View file

@ -14,8 +14,7 @@
"@exampledev/new.css": "^1.1.3", "@exampledev/new.css": "^1.1.3",
"@fastify/http-proxy": "^8.2.2", "@fastify/http-proxy": "^8.2.2",
"@lexical/history": "^0.4.1", "@lexical/history": "^0.4.1",
"@lexical/link": "^0.4.1", "@lexical/plain-text": "^0.4.1",
"@lexical/rich-text": "^0.4.1",
"@tsconfig/node18-strictest-esm": "^1.0.1", "@tsconfig/node18-strictest-esm": "^1.0.1",
"esbuild": "^0.15.7", "esbuild": "^0.15.7",
"esbuild-register": "^3.3.3", "esbuild-register": "^3.3.3",

View file

@ -1,7 +1,7 @@
{ {
"extends": "@tsconfig/node18-strictest-esm/tsconfig.json", "extends": "@tsconfig/node18-strictest-esm/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"lib": ["esnext", "dom", "dom.iterable"], "lib": ["dom", "dom.iterable"],
"jsx": "react-jsx", "jsx": "react-jsx",
"jsxImportSource": "solid-js/h", "jsxImportSource": "solid-js/h",
"noPropertyAccessFromIndexSignature": false "noPropertyAccessFromIndexSignature": false

View file

@ -23,7 +23,8 @@ header h1 {
margin: 0; margin: 0;
} }
header h1 > :is(a, a:hover) { header h1 > a,
header h1 > a:hover {
color: var(--nc-ac-1); color: var(--nc-ac-1);
} }

View file

@ -8,12 +8,3 @@
border-top-color: var(--nc-bg-3); border-top-color: var(--nc-bg-3);
box-shadow: 0 1px var(--nc-bg-3); box-shadow: 0 1px var(--nc-bg-3);
} }
.editor :is(h1, h2, h3, h4, h5, h6) {
padding: unset;
font-size: unset;
}
.editor p {
margin: unset;
}

View file

@ -1,23 +1,17 @@
import { import {
$createLineBreakNode,
$createParagraphNode, $createParagraphNode,
$createTextNode, $createTextNode,
$getRoot, $getRoot,
$isElementNode,
createEditor, createEditor,
} from "lexical"; } from "lexical";
import { registerHistory, createEmptyHistoryState } from "@lexical/history"; import { registerHistory, createEmptyHistoryState } from "@lexical/history";
import { import { registerPlainText } from "@lexical/plain-text";
$createHeadingNode,
HeadingNode,
registerRichText,
} from "@lexical/rich-text";
import { $createAutoLinkNode, AutoLinkNode } from "@lexical/link";
import { onCleanup, onMount } from "solid-js"; import { onCleanup, onMount } from "solid-js";
import type Pages from "../../protocol/pages"; import type Pages from "../../protocol/pages";
import "./editor.css"; import "./editor.css";
const urlMatcher = /https?:\/\/[^\s]+/; const editor = createEditor();
const editor = createEditor({ nodes: [HeadingNode, AutoLinkNode] });
function ref(el: HTMLElement) { function ref(el: HTMLElement) {
editor.setRootElement(el); editor.setRootElement(el);
@ -31,66 +25,25 @@ export default (props: {
}) => { }) => {
const initialEditorState = () => { const initialEditorState = () => {
const root = $getRoot(); const root = $getRoot();
const [title, ...lines] = props.text.split("\n"); if (root.getFirstChild()) return;
const titleNode = $createHeadingNode("h2"); const paragraphNode = $createParagraphNode();
titleNode.append($createTextNode(title)); const text = props.text
root.append(titleNode); .split("\n")
for (const line of lines) { .flatMap((line) => [$createTextNode(line), $createLineBreakNode()])
const lineNode = $createParagraphNode(); .slice(0, -1);
const indent = line.match(/^\s*/)?.[0]?.length ?? 0; paragraphNode.append(...text);
lineNode.setIndent(indent); root.append(paragraphNode);
let text = line.slice(indent);
let match: RegExpMatchArray | null = null;
while ((match = text.match(urlMatcher))) {
const offset = text.slice(0, match.index!);
const input = match[0]!;
const link = $createAutoLinkNode(input);
link.append($createTextNode(match[0]));
lineNode.append($createTextNode(offset), link);
text = text.slice(offset.length + input.length);
}
lineNode.append($createTextNode(text));
root.append(lineNode);
}
}; };
onCleanup(registerRichText(editor, initialEditorState)); onCleanup(registerPlainText(editor, initialEditorState));
onCleanup(registerHistory(editor, createEmptyHistoryState(), 333)); onCleanup(registerHistory(editor, createEmptyHistoryState(), 333));
onCleanup( onMount(() => {
editor.registerUpdateListener(() => onCleanup(
editor.update(() => { editor.registerTextContentListener((text) => {
const root = $getRoot(); const [title] = text.split("\n");
const defaultTitle = new Date() props.onUpdatePage({ id: props.id, title: title ?? "", text });
.toLocaleDateString(navigator.language, {
year: "numeric",
month: "2-digit",
day: "2-digit",
})
.replaceAll("/", "-");
const [titleNode, ...lineNodes] = root.getChildren();
const title =
titleNode?.getTextContent().trim() ||
(lineNodes.length === 0 ? "" : defaultTitle);
const lines = lineNodes.map((line) => {
const indent = $isElementNode(line) ? line.getIndent() : 0;
return `${" ".repeat(indent)}${line.getTextContent()}`;
});
const text = [title, ...lines].join("\n");
props.onUpdatePage({ id: props.id, title, text });
}) })
) );
); editor.focus();
onMount(() => editor.focus()); });
return ( return <article ref={ref} class="editor" contenteditable />;
<article
ref={ref}
onclick={(e) => {
const el = e.target.parentElement;
if (el instanceof HTMLAnchorElement) {
window.open(el.href, "_blank", "noreferrer");
}
}}
class="editor"
contenteditable
/>
);
}; };