From bc6b6a7db487abe0b0b4eecef03d4681645709ca Mon Sep 17 00:00:00 2001 From: Artemy Egorov Date: Wed, 24 Jul 2024 23:48:18 +0300 Subject: [PATCH] feat: add typescript lib, add daletl parser, add html converter --- libs/typescript/.eslintrc.json | 14 ++++++ .gitignore => libs/typescript/.gitignore | 0 libs/typescript/package.json | 36 +++++++++++++ libs/typescript/pnpm-lock.yaml | 33 ++++++++++++ libs/typescript/src/converters/html.ts | 51 +++++++++++++++++++ libs/typescript/src/converters/main.ts | 1 + libs/typescript/src/daletl/main.ts | 64 ++++++++++++++++++++++++ libs/typescript/src/daletl/types.ts | 14 ++++++ libs/typescript/src/lib.ts | 2 + libs/typescript/tsconfig.json | 9 ++++ 10 files changed, 224 insertions(+) create mode 100644 libs/typescript/.eslintrc.json rename .gitignore => libs/typescript/.gitignore (100%) create mode 100644 libs/typescript/package.json create mode 100644 libs/typescript/pnpm-lock.yaml create mode 100644 libs/typescript/src/converters/html.ts create mode 100644 libs/typescript/src/converters/main.ts create mode 100644 libs/typescript/src/daletl/main.ts create mode 100644 libs/typescript/src/daletl/types.ts create mode 100644 libs/typescript/src/lib.ts create mode 100644 libs/typescript/tsconfig.json diff --git a/libs/typescript/.eslintrc.json b/libs/typescript/.eslintrc.json new file mode 100644 index 0000000..380b417 --- /dev/null +++ b/libs/typescript/.eslintrc.json @@ -0,0 +1,14 @@ +{ + "env": { + "browser": true, + "es2021": true + }, + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": ["@typescript-eslint"], + "rules": {} +} diff --git a/.gitignore b/libs/typescript/.gitignore similarity index 100% rename from .gitignore rename to libs/typescript/.gitignore diff --git a/libs/typescript/package.json b/libs/typescript/package.json new file mode 100644 index 0000000..50cf9ec --- /dev/null +++ b/libs/typescript/package.json @@ -0,0 +1,36 @@ +{ + "name": "@txtdot/dalet", + "version": "1.0.0-pre0", + "description": "Dalet realization in typescript", + "main": "dist/lib.js", + "types": "dist/lib.d.ts", + "files": [ + "/dist" + ], + "scripts": { + "build": "tsc" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/TxtDot/dalet.git" + }, + "keywords": [ + "dalet", + "markup-language", + "markup", + "language", + "web" + ], + "author": "artegoser", + "license": "MIT", + "bugs": { + "url": "https://github.com/TxtDot/dalet/issues" + }, + "homepage": "https://github.com/TxtDot/dalet#readme", + "devDependencies": { + "tsc": "^2.0.4" + }, + "dependencies": { + "@msgpack/msgpack": "3.0.0-beta2" + } +} diff --git a/libs/typescript/pnpm-lock.yaml b/libs/typescript/pnpm-lock.yaml new file mode 100644 index 0000000..e226c92 --- /dev/null +++ b/libs/typescript/pnpm-lock.yaml @@ -0,0 +1,33 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@msgpack/msgpack': + specifier: 3.0.0-beta2 + version: 3.0.0-beta2 + devDependencies: + tsc: + specifier: ^2.0.4 + version: 2.0.4 + +packages: + + '@msgpack/msgpack@3.0.0-beta2': + resolution: {integrity: sha512-y+l1PNV0XDyY8sM3YtuMLK5vE3/hkfId+Do8pLo/OPxfxuFAUwcGz3oiiUuV46/aBpwTzZ+mRWVMtlSKbradhw==} + engines: {node: '>= 14'} + + tsc@2.0.4: + resolution: {integrity: sha512-fzoSieZI5KKJVBYGvwbVZs/J5za84f2lSTLPYf6AGiIf43tZ3GNrI1QzTLcjtyDDP4aLxd46RTZq1nQxe7+k5Q==} + hasBin: true + +snapshots: + + '@msgpack/msgpack@3.0.0-beta2': {} + + tsc@2.0.4: {} diff --git a/libs/typescript/src/converters/html.ts b/libs/typescript/src/converters/html.ts new file mode 100644 index 0000000..dfa09a7 --- /dev/null +++ b/libs/typescript/src/converters/html.ts @@ -0,0 +1,51 @@ +import { Root, Tag } from "../daletl/types"; + +interface Props { + [key: string]: string; +} + +function hy(tag: string, body?: string, props?: Props) { + return `<${tag} ${ + props + ? Object.entries(props) + .map(([key, value]) => `${key}="${value}"`) + .join(" ") + : "" + }>${body}`; +} + +function comp( + name: string, + body: string | Tag[], + classNames: string, + classes: boolean, + props: Props = {} +): string { + let realBody = Array.isArray(body) + ? body.map((b) => htmlTag(b, classes)).join("") + : body; + return hy(name, realBody, { + class: classes ? classNames : undefined, + ...props, + }); +} + +function element(tag: Tag, classes: boolean): string { + return comp("section", tag.body, "el", classes); +} + +function heading(tag: Tag, classes: boolean): string { + if (typeof tag.argument !== "number") { + return comp("h1", tag.body, "h", classes); + } + + return comp(`h${tag.argument}`, tag.body, `h hl${tag.argument}`, classes); +} + +function htmlTag(tag: Tag, classes: boolean): string { + return [element, heading][tag.id](tag, classes); +} + +export function toHtml(root: Root, classes: boolean = true): string { + return root.map((t) => htmlTag(t, classes)).join(""); +} diff --git a/libs/typescript/src/converters/main.ts b/libs/typescript/src/converters/main.ts new file mode 100644 index 0000000..1dfb5b9 --- /dev/null +++ b/libs/typescript/src/converters/main.ts @@ -0,0 +1 @@ +export { toHtml } from "./html"; diff --git a/libs/typescript/src/daletl/main.ts b/libs/typescript/src/daletl/main.ts new file mode 100644 index 0000000..222f818 --- /dev/null +++ b/libs/typescript/src/daletl/main.ts @@ -0,0 +1,64 @@ +import { encode, decode } from "@msgpack/msgpack"; +import { ParseError, Root, Tag } from "./types"; + +export function parseRawTag(raw_tag: any[] | string): Tag { + if (typeof raw_tag === "string") { + return { + id: 0, + body: raw_tag, + argument: null, + }; + } + + if (Array.isArray(raw_tag)) { + if (Array.isArray(raw_tag[0])) { + return { + id: 0, + body: parseRawTagBody(raw_tag), + argument: null, + }; + } + + if (typeof raw_tag[0] === "number") { + return { + id: raw_tag[0], + body: parseRawTagBody(raw_tag[1]), + argument: raw_tag[3] || null, + }; + } + } + + throw new ParseError("Invalid tag"); +} + +export function parseRawTagBody(body: string | null | any[]): Tag["body"] { + if (typeof body === "string") { + return body; + } + + if (body === null) { + return null; + } + + if (Array.isArray(body)) { + if (Array.isArray(body[0])) { + return body.map(parseRawTag); + } + + if (typeof body[0] === "number") { + return [parseRawTag(body)]; + } + } + + throw new ParseError("Invalid tag body"); +} + +export function parse(root_data?: Uint8Array): Root { + let root = root_data ? decode(root_data) : []; + + if (!Array.isArray(root)) { + throw new ParseError("Daletl root must be array"); + } + + return root.map(parseRawTag); +} diff --git a/libs/typescript/src/daletl/types.ts b/libs/typescript/src/daletl/types.ts new file mode 100644 index 0000000..001f0de --- /dev/null +++ b/libs/typescript/src/daletl/types.ts @@ -0,0 +1,14 @@ +export interface Tag { + id: number; + body: string | null | Tag[]; + argument: number | string | null; +} + +export type Root = Tag[]; + +export class ParseError extends Error { + constructor(message: string = "Parse error") { + super(message); + this.name = "ParseError"; + } +} diff --git a/libs/typescript/src/lib.ts b/libs/typescript/src/lib.ts new file mode 100644 index 0000000..fc6d03a --- /dev/null +++ b/libs/typescript/src/lib.ts @@ -0,0 +1,2 @@ +export { parse } from "./daletl/main"; +export * as converters from "./converters/main"; diff --git a/libs/typescript/tsconfig.json b/libs/typescript/tsconfig.json new file mode 100644 index 0000000..59c6c79 --- /dev/null +++ b/libs/typescript/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es2019", + "declaration": true, + "outDir": "./dist" + }, + "include": ["src/**/*"] +}