diff --git a/app.config.ts b/app.config.ts index 29550a6..fab26f7 100644 --- a/app.config.ts +++ b/app.config.ts @@ -1,9 +1,13 @@ import { defineConfig } from '@solidjs/start/config'; import solidSvg from 'vite-plugin-solid-svg' -// import { VitePWA } from 'vite-plugin-pwa' export default defineConfig({ vite: { + resolve: { + alias: [ + { find: '@', replacement: 'F:\\Github\\calque\\node_modules\\' }, + ], + }, html: { cspNonce: 'KAAS_IS_AWESOME', }, @@ -12,65 +16,13 @@ export default defineConfig({ // }, // }, plugins: [ - solidSvg() - // VitePWA({ - // strategies: 'injectManifest', - // registerType: 'autoUpdate', - // injectRegister: false, - - // workbox: { - // globPatterns: ['**/*.{js,css,html,svg,png,svg,ico}'], - // cleanupOutdatedCaches: true, - // clientsClaim: true, - // }, - // injectManifest: { - // globPatterns: ['**/*.{js,css,html,svg,png,svg,ico}'], - // }, - - // manifest: { - // name: 'Calque - manage your i18n files', - // short_name: 'KAAS', - // description: 'Simple tool for maitaining i18n files', - // icons: [ - // { - // src: '/images/favicon.dark.svg', - // type: 'image/svg+xml', - // sizes: 'any' - // } - // ], - // display_override: ['window-controls-overlay'], - // screenshots: [ - // { - // src: '/images/screenshots/narrow.png', - // type: 'image/png', - // sizes: '538x1133', - // form_factor: 'narrow' - // }, - // { - // src: '/images/screenshots/wide.png', - // type: 'image/png', - // sizes: '2092x1295', - // form_factor: 'wide' - // } - // ], - // file_handlers: [ - // { - // action: '/edit', - // accept: { - // 'text/*': [ - // '.json' - // ] - // } - // } - // ] - // }, - - // devOptions: { - // enabled: true, - // type: 'module', - // navigateFallback: 'index.html', - // }, - // }), + solidSvg(), + { + name: 'temp', + configResolved(config) { + console.log(config.resolve.alias); + }, + } ], }, solid: { diff --git a/src/components/textarea/textarea.tsx b/src/components/textarea/textarea.tsx index bca5fff..d82ae64 100644 --- a/src/components/textarea/textarea.tsx +++ b/src/components/textarea/textarea.tsx @@ -58,6 +58,13 @@ export function Textarea(props: TextareaProps) { })) }, 300); + const onInput = (e: InputEvent) => { + const target = e.target as HTMLElement; + + console.log(e); + console.log(target.innerText, target.textContent, target.innerHTML); + }; + const onKeyUp = (e: KeyboardEvent) => { e.stopPropagation(); e.preventDefault(); @@ -92,6 +99,7 @@ export function Textarea(props: TextareaProps) { class={`${css.textarea} ${props.class}`} lang={props.lang} dir="auto" + oninput={onInput} onkeyup={onKeyUp} on:keydown={e => e.stopPropagation()} on:pointerdown={e => e.stopPropagation()} diff --git a/src/features/source/index.ts b/src/features/source/index.ts new file mode 100644 index 0000000..62d2ad5 --- /dev/null +++ b/src/features/source/index.ts @@ -0,0 +1,6 @@ + +export type { Source } from './source'; + +export { createParser as createHtmlParser } from './parser/html'; +export { createParser as createMarkdownParser } from './parser/markdown'; +export { createSource } from './source'; \ No newline at end of file diff --git a/src/features/source/parser.ts b/src/features/source/parser.ts new file mode 100644 index 0000000..e8ad0c9 --- /dev/null +++ b/src/features/source/parser.ts @@ -0,0 +1,28 @@ +enum Decoration { + None = 0, + Bold = 1, + Italic = 2, + Underline = 4, + StrikeThrough = 8, +} + +interface TextNode { + type: 'text'; + decoration: Decoration; + nodes: (string | Node)[]; +} + +interface HeaderNode { + type: 'header'; + nodes: Node[]; +} + +type Node = TextNode | HeaderNode; + +export interface RichTextAST { + nodes: Node[]; +} + +export interface Parser { + parse(source: string): RichTextAST; +} \ No newline at end of file diff --git a/src/features/source/parser/html.ts b/src/features/source/parser/html.ts new file mode 100644 index 0000000..0b34aee --- /dev/null +++ b/src/features/source/parser/html.ts @@ -0,0 +1,9 @@ +import { Parser } from "../parser"; + +export function createParser(): Parser { + return { + parse(value) { + return {}; + }, + }; +} \ No newline at end of file diff --git a/src/features/source/parser/markdown.ts b/src/features/source/parser/markdown.ts new file mode 100644 index 0000000..30b04c7 --- /dev/null +++ b/src/features/source/parser/markdown.ts @@ -0,0 +1,80 @@ +import { Parser } from "../parser"; + +export function createParser(): Parser { + return { + parse(source) { + // console.log(source); + + for (const token of tokenize(source)) { + console.log(token); + } + + return { + nodes: [], + }; + }, + }; +} + +// const states = { +// none(): State { + +// }, +// } as const; + + +type Token = { start: number, length: number } & ( + | { kind: 'bold' } + | { kind: 'italic' } + | { kind: 'underline' } + | { kind: 'strikethrough' } + | { kind: 'header', level: number } + | { kind: 'text', value: string } +); +function* tokenize(characters: string): Generator { + let buffer: string = ''; + let clearBuffer = false; + let start = 0; + let i = 0; + + for (const character of characters) { + if (buffer.length === 0) { + start = i; + } + + buffer += character; + const length = buffer.length; + + if (buffer === '**') { + yield { kind: 'bold', start, length }; + clearBuffer = true; + } + else if (buffer === '') { + yield { kind: 'italic', start, length }; + clearBuffer = true; + } + else if (buffer === ':') { + yield { kind: 'underline', start, length }; + clearBuffer = true; + } + else if (buffer === ':') { + yield { kind: 'strikethrough', start, length }; + clearBuffer = true; + } + else if (buffer.length > 1 && buffer.startsWith('#') && buffer.endsWith(' ')) { + yield { kind: 'header', start, length, level: buffer.length - 1 }; + clearBuffer = true; + } + else if (buffer.length > 1 && buffer.startsWith('"') && buffer.endsWith('"')) { + yield { kind: 'text', start, length, value: buffer.slice(1, buffer.length - 1) }; + clearBuffer = true; + } + + if (clearBuffer) { + buffer = ''; + clearBuffer = false; + } + + i++; + } +} \ No newline at end of file diff --git a/src/features/source/source.ts b/src/features/source/source.ts new file mode 100644 index 0000000..172acbe --- /dev/null +++ b/src/features/source/source.ts @@ -0,0 +1,31 @@ +import { createEffect, createSignal, Signal } from "solid-js"; +import { Parser, RichTextAST } from "./parser"; + +export interface Source { + readonly in: Signal; + readonly out: Signal; +} + +export function createSource(inParser: TIn, outParser: TOut, initalValue: string): Source { + const [inValue, setIn] = createSignal(initalValue); + const [outValue, setOut] = createSignal(''); + + const [ast, setAst] = createSignal(); + + createEffect(() => { + setAst(inParser.parse(inValue())); + }); + + createEffect(() => { + setAst(outParser.parse(outValue())); + }); + + return { + get in() { + return [inValue, setIn] as Signal; + }, + get out() { + return [outValue, setOut] as Signal; + }, + }; +} \ No newline at end of file diff --git a/src/routes/(editor)/edit.tsx b/src/routes/(editor)/edit.tsx index 8076c91..d4d5c96 100644 --- a/src/routes/(editor)/edit.tsx +++ b/src/routes/(editor)/edit.tsx @@ -15,6 +15,7 @@ import { writeClipboard } from "@solid-primitives/clipboard"; import { destructure } from "@solid-primitives/destructure"; import css from "./edit.module.css"; import { contentsOf } from "~/features/file/helpers"; +import { createHtmlParser, createMarkdownParser, createSource } from "~/features/source"; const isInstalledPWA = !isServer && window.matchMedia('(display-mode: standalone)').matches; @@ -389,17 +390,52 @@ const Content: Component<{ directory: FileSystemDirectoryHandle, api?: Setter writeClipboard(key)); - return { - key => { - return - { - command => - } + const tempVal = ` +# Header - {key.split('.').at(-1)!} - ; - } - }; +this is **a string** that contains bolded text + +this is *a string* that contains italicized text + +> Dorothy followed her through many of the beautiful rooms in her castle. + +> Dorothy followed her through many of the beautiful rooms in her castle. +> +>> The Witch bade her clean the pots and kettles and sweep the floor and keep the fire fed with wood. + +> #### The quarterly results look great! +> +> - Revenue was off the chart. +> - Profits were higher than ever. +> +> *Everything* is going according to **plan**. + +- First item +- Second item +- Third item +- Fourth item + `; + const { out: [html, update] } = createSource(createMarkdownParser(), createHtmlParser(), tempVal); + + createEffect(() => { + console.log(html()); + }); + + return <> +
+ + { + key => { + return + { + command => + } + + {key.split('.').at(-1)!} + ; + } + } + ; }; const Blank: Component<{ open: CommandType }> = (props) => {