mirror of
https://github.com/TxtDot/dalet.git
synced 2024-11-21 20:36:23 +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",
|
"homepage": "https://github.com/TxtDot/dalet#readme",
|
||||||
"devDependencies": {
|
"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": {
|
"dependencies": {
|
||||||
"@msgpack/msgpack": "3.0.0-beta2"
|
"@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 { 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") {
|
if (typeof raw_tag === "string") {
|
||||||
return {
|
return new El(raw_tag);
|
||||||
id: 0,
|
}
|
||||||
body: raw_tag,
|
|
||||||
argument: null,
|
if (typeof raw_tag === "number") {
|
||||||
};
|
return TagNormalizers[raw_tag]([raw_tag, null]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(raw_tag)) {
|
if (Array.isArray(raw_tag)) {
|
||||||
if (Array.isArray(raw_tag[0])) {
|
if (Array.isArray(raw_tag[0])) {
|
||||||
return {
|
raw_tag = raw_tag as RawTag[];
|
||||||
id: 0,
|
return new El(raw_tag.map(parseTag));
|
||||||
body: parseRawTagBody(raw_tag),
|
|
||||||
argument: null,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof raw_tag[0] === "number") {
|
if (typeof raw_tag[0] === "number") {
|
||||||
return {
|
return TagNormalizers[(raw_tag as RawTagAsArray)[0]](
|
||||||
id: raw_tag[0],
|
raw_tag as RawTagAsArray
|
||||||
body: parseRawTagBody(raw_tag[1]),
|
);
|
||||||
argument: raw_tag[3] || null,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ParseError("Invalid tag");
|
throw new ParseError("Invalid tag");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseRawTagBody(body: string | null | any[]): Tag["body"] {
|
export function parseBody(body: RawBody): Body {
|
||||||
if (typeof body === "string") {
|
if (typeof body === "string") {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
@ -42,23 +39,38 @@ export function parseRawTagBody(body: string | null | any[]): Tag["body"] {
|
||||||
|
|
||||||
if (Array.isArray(body)) {
|
if (Array.isArray(body)) {
|
||||||
if (Array.isArray(body[0])) {
|
if (Array.isArray(body[0])) {
|
||||||
return body.map(parseRawTag);
|
return body.map(parseTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof body[0] === "number") {
|
if (typeof body[0] === "number") {
|
||||||
return [parseRawTag(body)];
|
return [parseTag(body)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ParseError("Invalid tag body");
|
throw new ParseError("Invalid tag body");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parse(root_data?: Uint8Array): Root {
|
export function parse(root_data: Uint8Array): Tag[] {
|
||||||
let root = root_data ? decode(root_data) : [];
|
let root = decode(root_data);
|
||||||
|
|
||||||
if (!Array.isArray(root)) {
|
if (!Array.isArray(root)) {
|
||||||
throw new ParseError("Daletl root must be array");
|
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 {
|
import { encode } from "@msgpack/msgpack";
|
||||||
id: number;
|
import { bodyToRaw } from "../utils";
|
||||||
body: string | null | Tag[];
|
|
||||||
argument: number | string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
export class ParseError extends Error {
|
||||||
constructor(message: string = "Parse error") {
|
constructor(message: string = "Parse error") {
|
||||||
|
@ -12,3 +15,33 @@ export class ParseError extends Error {
|
||||||
this.name = "ParseError";
|
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).
|
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
|
#### Data Representation
|
||||||
|
|
||||||
##### As array of 1-3 elements
|
##### As array of 2-3 elements
|
||||||
|
|
||||||
1. Tag id
|
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)
|
3. Tag argument (optional)
|
||||||
|
|
||||||
Tag id is integer number.
|
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
|
##### As string
|
||||||
|
|
||||||
String becomes element tag.
|
String becomes element tag.
|
||||||
|
|
Loading…
Add table
Reference in a new issue