mirror of
https://github.com/TxtDot/dalet.git
synced 2024-12-25 20:23:44 +03:00
fix: refactor, tag classes, daletl add data type of tag
This commit is contained in:
parent
bc6b6a7db4
commit
599639dee6
12 changed files with 1178 additions and 99 deletions
|
@ -1,14 +0,0 @@
|
|||
{
|
||||
"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": {}
|
||||
}
|
11
libs/typescript/eslint.config.mjs
Normal file
11
libs/typescript/eslint.config.mjs
Normal file
|
@ -0,0 +1,11 @@
|
|||
import globals from "globals";
|
||||
import pluginJs from "@eslint/js";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
|
||||
export default [
|
||||
{files: ["**/*.{js,mjs,cjs,ts}"]},
|
||||
{languageOptions: { globals: globals.browser }},
|
||||
pluginJs.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
];
|
|
@ -28,7 +28,11 @@
|
|||
},
|
||||
"homepage": "https://github.com/TxtDot/dalet#readme",
|
||||
"devDependencies": {
|
||||
"tsc": "^2.0.4"
|
||||
"@eslint/js": "^9.7.0",
|
||||
"eslint": "9.x",
|
||||
"globals": "^15.8.0",
|
||||
"tsc": "^2.0.4",
|
||||
"typescript-eslint": "^7.17.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@msgpack/msgpack": "3.0.0-beta2"
|
||||
|
|
1005
libs/typescript/pnpm-lock.yaml
generated
1005
libs/typescript/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
@ -1,51 +0,0 @@
|
|||
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}</${tag}>`;
|
||||
}
|
||||
|
||||
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("");
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export { toHtml } from "./html";
|
|
@ -1,37 +1,34 @@
|
|||
import { encode, decode } from "@msgpack/msgpack";
|
||||
import { ParseError, Root, Tag } from "./types";
|
||||
import { ParseError, RawTag, Tag, RawTagAsArray, RawBody, Body } from "./types";
|
||||
import El from "./tags/el";
|
||||
import { TagNormalizers } from "./normalizers";
|
||||
|
||||
export function parseRawTag(raw_tag: any[] | string): Tag {
|
||||
export function parseTag(raw_tag: RawTag): Tag {
|
||||
if (typeof raw_tag === "string") {
|
||||
return {
|
||||
id: 0,
|
||||
body: raw_tag,
|
||||
argument: null,
|
||||
};
|
||||
return new El(raw_tag);
|
||||
}
|
||||
|
||||
if (typeof raw_tag === "number") {
|
||||
return TagNormalizers[raw_tag]([raw_tag, null]);
|
||||
}
|
||||
|
||||
if (Array.isArray(raw_tag)) {
|
||||
if (Array.isArray(raw_tag[0])) {
|
||||
return {
|
||||
id: 0,
|
||||
body: parseRawTagBody(raw_tag),
|
||||
argument: null,
|
||||
};
|
||||
raw_tag = raw_tag as RawTag[];
|
||||
return new El(raw_tag.map(parseTag));
|
||||
}
|
||||
|
||||
if (typeof raw_tag[0] === "number") {
|
||||
return {
|
||||
id: raw_tag[0],
|
||||
body: parseRawTagBody(raw_tag[1]),
|
||||
argument: raw_tag[3] || null,
|
||||
};
|
||||
return TagNormalizers[(raw_tag as RawTagAsArray)[0]](
|
||||
raw_tag as RawTagAsArray
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
throw new ParseError("Invalid tag");
|
||||
}
|
||||
|
||||
export function parseRawTagBody(body: string | null | any[]): Tag["body"] {
|
||||
export function parseBody(body: RawBody): Body {
|
||||
if (typeof body === "string") {
|
||||
return body;
|
||||
}
|
||||
|
@ -42,23 +39,38 @@ export function parseRawTagBody(body: string | null | any[]): Tag["body"] {
|
|||
|
||||
if (Array.isArray(body)) {
|
||||
if (Array.isArray(body[0])) {
|
||||
return body.map(parseRawTag);
|
||||
return body.map(parseTag);
|
||||
}
|
||||
|
||||
if (typeof body[0] === "number") {
|
||||
return [parseRawTag(body)];
|
||||
return [parseTag(body)];
|
||||
}
|
||||
}
|
||||
|
||||
throw new ParseError("Invalid tag body");
|
||||
}
|
||||
|
||||
export function parse(root_data?: Uint8Array): Root {
|
||||
let root = root_data ? decode(root_data) : [];
|
||||
export function parse(root_data: Uint8Array): Tag[] {
|
||||
let root = decode(root_data);
|
||||
|
||||
if (!Array.isArray(root)) {
|
||||
throw new ParseError("Daletl root must be array");
|
||||
}
|
||||
|
||||
return root.map(parseRawTag);
|
||||
return root.map(parseTag);
|
||||
}
|
||||
|
||||
export class Root {
|
||||
root: Tag[];
|
||||
constructor(root: Tag[]) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
encode(): Uint8Array {
|
||||
return encode(this.root.map((t) => t.encode()));
|
||||
}
|
||||
|
||||
toHtml(classes?: boolean): string {
|
||||
return this.root.map((t) => t.toHtml(classes)).join("");
|
||||
}
|
||||
}
|
||||
|
|
17
libs/typescript/src/daletl/normalizers.ts
Normal file
17
libs/typescript/src/daletl/normalizers.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { parseBody } from "./main";
|
||||
import El from "./tags/el";
|
||||
import { ParseError, RawTagAsArray } from "./types";
|
||||
|
||||
export function ElNormalizer(tag: RawTagAsArray): El {
|
||||
let body = parseBody(tag[1]);
|
||||
|
||||
if (body == null) {
|
||||
throw new ParseError("Invalid tag body, must be not null");
|
||||
}
|
||||
|
||||
return new El(body);
|
||||
}
|
||||
|
||||
const TagNormalizers = [ElNormalizer];
|
||||
|
||||
export { TagNormalizers };
|
16
libs/typescript/src/daletl/tags/el.ts
Normal file
16
libs/typescript/src/daletl/tags/el.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { bodyToRaw } from "../../utils";
|
||||
import { RawTag, Tag, Body } from "../types";
|
||||
|
||||
export default class El extends Tag {
|
||||
constructor(body: string | Tag[]) {
|
||||
super(0, body, null);
|
||||
}
|
||||
|
||||
public get raw(): RawTag {
|
||||
return bodyToRaw(this.body);
|
||||
}
|
||||
|
||||
public toHtml(classes?: boolean): string {
|
||||
return "";
|
||||
}
|
||||
}
|
|
@ -1,10 +1,13 @@
|
|||
export interface Tag {
|
||||
id: number;
|
||||
body: string | null | Tag[];
|
||||
argument: number | string | null;
|
||||
}
|
||||
import { encode } from "@msgpack/msgpack";
|
||||
import { bodyToRaw } from "../utils";
|
||||
|
||||
export type Root = Tag[];
|
||||
export type RawBody = string | null | RawTag[] | RawTag;
|
||||
export type RawId = number;
|
||||
export type RawArgument = number | string | null;
|
||||
export type RawTagAsArray = [RawId, RawBody, RawArgument] | [RawId, RawBody];
|
||||
|
||||
export type RawTag = RawTagAsArray | number | string | RawTag[];
|
||||
export type RootRaw = RawTag[];
|
||||
|
||||
export class ParseError extends Error {
|
||||
constructor(message: string = "Parse error") {
|
||||
|
@ -12,3 +15,33 @@ export class ParseError extends Error {
|
|||
this.name = "ParseError";
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class Tag {
|
||||
id: number;
|
||||
body: Body;
|
||||
argument: Argument;
|
||||
constructor(id: number, body: Body, argument: Argument) {
|
||||
this.id = id;
|
||||
this.body = body;
|
||||
this.argument = argument;
|
||||
}
|
||||
get raw(): RawTag {
|
||||
if (this.argument == null) {
|
||||
if (this.body == null) {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
return [this.id, bodyToRaw(this.body)];
|
||||
}
|
||||
return [this.id, bodyToRaw(this.body), this.argument];
|
||||
}
|
||||
encode(): Uint8Array {
|
||||
return encode(this.raw);
|
||||
}
|
||||
abstract toHtml(classes?: boolean): string;
|
||||
}
|
||||
|
||||
export type Body = string | Tag[] | null;
|
||||
export type Argument = RawArgument;
|
||||
|
||||
export type TagNormalizer = (tag: RawTagAsArray) => Tag;
|
||||
|
|
33
libs/typescript/src/utils.ts
Normal file
33
libs/typescript/src/utils.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import { Body, ParseError, RawBody, RawTag, Tag } from "./daletl/types";
|
||||
|
||||
export function bodyToRaw(body: Body): RawBody {
|
||||
if (typeof body === "string") {
|
||||
return body;
|
||||
}
|
||||
|
||||
if (Array.isArray(body)) {
|
||||
if (Array.isArray(body[0])) {
|
||||
return body.map(getRaw);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getRaw(t: Tag): RawTag {
|
||||
return t.raw;
|
||||
}
|
||||
|
||||
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}</${tag}>`;
|
||||
}
|
|
@ -16,14 +16,14 @@ Daletl root is array of tags. For convenience, we will use the json5 representat
|
|||
|
||||
All tags specification is in [Tags](./tags.md).
|
||||
|
||||
Each tag may be one of three types:
|
||||
Each tag may be one of four types:
|
||||
|
||||
#### Data Representation
|
||||
|
||||
##### As array of 1-3 elements
|
||||
##### As array of 2-3 elements
|
||||
|
||||
1. Tag id
|
||||
2. Tag body (optional if argument not specified, if argument specified it must be null)
|
||||
2. Tag body
|
||||
3. Tag argument (optional)
|
||||
|
||||
Tag id is integer number.
|
||||
|
@ -50,6 +50,20 @@ Argument can be number or string.
|
|||
]
|
||||
```
|
||||
|
||||
##### As number
|
||||
|
||||
Number becomes tag.
|
||||
|
||||
```json5
|
||||
1
|
||||
```
|
||||
|
||||
equals to
|
||||
|
||||
```json5
|
||||
[1, null]
|
||||
```
|
||||
|
||||
##### As string
|
||||
|
||||
String becomes element tag.
|
||||
|
|
Loading…
Add table
Reference in a new issue