2
0
mirror of https://github.com/tenrok/BBob.git synced 2026-05-15 11:59:37 +03:00

fix(#206): TagNode.create now with null content argument by default (#233)

* fix: TagNode.create with null content by default

* Create five-meals-sing.md

* fix: tests

* fix(preset): types inference

* fix: preset types

* fix: preset types

* fix: lock file, parser and utils

* refactor: move types to separate package

* fix(preset): add @bbob/core to dev deps

* fix(preset): lock file

* test(preset-vue): create tags

* test(preset-vue): tests

* chore(nx): fix nx cover deps

* chore: changesets
This commit is contained in:
Nikolay Kost
2024-06-24 01:32:15 +03:00
committed by GitHub
parent 95d9b8a2ba
commit 270f5645f8
58 changed files with 657 additions and 428 deletions
+27
View File
@@ -0,0 +1,27 @@
---
"@bbob/plugin-helper": minor
"@bbob/preset-html5": minor
"@bbob/preset-react": minor
"@bbob/preset-vue": minor
"@bbob/parser": minor
"@bbob/preset": minor
"@bbob/react": minor
"@bbob/core": minor
"@bbob/html": minor
"@bbob/vue2": minor
"@bbob/vue3": minor
"@bbob/cli": minor
---
** BREAKING CHANGE **
`TagNode.create` method now by default pass `null` to content instead of empty array `[]`
```js
// new behavior
TagNode.create('img').toString() // -> [img]
// old behavior
TagNode.create('img', {}, []).toString() // -> [img][/img]
```
Migrate all calls of `TagNode.create('test-tag')` to `TagNode.create('test-tag', {}, [])
+18
View File
@@ -0,0 +1,18 @@
/* eslint-disable global-require */
const parser = require('@bbob/parser');
const stub = require('./test/stub');
const passes = 100;
const results = new Array(passes);
const lexer = parser.createLexer;
// eslint-disable-next-line no-plusplus
for (let i = 0; i < passes; i++) {
results[i] = parser.parse(stub, {
onlyAllowTags: ['ch'],
createTokenizer: lexer,
});
}
console.log(results.length);
+3 -1
View File
@@ -6,7 +6,8 @@
"test": "test" "test": "test"
}, },
"scripts": { "scripts": {
"start": "node index.js" "start": "node index.js",
"cpupro": "node --require cpupro benchmark.js"
}, },
"author": { "author": {
"name": "Nikolay Kostyurin <jilizart@gmail.com>", "name": "Nikolay Kostyurin <jilizart@gmail.com>",
@@ -18,6 +19,7 @@
"benchmark": "2.1.4", "benchmark": "2.1.4",
"picocolors": "1.0.0", "picocolors": "1.0.0",
"xbbcode-parser": "0.1.2", "xbbcode-parser": "0.1.2",
"cpupro": "*",
"ya-bbcode": "1.0.12" "ya-bbcode": "1.0.12"
} }
} }
+2 -1
View File
@@ -16,7 +16,8 @@
"packages/bbob-preset-vue", "packages/bbob-preset-vue",
"packages/bbob-react", "packages/bbob-react",
"packages/bbob-vue2", "packages/bbob-vue2",
"packages/bbob-vue3" "packages/bbob-vue3",
"packages/bbob-types"
], ],
"publishConfig": { "publishConfig": {
"access": "public", "access": "public",
+5 -10
View File
@@ -5,27 +5,25 @@
"^types" "^types"
], ],
"outputs": ["{projectRoot}/types"], "outputs": ["{projectRoot}/types"],
"cache": true
}, },
"build": { "build": {
"dependsOn": [ "dependsOn": [
"^types", "^types",
"^build:commonjs",
"^build:es", "^build:es",
"^build:commonjs",
"^build:umd" "^build:umd"
], ],
"outputs": ["{projectRoot}/lib", "{projectRoot}/es", "{projectRoot}/dist"], "outputs": ["{projectRoot}/lib", "{projectRoot}/es", "{projectRoot}/dist"],
"cache": true
}, },
"test": { "test": {
"dependsOn": [ "dependsOn": [
"^build", "build",
"^test" "^test"
] ]
}, },
"cover": { "cover": {
"dependsOn": [ "dependsOn": [
"^build", "build",
"^cover" "^cover"
], ],
"outputs": ["{projectRoot}/coverage"] "outputs": ["{projectRoot}/coverage"]
@@ -37,26 +35,23 @@
}, },
"build:commonjs": { "build:commonjs": {
"dependsOn": [ "dependsOn": [
"^build:es", "build:es",
"^build:commonjs" "^build:commonjs"
], ],
"outputs": ["{projectRoot}/lib"], "outputs": ["{projectRoot}/lib"],
"cache": true
}, },
"build:es": { "build:es": {
"dependsOn": [ "dependsOn": [
"^build:es" "^build:es"
], ],
"outputs": ["{projectRoot}/es"], "outputs": ["{projectRoot}/es"],
"cache": true
}, },
"build:umd": { "build:umd": {
"dependsOn": [ "dependsOn": [
"^build:es", "build:es",
"^build:umd" "^build:umd"
], ],
"outputs": ["{projectRoot}/dist"], "outputs": ["{projectRoot}/dist"],
"cache": true
} }
}, },
"$schema": "./node_modules/nx/schemas/nx-schema.json", "$schema": "./node_modules/nx/schemas/nx-schema.json",
+1
View File
@@ -47,6 +47,7 @@
"build:umd": "pkg-task", "build:umd": "pkg-task",
"build": "pkg-task", "build": "pkg-task",
"test": "pkg-task", "test": "pkg-task",
"cover": "pkg-task",
"lint": "pkg-task", "lint": "pkg-task",
"size": "pkg-task", "size": "pkg-task",
"bundlesize": "pkg-task", "bundlesize": "pkg-task",
+2 -1
View File
@@ -21,7 +21,8 @@
], ],
"dependencies": { "dependencies": {
"@bbob/parser": "*", "@bbob/parser": "*",
"@bbob/plugin-helper": "*" "@bbob/plugin-helper": "*",
"@bbob/types": "*"
}, },
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
+10 -6
View File
@@ -1,13 +1,17 @@
import type {
BBobCore,
BBobCoreOptions,
BBobCoreTagNodeTree,
BBobPlugins,
IterateCallback,
NodeContent,
PartialNodeContent
} from "@bbob/types";
import { parse } from '@bbob/parser'; import { parse } from '@bbob/parser';
import { iterate, match } from './utils'; import { iterate, match } from './utils';
import { C1, C2 } from './errors' import { C1, C2 } from './errors'
import type { IterateCallback } from './utils';
import type { NodeContent, PartialNodeContent } from "@bbob/plugin-helper";
import type { BBobCore, BBobCoreOptions, BBobCoreTagNodeTree, BBobPlugins } from "./types";
export * from './types'
export function createTree<Options extends BBobCoreOptions = BBobCoreOptions>(tree: NodeContent[], options: Options) { export function createTree<Options extends BBobCoreOptions = BBobCoreOptions>(tree: NodeContent[], options: Options) {
const extendedTree = tree as BBobCoreTagNodeTree const extendedTree = tree as BBobCoreTagNodeTree
-57
View File
@@ -1,57 +0,0 @@
import type { ParseOptions, TagNode } from "@bbob/parser";
import type {
NodeContent,
PartialNodeContent,
TagNodeTree,
} from "@bbob/plugin-helper";
import type { IterateCallback, iterate } from "./utils";
export interface BBobCoreOptions<
Data = unknown | null,
Options extends ParseOptions = ParseOptions
> extends ParseOptions {
skipParse?: boolean;
parser?: (source: string, options?: Options) => TagNode[];
render?: (ast: TagNodeTree, options?: Options) => string;
data?: Data;
}
export interface BbobPluginOptions<
Options extends ParseOptions = ParseOptions
> {
parse: BBobCoreOptions["parser"];
render: (ast: TagNodeTree, options?: Options) => string;
iterate: typeof iterate;
data: unknown | null;
}
export interface BBobPluginFunction {
(tree: BBobCoreTagNodeTree, options: BbobPluginOptions): BBobCoreTagNodeTree;
}
export interface BBobCore<
InputValue = string | TagNode[],
Options extends BBobCoreOptions = BBobCoreOptions
> {
process(
input: InputValue,
opts?: Options
): {
readonly html: string;
tree: BBobCoreTagNodeTree;
raw: TagNode[] | string;
messages: unknown[];
};
}
export interface BBobCoreTagNodeTree extends Array<NodeContent> {
messages: unknown[];
options: BBobCoreOptions;
walk: (cb: IterateCallback<NodeContent>) => BBobCoreTagNodeTree;
match: (
expression: PartialNodeContent | PartialNodeContent[],
cb: IterateCallback<NodeContent>
) => BBobCoreTagNodeTree;
}
export type BBobPlugins = BBobPluginFunction | BBobPluginFunction[];
+2 -2
View File
@@ -1,9 +1,9 @@
/* eslint-disable no-plusplus */ /* eslint-disable no-plusplus */
import { IterateCallback } from "@bbob/types";
const isObj = (value: unknown): value is Record<string, unknown> => (typeof value === 'object' && value !== null); const isObj = (value: unknown): value is Record<string, unknown> => (typeof value === 'object' && value !== null);
const isBool = (value: unknown): value is boolean => (typeof value === 'boolean'); const isBool = (value: unknown): value is boolean => (typeof value === 'boolean');
export type IterateCallback<Content> = (node: Content) => Content
export function iterate<Content, Iterable = ArrayLike<Content> | Content>(t: Iterable, cb: IterateCallback<Content>): Iterable { export function iterate<Content, Iterable = ArrayLike<Content> | Content>(t: Iterable, cb: IterateCallback<Content>): Iterable {
const tree = t; const tree = t;
+1 -1
View File
@@ -71,7 +71,7 @@ describe('@bbob/core', () => {
const plugin: BBobPluginFunction = (tree) => tree.walk(node => { const plugin: BBobPluginFunction = (tree) => tree.walk(node => {
if (node === ':)') { if (node === ':)') {
return TagNode.create('test-tag') return TagNode.create('test-tag', {}, [])
} }
return node return node
+2 -1
View File
@@ -10,7 +10,8 @@
], ],
"dependencies": { "dependencies": {
"@bbob/core": "*", "@bbob/core": "*",
"@bbob/plugin-helper": "*" "@bbob/plugin-helper": "*",
"@bbob/types": "*"
}, },
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
+7 -6
View File
@@ -1,14 +1,15 @@
import core, { BBobCoreOptions, BBobPlugins } from '@bbob/core'; import core from '@bbob/core';
import { attrsToString, isTagNode, TagNode, TagNodeTree } from '@bbob/plugin-helper'; import { attrsToString, isTagNode, TagNode } from '@bbob/plugin-helper';
import type { BBobCoreOptions, BBobPlugins, TagNodeTree } from '@bbob/types';
const SELFCLOSE_END_TAG = '/>'; const SELFCLOSE_END_TAG = '/>';
const CLOSE_START_TAG = '</'; const CLOSE_START_TAG = '</';
const START_TAG = '<'; const START_TAG = '<';
const END_TAG = '>'; const END_TAG = '>';
export type BBobHTMLOptions = { interface BBobHTMLOptions extends BBobCoreOptions {
stripTags?: boolean stripTags?: boolean
} & BBobCoreOptions }
function renderNode(node?: TagNodeTree, options?: BBobHTMLOptions): string { function renderNode(node?: TagNodeTree, options?: BBobHTMLOptions): string {
const { stripTags = false } = options || {} const { stripTags = false } = options || {}
@@ -42,8 +43,8 @@ function renderNode(node?: TagNodeTree, options?: BBobHTMLOptions): string {
return ''; return '';
} }
export function render(nodes: TagNodeTree, options?: BBobHTMLOptions): string { export function render(nodes?: TagNodeTree, options?: BBobHTMLOptions): string {
if (Array.isArray(nodes)) { if (nodes && Array.isArray(nodes)) {
return nodes.reduce<string>((r, node) => r + renderNode(node, options), '') return nodes.reduce<string>((r, node) => r + renderNode(node, options), '')
} }
+2 -1
View File
@@ -20,7 +20,8 @@
"types" "types"
], ],
"dependencies": { "dependencies": {
"@bbob/plugin-helper": "*" "@bbob/plugin-helper": "*",
"@bbob/types": "*"
}, },
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
+6 -5
View File
@@ -3,6 +3,7 @@ import {
CLOSE_BRAKET, CLOSE_BRAKET,
SLASH, SLASH,
} from '@bbob/plugin-helper'; } from '@bbob/plugin-helper';
import type { Token as TokenInterface } from "@bbob/types";
// type, value, line, row, // type, value, line, row,
@@ -87,11 +88,11 @@ const tokenToText = (token: Token) => {
* @export * @export
* @class Token * @class Token
*/ */
class Token<TokenValue = string> { class Token<TokenValue = string> implements TokenInterface {
private t: number // type readonly t: number // type
private v: string // value readonly v: string // value
private l: number // line readonly l: number // line
private r: number // row readonly r: number // row
constructor(type?: number, value?: TokenValue, row: number = 0, col: number = 0) { constructor(type?: number, value?: TokenValue, row: number = 0, col: number = 0) {
this[TOKEN_LINE_ID] = row; this[TOKEN_LINE_ID] = row;
-1
View File
@@ -2,4 +2,3 @@ export { TagNode } from '@bbob/plugin-helper';
export { default } from './parse'; export { default } from './parse';
export * from './parse'; export * from './parse';
export * from './lexer' export * from './lexer'
export * from './types'
+29 -19
View File
@@ -10,12 +10,12 @@ import {
EQ, EQ,
N, N,
} from '@bbob/plugin-helper'; } from '@bbob/plugin-helper';
import type { LexerOptions, LexerTokenizer } from "@bbob/types";
import { import {
Token, TYPE_ATTR_NAME, TYPE_ATTR_VALUE, TYPE_NEW_LINE, TYPE_SPACE, TYPE_TAG, TYPE_WORD, Token, TYPE_ATTR_NAME, TYPE_ATTR_VALUE, TYPE_NEW_LINE, TYPE_SPACE, TYPE_TAG, TYPE_WORD,
} from './Token'; } from './Token';
import { CharGrabber, createCharGrabber, trimChar, unquote } from './utils'; import { CharGrabber, createCharGrabber, trimChar, unquote } from './utils';
import type { LexerOptions, LexerTokenizer } from "./types";
// for cases <!-- --> // for cases <!-- -->
const EM = '!'; const EM = '!';
@@ -24,15 +24,24 @@ export function createTokenOfType(type: number, value: string, r = 0, cl = 0) {
return new Token(type, value, r, cl) return new Token(type, value, r, cl)
} }
const STATE_WORD = 0;
const STATE_TAG = 1;
const STATE_TAG_ATTRS = 2;
const TAG_STATE_NAME = 0;
const TAG_STATE_ATTR = 1;
const TAG_STATE_VALUE = 2;
const WHITESPACES = [SPACE, TAB];
const SPECIAL_CHARS = [EQ, SPACE, TAB];
const isWhiteSpace = (char: string) => (WHITESPACES.indexOf(char) >= 0);
const isEscapeChar = (char: string) => char === BACKSLASH;
const isSpecialChar = (char: string) => (SPECIAL_CHARS.indexOf(char) >= 0);
const isNewLine = (char: string) => char === N;
const unq = (val: string) => unquote(trimChar(val, QUOTEMARK));
export function createLexer(buffer: string, options: LexerOptions = {}): LexerTokenizer { export function createLexer(buffer: string, options: LexerOptions = {}): LexerTokenizer {
const STATE_WORD = 0;
const STATE_TAG = 1;
const STATE_TAG_ATTRS = 2;
const TAG_STATE_NAME = 0;
const TAG_STATE_ATTR = 1;
const TAG_STATE_VALUE = 2;
let row = 0; let row = 0;
let col = 0; let col = 0;
@@ -47,6 +56,7 @@ export function createLexer(buffer: string, options: LexerOptions = {}): LexerTo
const contextFreeTags = (options.contextFreeTags || []) const contextFreeTags = (options.contextFreeTags || [])
.filter(Boolean) .filter(Boolean)
.map((tag) => tag.toLowerCase()); .map((tag) => tag.toLowerCase());
const nestedMap = new Map<string, boolean>();
const onToken = options.onToken || (() => { const onToken = options.onToken || (() => {
}); });
@@ -54,22 +64,14 @@ export function createLexer(buffer: string, options: LexerOptions = {}): LexerTo
const NOT_CHAR_TOKENS = [ const NOT_CHAR_TOKENS = [
openTag, SPACE, TAB, N, openTag, SPACE, TAB, N,
]; ];
const WHITESPACES = [SPACE, TAB];
const SPECIAL_CHARS = [EQ, SPACE, TAB];
const isCharReserved = (char: string) => (RESERVED_CHARS.indexOf(char) >= 0); const isCharReserved = (char: string) => (RESERVED_CHARS.indexOf(char) >= 0);
const isNewLine = (char: string) => char === N;
const isWhiteSpace = (char: string) => (WHITESPACES.indexOf(char) >= 0);
const isCharToken = (char: string) => (NOT_CHAR_TOKENS.indexOf(char) === -1); const isCharToken = (char: string) => (NOT_CHAR_TOKENS.indexOf(char) === -1);
const isSpecialChar = (char: string) => (SPECIAL_CHARS.indexOf(char) >= 0);
const isEscapableChar = (char: string) => (char === openTag || char === closeTag || char === BACKSLASH); const isEscapableChar = (char: string) => (char === openTag || char === closeTag || char === BACKSLASH);
const isEscapeChar = (char: string) => char === BACKSLASH;
const onSkip = () => { const onSkip = () => {
col++; col++;
}; };
const unq = (val: string) => unquote(trimChar(val, QUOTEMARK));
const checkContextFreeMode = (name: string, isClosingTag?: boolean) => { const checkContextFreeMode = (name: string, isClosingTag?: boolean) => {
if (contextFreeTag !== '' && isClosingTag) { if (contextFreeTag !== '' && isClosingTag) {
contextFreeTag = ''; contextFreeTag = '';
@@ -339,8 +341,16 @@ export function createLexer(buffer: string, options: LexerOptions = {}): LexerTo
function isTokenNested(token: Token) { function isTokenNested(token: Token) {
const value = openTag + SLASH + token.getValue(); const value = openTag + SLASH + token.getValue();
// potential bottleneck
return buffer.indexOf(value) > -1; if (nestedMap.has(value)) {
return !!nestedMap.get(value);
} else {
const status = (buffer.indexOf(value) > -1)
nestedMap.set(value, status);
return status;
}
} }
return { return {
+3 -19
View File
@@ -1,3 +1,5 @@
import type { NodeContent, TagNodeTree, LexerTokenizer, ParseOptions } from "@bbob/types";
import { import {
CLOSE_BRAKET, CLOSE_BRAKET,
OPEN_BRAKET, OPEN_BRAKET,
@@ -7,26 +9,8 @@ import {
import { createLexer } from "./lexer"; import { createLexer } from "./lexer";
import type { NodeContent, TagNodeTree } from "@bbob/plugin-helper";
import type { LexerTokenizer, LexerOptions } from "./types";
import type { Token } from "./Token"; import type { Token } from "./Token";
type ParseError = {
tagName: string;
lineNumber: number;
columnNumber: number;
};
export interface ParseOptions {
createTokenizer?: (input: string, options?: LexerOptions) => LexerTokenizer;
openTag?: string;
closeTag?: string;
onlyAllowTags?: string[];
contextFreeTags?: string[];
enableEscapeTags?: boolean;
onError?: (error: ParseError) => void;
}
class NodeList<Value> { class NodeList<Value> {
private n: Value[]; private n: Value[];
@@ -201,7 +185,7 @@ function parse(input: string, opts: ParseOptions = {}) {
function handleTagStart(token: Token) { function handleTagStart(token: Token) {
flushTagNodes(); flushTagNodes();
const tagNode = TagNode.create(token.getValue()); const tagNode = TagNode.create(token.getValue(), {}, []);
const isNested = isTokenNested(token); const isNested = isTokenNested(token);
tagNodes.push(tagNode); tagNodes.push(tagNode);
-15
View File
@@ -1,15 +0,0 @@
import type Token from "./Token";
export interface LexerTokenizer {
tokenize: () => Token<string>[];
isTokenNested?: (token: Token<string>) => boolean;
}
export type LexerOptions = {
openTag?: string;
closeTag?: string;
onlyAllowTags?: string[];
enableEscapeTags?: boolean;
contextFreeTags?: string[];
onToken?: (token?: Token<string>) => void;
};
+9 -1
View File
@@ -35,6 +35,10 @@ export class CharGrabber {
} }
getCurr() { getCurr() {
if (typeof this.s[this.c.pos] === 'undefined') {
return ''
}
return this.s[this.c.pos] return this.s[this.c.pos]
} }
@@ -51,7 +55,11 @@ export class CharGrabber {
getPrev() { getPrev() {
const prevPos = this.c.pos - 1; const prevPos = this.c.pos - 1;
return typeof this.s[prevPos] !== 'undefined' ? this.s[prevPos] : null; if (typeof this.s[prevPos] === 'undefined') {
return null
}
return this.s[prevPos];
} }
isLast() { isLast() {
+3
View File
@@ -20,6 +20,9 @@
"browser": "dist/index.js", "browser": "dist/index.js",
"browserName": "BbobPluginHelper", "browserName": "BbobPluginHelper",
"types": "types/index.d.ts", "types": "types/index.d.ts",
"dependencies": {
"@bbob/types": "*"
},
"exports": { "exports": {
".": { ".": {
"types": "./types/index.d.ts", "types": "./types/index.d.ts",
+3 -3
View File
@@ -1,3 +1,5 @@
import type { NodeContent, TagNodeObject, TagNodeTree } from "@bbob/types";
import { OPEN_BRAKET, CLOSE_BRAKET, SLASH } from './char'; import { OPEN_BRAKET, CLOSE_BRAKET, SLASH } from './char';
import { import {
getUniqAttr, getUniqAttr,
@@ -8,8 +10,6 @@ import {
isTagNode, isTagNode,
} from './helpers'; } from './helpers';
import type { NodeContent, TagNodeObject, TagNodeTree } from "./types";
const getTagAttrs = <AttrValue>(tag: string, params: Record<string, AttrValue>) => { const getTagAttrs = <AttrValue>(tag: string, params: Record<string, AttrValue>) => {
const uniqAttr = getUniqAttr(params); const uniqAttr = getUniqAttr(params);
@@ -105,7 +105,7 @@ export class TagNode implements TagNodeObject {
return `${tagStart}${content}${this.toTagEnd({ openTag, closeTag })}`; return `${tagStart}${content}${this.toTagEnd({ openTag, closeTag })}`;
} }
static create(tag: string, attrs: Record<string, unknown> = {}, content: TagNodeTree = []) { static create(tag: string, attrs: Record<string, unknown> = {}, content: TagNodeTree = null) {
return new TagNode(tag, attrs, content) return new TagNode(tag, attrs, content)
} }
+9 -8
View File
@@ -1,6 +1,7 @@
import type { NodeContent, StringNode } from "@bbob/types";
import { N } from './char'; import { N } from './char';
import type { TagNode } from "./TagNode"; import type { TagNode } from "./TagNode";
import type { NodeContent, StringNode } from "./types";
function isTagNode(el: unknown): el is TagNode { function isTagNode(el: unknown): el is TagNode {
return typeof el === 'object' && el !== null && 'tag' in el; return typeof el === 'object' && el !== null && 'tag' in el;
@@ -15,10 +16,10 @@ function isEOL(el: string) {
return el === N return el === N
} }
function keysReduce<Res, Def extends Res, T extends Record<string, unknown>>(obj: T, reduce: (acc: Def, key: keyof T) => Res, def: Def): Res { function keysReduce<Res, Def extends Res, T extends Record<string, unknown>>(obj: T, reduce: (acc: Def, key: keyof T, obj: T) => Res, def: Def): Res {
const keys = Object.keys(obj) const keys = Object.keys(obj)
return keys.reduce((acc, key) => reduce(acc, key), def) return keys.reduce((acc, key) => reduce(acc, key, obj), def)
} }
function getNodeLength(node: NodeContent): number { function getNodeLength(node: NodeContent): number {
@@ -85,7 +86,7 @@ function attrValue<AttrValue = unknown>(name: string, value: AttrValue) {
* @example * @example
* attrsToString({ 'foo': true, 'bar': bar' }) => 'foo="true" bar="bar"' * attrsToString({ 'foo': true, 'bar': bar' }) => 'foo="true" bar="bar"'
*/ */
function attrsToString<AttrValue = unknown>(values: Record<string, AttrValue> | null) { function attrsToString<AttrValue = unknown>(values?: Record<string, AttrValue> | null) {
// To avoid some malformed attributes // To avoid some malformed attributes
if (values == null) { if (values == null) {
return ''; return '';
@@ -93,7 +94,7 @@ function attrsToString<AttrValue = unknown>(values: Record<string, AttrValue> |
return keysReduce( return keysReduce(
values, values,
(arr, key) => [...arr, attrValue(key, values[key])], (arr, key, obj) => [...arr, attrValue(key, obj[key])],
[''], [''],
).join(' '); ).join(' ');
} }
@@ -103,10 +104,10 @@ function attrsToString<AttrValue = unknown>(values: Record<string, AttrValue> |
* @example * @example
* getUniqAttr({ 'foo': true, 'bar': bar' }) => 'bar' * getUniqAttr({ 'foo': true, 'bar': bar' }) => 'bar'
*/ */
function getUniqAttr<Value>(attrs: Record<string, Value>) { function getUniqAttr<Value>(attrs?: Record<string, Value>) {
return keysReduce( return keysReduce(
attrs, attrs || {},
(res, key) => (attrs[key] === key ? attrs[key] : null), (res, key, obj) => (obj[key] === key ? obj[key] : null),
null, null,
) )
} }
-1
View File
@@ -1,4 +1,3 @@
export * from "./helpers"; export * from "./helpers";
export * from "./char"; export * from "./char";
export * from "./TagNode"; export * from "./TagNode";
export * from "./types";
@@ -44,6 +44,18 @@ describe('@bbob/plugin-helper/TagNode', () => {
expect(newTagNode.content).toEqual(tagNode.content); expect(newTagNode.content).toEqual(tagNode.content);
}); });
test('null content', () => {
const tagNode = TagNode.create('img');
expect(String(tagNode)).toBe('[img]');
});
test('array content', () => {
const tagNode = TagNode.create('img', {}, []);
expect(String(tagNode)).toBe('[img]');
});
describe('toString', () => { describe('toString', () => {
test('tag with content and params', () => { test('tag with content and params', () => {
const tagNode = TagNode.create('test', {test: 1}, ['Hello']); const tagNode = TagNode.create('test', {test: 1}, ['Hello']);
+2 -1
View File
@@ -9,7 +9,8 @@
], ],
"dependencies": { "dependencies": {
"@bbob/plugin-helper": "*", "@bbob/plugin-helper": "*",
"@bbob/preset": "*" "@bbob/preset": "*",
"@bbob/types": "*"
}, },
"devDependencies": { "devDependencies": {
"@bbob/core": "*", "@bbob/core": "*",
+85 -97
View File
@@ -4,18 +4,18 @@ import {
isStringNode, isStringNode,
isTagNode, isTagNode,
TagNode, TagNode,
TagNodeTree,
} from "@bbob/plugin-helper"; } from "@bbob/plugin-helper";
import type { NodeContent, TagNodeObject } from "@bbob/plugin-helper";
import type { PresetTagsDefinition } from "@bbob/preset"; import type { BBobPluginOptions, PresetTagsDefinition, NodeContent, TagNodeTree, TagNodeObject } from "@bbob/types";
import type { BbobPluginOptions } from "@bbob/core";
const isStartsWith = (node: string, type: string) => node[0] === type; const isStartsWith = (node: string, type: string) => node[0] === type;
const getStyleFromAttrs = (attrs: Record<string, unknown>) => { const styleAttrs = (attrs?: Record<string, unknown>) => {
return Object.keys(attrs) const values = attrs || {}
return Object.keys(values)
.reduce<string[]>((acc, key: "color" | "size") => { .reduce<string[]>((acc, key: "color" | "size") => {
const value = attrs[key]; const value = values[key];
if (typeof value === "string") { if (typeof value === "string") {
if (key === "color") { if (key === "color") {
@@ -32,53 +32,49 @@ const getStyleFromAttrs = (attrs: Record<string, unknown>) => {
.join(" "); .join(" ");
}; };
const asListItems = (content: TagNodeTree): NodeContent[] => { export const toListNodes = (content?: TagNodeTree) => {
let listIdx = 0; if (content && Array.isArray(content)) {
const listItems = [] as Array<NodeContent>; return content.reduce<NodeContent[]>((acc, node) => {
const listItem = acc[acc.length - 1];
const createItemNode = () => TagNode.create("li"); // *Entry
const ensureListItem = (val: NodeContent) => { if (isStringNode(node) && isStartsWith(String(node), "*")) {
listItems[listIdx] = listItems[listIdx] || val; // from '*Entry' to 'Entry'
}; const content = String(node).slice(1)
const addItem = (val: NodeContent) => {
const listItem = listItems[listIdx];
if (listItem && isTagNode(listItem) && Array.isArray(listItem.content)) { acc.push(TagNode.create("li", {}, [content]));
listItem.content = listItem.content.concat(val);
}
// else if (Array.isArray(listItem) && Array.isArray(listItems[listIdx])) {
// listItems[listIdx] = listItems[listIdx].concat(val);
// }
};
if (Array.isArray(content)) { return acc
content.forEach((el) => {
if (isStringNode(el) && isStartsWith(String(el), "*")) {
if (listItems[listIdx]) {
listIdx++;
}
ensureListItem(createItemNode());
addItem(String(el).substr(1));
} else if (isTagNode(el) && TagNode.isOf(el, "*")) {
if (listItems[listIdx]) {
listIdx++;
}
ensureListItem(createItemNode());
} else if (!isTagNode(listItems[listIdx])) {
listIdx++;
ensureListItem(el);
} else if (listItems[listIdx]) {
addItem(el);
} else {
ensureListItem(el);
} }
});
// { tag: '*', attrs: {}, content: [] }
if (isTagNode(node) && TagNode.isOf(node, "*")) {
acc.push(TagNode.create("li", {}, []));
return acc
}
if (!isTagNode(listItem)) {
acc.push(node);
return acc
}
if (listItem && isTagNode(listItem) && Array.isArray(listItem.content)) {
listItem.content = listItem.content.concat(node);
return acc
}
acc.push(node);
return acc
}, []);
} }
return listItems; return content
}; };
const renderUrl = (node: TagNodeObject, render: BbobPluginOptions["render"]) => const renderUrl = (node: TagNodeObject, render: BBobPluginOptions["render"]) =>
getUniqAttr(node.attrs) getUniqAttr(node.attrs)
? getUniqAttr(node.attrs) ? getUniqAttr(node.attrs)
: render(node.content || []); : render(node.content || []);
@@ -86,61 +82,53 @@ const renderUrl = (node: TagNodeObject, render: BbobPluginOptions["render"]) =>
const toNode = ( const toNode = (
tag: string, tag: string,
attrs: Record<string, unknown>, attrs: Record<string, unknown>,
content: TagNodeTree content?: TagNodeTree
) => TagNode.create(tag, attrs, content); ) => TagNode.create(tag, attrs, content);
const toStyle = (style: string) => ({ style }); const toStyle = (style: string) => ({ style });
const defaultTags: PresetTagsDefinition< export const defineStyleNode = (tag: string, style: string) => (node: TagNodeObject) => toNode(tag, toStyle(style), node.content)
| "b"
| "i"
| "u"
| "s"
| "url"
| "img"
| "quote"
| "code"
| "style"
| "list"
| "color"
> = {
b: (node) => toNode("span", toStyle("font-weight: bold;"), node.content),
i: (node) => toNode("span", toStyle("font-style: italic;"), node.content),
u: (node) =>
toNode("span", toStyle("text-decoration: underline;"), node.content),
s: (node) =>
toNode("span", toStyle("text-decoration: line-through;"), node.content),
url: (node, { render }) =>
toNode(
"a",
{
href: renderUrl(node, render),
},
node.content
),
img: (node, { render }) =>
toNode(
"img",
{
src: render(node.content),
},
null
),
quote: (node) => toNode("blockquote", {}, [toNode("p", {}, node.content)]),
code: (node) => toNode("pre", {}, node.content),
style: (node) =>
toNode("span", toStyle(getStyleFromAttrs(node.attrs)), node.content),
list: (node) => {
const type = getUniqAttr(node.attrs);
return toNode( export const defaultTags = (function createTags() {
type ? "ol" : "ul", const tags: PresetTagsDefinition<string> = {
type ? { type } : {}, b: defineStyleNode("span", "font-weight: bold;"),
asListItems(node.content) i: defineStyleNode("span", "font-style: italic;"),
); u: defineStyleNode("span", "text-decoration: underline;"),
}, s: defineStyleNode("span", "text-decoration: line-through;"),
color: (node) => url: (node, { render }) =>
toNode("span", toStyle(`color: ${getUniqAttr(node.attrs)};`), node.content), toNode(
}; "a",
{
href: renderUrl(node, render),
},
node.content
),
img: (node, { render }) =>
toNode(
"img",
{
src: render(node.content),
},
null
),
quote: (node) => toNode("blockquote", {}, [toNode("p", {}, node.content)]),
code: (node) => toNode("pre", {}, node.content),
style: (node) =>
toNode("span", toStyle(styleAttrs(node.attrs)), node.content),
list: (node) => {
const type = getUniqAttr(node.attrs);
return toNode(
type ? "ol" : "ul",
type ? { type } : {},
toListNodes(node.content)
);
},
color: (node) =>
toNode("span", toStyle(`color: ${getUniqAttr(node.attrs)};`), node.content),
}
return tags
})();
export default defaultTags; export default defaultTags;
+1 -4
View File
@@ -9,10 +9,7 @@
], ],
"dependencies": { "dependencies": {
"@bbob/preset-html5": "*", "@bbob/preset-html5": "*",
"@bbob/preset": "*" "@bbob/types": "*"
},
"devDependencies": {
"@bbob/core": "*"
}, },
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
+4 -2
View File
@@ -1,5 +1,5 @@
import presetHTML5 from '@bbob/preset-html5'; import presetHTML5 from '@bbob/preset-html5';
import type { PresetTagsDefinition } from '@bbob/preset'; import type { PresetTagsDefinition } from '@bbob/types';
const tagAttr = (style: Record<string, string>) => ({ const tagAttr = (style: Record<string, string>) => ({
attrs: { attrs: {
@@ -7,7 +7,7 @@ const tagAttr = (style: Record<string, string>) => ({
}, },
}); });
export default presetHTML5.extend((tags: PresetTagsDefinition<'b' | 'i' | 'u' | 's'>) => ({ const presetReact = presetHTML5.extend((tags: PresetTagsDefinition<'b' | 'i' | 'u' | 's'>) => ({
...tags, ...tags,
b: (...args) => ({ b: (...args) => ({
@@ -30,3 +30,5 @@ export default presetHTML5.extend((tags: PresetTagsDefinition<'b' | 'i' | 'u' |
...tagAttr({ textDecoration: 'line-through' }), ...tagAttr({ textDecoration: 'line-through' }),
}), }),
})); }));
export default presetReact;
+1 -4
View File
@@ -9,10 +9,7 @@
], ],
"dependencies": { "dependencies": {
"@bbob/preset-html5": "*", "@bbob/preset-html5": "*",
"@bbob/preset": "*" "@bbob/types": "*"
},
"devDependencies": {
"@bbob/core": "*"
}, },
"main": "lib/index.js", "main": "lib/index.js",
"module": "es/index.js", "module": "es/index.js",
+27 -20
View File
@@ -1,5 +1,6 @@
import presetHTML5 from '@bbob/preset-html5'; import presetHTML5 from '@bbob/preset-html5';
import type { PresetTagsDefinition } from '@bbob/preset';
import type { PresetTagsDefinition } from '@bbob/types';
export const tagAttr = (style: Record<string, string>) => ({ export const tagAttr = (style: Record<string, string>) => ({
attrs: { attrs: {
@@ -7,29 +8,35 @@ export const tagAttr = (style: Record<string, string>) => ({
}, },
}); });
export const createTags = (tags: PresetTagsDefinition<'b' | 'i' | 'u' | 's'>) => ({ export const createTags = (tags: PresetTagsDefinition<string>) => {
b: (...args) => ({ const newTags: PresetTagsDefinition<string> = {
...tags.b(...args), b: (...args) => ({
...tagAttr({ fontWeight: 'bold' }), ...tags.b?.(...args),
}), ...tagAttr({ fontWeight: 'bold' }),
}),
i: (...args) => ({ i: (...args) => ({
...tags.i(...args), ...tags.i?.(...args),
...tagAttr({ fontStyle: 'italic' }), ...tagAttr({ fontStyle: 'italic' }),
}), }),
u: (...args) => ({ u: (...args) => ({
...tags.u(...args), ...tags.u?.(...args),
...tagAttr({ textDecoration: 'underline' }), ...tagAttr({ textDecoration: 'underline' }),
}), }),
s: (...args) => ({ s: (...args) => ({
...tags.s(...args), ...tags.s?.(...args),
...tagAttr({ textDecoration: 'line-through' }), ...tagAttr({ textDecoration: 'line-through' }),
}), }),
} as PresetTagsDefinition); }
export default presetHTML5.extend((tags) => ({ return newTags
};
const presetVue = presetHTML5.extend((tags: PresetTagsDefinition<string>) => ({
...tags, ...tags,
...createTags(tags), ...createTags(tags),
})); }));
export default presetVue;
+14 -9
View File
@@ -1,23 +1,28 @@
import type { PresetTagFunction } from "@bbob/types";
import preset, { createTags, tagAttr } from '../src' import preset, { createTags, tagAttr } from '../src'
const tagFactory = (tag: string): PresetTagFunction => jest.fn((...args) => ({ tag }))
const createTag = (tag: string, style: Record<string, string>) => ({ tag, ...tagAttr(style)})
describe('@bbob/preset-vue', () => { describe('@bbob/preset-vue', () => {
test('is a function', () => { test('is a function', () => {
expect(preset).toBeInstanceOf(Function) expect(preset).toBeInstanceOf(Function)
}) })
test('createTags', () => { test('createTags', () => {
const defFn = jest.fn(() => ({}))
const defTags = { const defTags = {
b: defFn, b: tagFactory('b'),
i: defFn, i: tagFactory('i'),
u: defFn, u: tagFactory('u'),
s: defFn, s: tagFactory('s'),
} }
const tags = createTags(defTags) const tags = createTags(defTags)
const args = [{tag: 'test'}]
expect(tags.b()).toEqual(tagAttr({ fontWeight: 'bold' })) expect(tags.b?.({tag: 'b'}, ...args)).toEqual(createTag('b',{ fontWeight: 'bold' }))
expect(tags.i()).toEqual(tagAttr({ fontStyle: 'italic' })) expect(tags.i?.({tag: 'i'}, ...args)).toEqual(createTag('i',{ fontStyle: 'italic' }))
expect(tags.u()).toEqual(tagAttr({ textDecoration: 'underline' })) expect(tags.u?.({tag: 'u'}, ...args)).toEqual(createTag('u',{ textDecoration: 'underline' }))
expect(tags.s()).toEqual(tagAttr({ textDecoration: 'line-through' })) expect(tags.s?.({tag: 's'}, ...args)).toEqual(createTag('s',{ textDecoration: 'line-through' }))
}) })
}); });
+3
View File
@@ -16,6 +16,9 @@
], ],
"dependencies": { "dependencies": {
"@bbob/plugin-helper": "*", "@bbob/plugin-helper": "*",
"@bbob/types": "*"
},
"devDependencies": {
"@bbob/core": "*" "@bbob/core": "*"
}, },
"main": "lib/index.js", "main": "lib/index.js",
-1
View File
@@ -1,3 +1,2 @@
export { default } from "./preset"; export { default } from "./preset";
export * from "./preset"; export * from "./preset";
export * from "./types";
+26 -50
View File
@@ -1,87 +1,63 @@
import { isTagNode } from "@bbob/plugin-helper";
import type { import type {
BBobCoreTagNodeTree, BBobCoreTagNodeTree,
BbobPluginOptions, BBobPluginOptions,
BBobPluginFunction,
} from "@bbob/core";
import { isTagNode } from "@bbob/plugin-helper";
import type {
PresetExtendCallback, PresetExtendCallback,
PresetFactoryOptions, PresetFactory,
PresetOptions, PresetOptions,
PresetTagsDefinition, PresetTagsDefinition,
} from "./types"; ProcessorFunction
} from "@bbob/types";
function process<Name extends string = string>( export function process<Tags extends PresetTagsDefinition = PresetTagsDefinition, Options extends PresetOptions = PresetOptions>(
tags: PresetTagsDefinition<Name>, tags: Tags,
tree: BBobCoreTagNodeTree, tree: BBobCoreTagNodeTree,
core: BbobPluginOptions, core: BBobPluginOptions,
options: PresetFactoryOptions = {} options: Options
) { ) {
return tree.walk((node) => { return tree.walk((node) => {
if (isTagNode(node) && typeof tags[node.tag] === "function") { if (isTagNode(node)) {
const tag = node.tag; const tag = node.tag;
const tagCallback = tags[tag]; const tagCallback = tags[tag];
return tagCallback(node, core, options); if (typeof tagCallback === "function") {
return tagCallback(node, core, options);
}
} }
return node; return node;
}); });
} }
export type ProcessorFunction = typeof process;
export type ProcessorReturnType = ReturnType<ProcessorFunction>;
export interface PresetExecutor<
TagName extends string = string,
AttrValue = unknown
> extends BBobPluginFunction {
(tree: BBobCoreTagNodeTree, core?: BbobPluginOptions): ProcessorReturnType;
options: PresetOptions;
}
export interface PresetFactory<
TagName extends string = string,
AttrValue = unknown,
Names extends string = string
> {
(opts?: PresetOptions): PresetExecutor;
options?: PresetOptions;
extend: (
cb: PresetExtendCallback<Names>
) => PresetFactory<TagName, AttrValue, Names>;
}
/** /**
* Create a preset plugin for @bbob/core * Create a preset plugin for @bbob/core
*/ */
function createPreset<Names extends string = string>( function createPreset<Tags extends PresetTagsDefinition = PresetTagsDefinition, RootOptions extends PresetOptions = PresetOptions,>(
defTags: PresetTagsDefinition<Names>, defTags: Tags,
processor: ProcessorFunction = process processor: ProcessorFunction<Tags> = process
) { ) {
const presetFactory: PresetFactory = (opts: PresetOptions = {}) => { const presetFactory: PresetFactory<typeof defTags, RootOptions> = <Options extends RootOptions>(opts?: Options) => {
presetFactory.options = Object.assign(presetFactory.options || {}, opts); presetFactory.options = Object.assign(presetFactory.options || {}, opts);
function presetExecutor( function presetExecutor(
tree: BBobCoreTagNodeTree, tree: BBobCoreTagNodeTree,
core: BbobPluginOptions core: BBobPluginOptions
) { ) {
return processor(defTags, tree, core, presetFactory.options); return processor(defTags, tree, core, presetFactory.options || {});
} }
presetExecutor.options = presetFactory.options; presetExecutor.options = presetFactory.options as Options;
return presetExecutor; return presetExecutor;
}; };
presetFactory.extend = function presetExtend<ExtendNames extends string>( presetFactory.extend = function presetExtend<NewTags extends PresetTagsDefinition = PresetTagsDefinition>(
callback: PresetExtendCallback<Names & ExtendNames> callback: PresetExtendCallback<Tags, NewTags, RootOptions>
) { ) {
return createPreset( const newTags = callback(defTags, presetFactory.options)
callback(defTags, presetFactory.options || {}),
processor return createPreset<typeof newTags, RootOptions>(newTags, processor as unknown as ProcessorFunction<NewTags>);
);
}; };
return presetFactory; return presetFactory;
-15
View File
@@ -1,15 +0,0 @@
import type { TagNodeObject } from "@bbob/plugin-helper";
import type { BbobPluginOptions } from "@bbob/core";
export type PresetFactoryOptions = Record<string, unknown>
export type PresetTagFunction<Node extends object = TagNodeObject> = (
node: Node,
core: BbobPluginOptions,
options: PresetFactoryOptions
) => Node
export type PresetTagsDefinition<Name extends string = string> = Record<Name | string, PresetTagFunction>
export type PresetOptions = Record<string, unknown>
export type PresetExtendCallback<Names extends string> = (defTags: PresetTagsDefinition<Names>, options: PresetOptions) => PresetTagsDefinition<Names>
+9 -8
View File
@@ -2,21 +2,22 @@ import { createPreset, PresetTagsDefinition } from '../src';
import { BBobCoreOptions, createTree } from '@bbob/core' import { BBobCoreOptions, createTree } from '@bbob/core'
describe('@bbob/preset', () => { describe('@bbob/preset', () => {
const presetFactory = (defTags: PresetTagsDefinition) => { const presetFactory = <Tags extends PresetTagsDefinition = PresetTagsDefinition>(defTags: Tags) => {
const processor = jest.fn((tags, tree, core, options) => tags) const processor = jest.fn((tags, tree, core, options) => tags)
const preset = createPreset<Tags>(defTags, processor)
return { return {
preset: createPreset(defTags, processor), preset,
processor, processor,
core: {} as BBobCoreOptions core: {} as BBobCoreOptions
} }
} }
test('create', () => { test('create', () => {
const defTags = { test: () => 'test' } const defTags = { test: () => ({ tag: 'test' }) }
const options = { foo: 'bar' } const options = { foo: 'bar' }
const tree = createTree([], {}) const tree = createTree([], {})
const { preset, processor, core } = presetFactory(defTags); const { preset, processor } = presetFactory(defTags);
expect(preset.extend) expect(preset.extend)
.toBeDefined(); .toBeDefined();
@@ -28,8 +29,8 @@ describe('@bbob/preset', () => {
expect(processor.mock.calls.length).toBe(1); expect(processor.mock.calls.length).toBe(1);
}); });
test('extend', () => { test('extend', () => {
const defTags = { foo: () => 'foo' } const defTags = { foo: () => ({ tag: 'foo'}) }
const extendedTags = { bar: () => 'bar' } const extendedTags = { bar: () =>({tag: 'bar'}) }
const options = { foo: 'bar' } const options = { foo: 'bar' }
const tree = createTree([], {}) const tree = createTree([], {})
const { preset, processor, core } = presetFactory(defTags); const { preset, processor, core } = presetFactory(defTags);
@@ -47,8 +48,8 @@ describe('@bbob/preset', () => {
expect(processor.mock.calls.length).toBe(1); expect(processor.mock.calls.length).toBe(1);
}); });
test('pass options', () => { test('pass options', () => {
const { preset, processor } = presetFactory({ test: () => 'test' }); const { preset } = presetFactory({ test: () => ({tag: 'test'}) });
const newPreset = preset.extend((tags, options) => ({ bar: () => 'bar' })); const newPreset = preset.extend((tags, options) => ({ bar: () => ({tag: 'bar'}) }));
const instance = preset({ foo: 'bar' }); const instance = preset({ foo: 'bar' });
const instance2 = newPreset({ some: 'some' }); const instance2 = newPreset({ some: 'some' });
+2 -1
View File
@@ -11,7 +11,8 @@
"dependencies": { "dependencies": {
"@bbob/core": "*", "@bbob/core": "*",
"@bbob/html": "*", "@bbob/html": "*",
"@bbob/plugin-helper": "*" "@bbob/plugin-helper": "*",
"@bbob/types": "*"
}, },
"peerDependencies": { "peerDependencies": {
"react": "> 15.0" "react": "> 15.0"
+7 -2
View File
@@ -1,8 +1,13 @@
import React, { ReactNode } from 'react'; import React, { ReactNode } from 'react';
import type { BBobPlugins, BBobCoreOptions } from '@bbob/core'; import type { BBobPlugins, BBobCoreOptions } from '@bbob/types';
import { render } from './render'; import { render } from './render';
const content = (children: ReactNode, plugins?: BBobPlugins, options?: BBobCoreOptions) => React.Children.map(children, (child) => (typeof child === 'string' ? render(child, plugins, options) : child)); const content = (children: ReactNode, plugins?: BBobPlugins, options?: BBobCoreOptions) =>
React.Children.map(children,
(child) =>
(typeof child === 'string' ? render(child, plugins, options) : child)
);
export type BBobReactComponentProps = { export type BBobReactComponentProps = {
children: ReactNode children: ReactNode
+10 -8
View File
@@ -1,20 +1,22 @@
/* eslint-disable no-use-before-define */ /* eslint-disable no-use-before-define */
import React, { ReactNode } from "react"; import React, { ReactNode } from "react";
import { render as htmlrender } from "@bbob/html"; import { render as htmlrender } from "@bbob/html";
import core, { import core from "@bbob/core";
BBobCoreOptions,
BBobCoreTagNodeTree,
BBobPlugins,
} from "@bbob/core";
import { import {
isTagNode, isTagNode,
isStringNode, isStringNode,
isEOL, isEOL,
TagNode, TagNode,
TagNodeTree,
} from "@bbob/plugin-helper"; } from "@bbob/plugin-helper";
import type {
BBobCoreOptions,
BBobCoreTagNodeTree,
BBobPlugins,
TagNodeTree,
} from "@bbob/types";
const toAST = ( const toAST = (
source: string, source: string,
plugins?: BBobPlugins, plugins?: BBobPlugins,
@@ -45,8 +47,8 @@ function tagToReactElement(node: TagNode, index: number) {
); );
} }
function renderToReactNodes(nodes: BBobCoreTagNodeTree | TagNodeTree) { function renderToReactNodes(nodes?: BBobCoreTagNodeTree | TagNodeTree) {
if (Array.isArray(nodes) && nodes.length) { if (nodes && Array.isArray(nodes) && nodes.length) {
return nodes.reduce<ReactNode[]>((arr, node, index) => { return nodes.reduce<ReactNode[]>((arr, node, index) => {
if (isTagNode(node)) { if (isTagNode(node)) {
arr.push(tagToReactElement(node, index)); arr.push(tagToReactElement(node, index));
+4
View File
@@ -0,0 +1,4 @@
dist
es
lib
test
+8
View File
@@ -0,0 +1,8 @@
coverage
dist
lib
es
types
test/*.d.ts
test/*.map
tsconfig.tsbuildinfo
+7
View File
@@ -0,0 +1,7 @@
pnpm-lock.yaml
coverage
src
!dist
!lib
!es
*.test.js
+34
View File
@@ -0,0 +1,34 @@
{
"name": "@bbob/types",
"version": "3.0.2",
"description": "Shared Typescript types of @bbob",
"keywords": [
"bbcode",
"types"
],
"files": [
"dist",
"lib",
"src",
"es",
"types"
],
"types": "types/index.d.ts",
"module": "types/index.d.ts",
"homepage": "https://github.com/JiLiZART/bbob",
"author": "Nikolay Kostyurin <jilizart@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/JiLiZART/bbob/issues"
},
"repository": {
"type": "git",
"url": "git://github.com/JiLiZART/bbob.git"
},
"scripts": {
"types": "pkg-task"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/"
}
}
+54
View File
@@ -0,0 +1,54 @@
import { ParseOptions } from "./parser";
import { NodeContent, PartialNodeContent, TagNodeObject, TagNodeTree } from "./types";
export interface BBobCoreOptions<
Data = unknown | null,
Options extends ParseOptions = ParseOptions
> extends ParseOptions {
skipParse?: boolean;
parser?: (source: string, options?: Options) => TagNodeObject[];
render?: (ast?: TagNodeTree, options?: Options) => string;
data?: Data;
}
export type IterateCallback<Content> = (node: Content) => Content
export interface BBobPluginOptions<
Options extends ParseOptions = ParseOptions,
> {
parse: BBobCoreOptions["parser"];
render: (ast?: TagNodeTree, options?: Options) => string;
iterate: <Content, Iterable = ArrayLike<Content> | Content>(t: Iterable, cb: IterateCallback<Content>) => Iterable;
data: unknown | null;
}
export interface BBobPluginFunction {
(tree: BBobCoreTagNodeTree, options: BBobPluginOptions): BBobCoreTagNodeTree;
}
export interface BBobCore<
InputValue = string | TagNodeObject[],
Options extends BBobCoreOptions = BBobCoreOptions
> {
process(
input: InputValue,
opts?: Options
): {
readonly html: string;
tree: BBobCoreTagNodeTree;
raw: TagNodeObject[] | string;
messages: unknown[];
};
}
export interface BBobCoreTagNodeTree extends Array<NodeContent> {
messages: unknown[];
options: BBobCoreOptions;
walk: (cb: IterateCallback<NodeContent>) => BBobCoreTagNodeTree;
match: (
expression: PartialNodeContent | PartialNodeContent[],
cb: IterateCallback<NodeContent>
) => BBobCoreTagNodeTree;
}
export type BBobPlugins = BBobPluginFunction | BBobPluginFunction[];
+4
View File
@@ -0,0 +1,4 @@
export * from './types'
export * from './parser'
export * from './core'
export * from './preset'
+44
View File
@@ -0,0 +1,44 @@
import { TagNodeTree } from "./types";
export interface ParseError {
tagName: string;
lineNumber: number;
columnNumber: number;
}
export interface TagNode {
readonly tag: string
attrs?: Record<string, unknown>
content?: TagNodeTree
}
export interface Token<TokenValue = string> {
readonly t: number // type
readonly v: string // value
readonly l: number // line
readonly r: number // row
}
export interface LexerTokenizer {
tokenize: () => Token<string>[];
isTokenNested?: (token: Token<string>) => boolean;
}
export interface LexerOptions {
openTag?: string;
closeTag?: string;
onlyAllowTags?: string[];
enableEscapeTags?: boolean;
contextFreeTags?: string[];
onToken?: (token?: Token<string>) => void;
}
export interface ParseOptions {
createTokenizer?: (input: string, options?: LexerOptions) => LexerTokenizer;
openTag?: string;
closeTag?: string;
onlyAllowTags?: string[];
contextFreeTags?: string[];
enableEscapeTags?: boolean;
onError?: (error: ParseError) => void;
}
+46
View File
@@ -0,0 +1,46 @@
import { BBobCoreTagNodeTree, BBobPluginFunction, BBobPluginOptions } from "./core";
import { TagNodeObject } from "./types";
export type PartialRecord<K extends keyof any, T> = Partial<Record<K, T>>
export type PresetTagsDefinition<Key extends string = string> = Record<Key, PresetTagFunction>
export type PresetOptions = Record<string, unknown>
export type ProcessorFunction<Tags extends PresetTagsDefinition = PresetTagsDefinition, Options extends PresetOptions = PresetOptions> = (
tags: Tags,
tree: BBobCoreTagNodeTree,
core: BBobPluginOptions,
options: Options
) => BBobCoreTagNodeTree
// export type ProcessorReturnType = ReturnType<ProcessorFunction>;
export interface PresetTagFunction<Node extends TagNodeObject = TagNodeObject, Options extends PresetOptions = PresetOptions> {
(
node: Node,
data: BBobPluginOptions,
options: Options
): Node
}
export interface PresetExtendCallback<Tags, NewTags = Tags, Options extends PresetOptions = PresetOptions> {
(defTags: Tags, options?: Options): NewTags
}
export interface PresetExecutor<Options extends PresetOptions = PresetOptions> extends BBobPluginFunction {
(tree: BBobCoreTagNodeTree, core?: BBobPluginOptions): BBobCoreTagNodeTree;
options: Options;
}
export interface PresetFactory<
Tags extends PresetTagsDefinition = PresetTagsDefinition,
RootOptions extends PresetOptions = PresetOptions,
> {
<Options extends RootOptions>(opts?: Options): PresetExecutor<Options>;
options?: RootOptions;
extend: <NewTags extends PresetTagsDefinition = PresetTagsDefinition>(
cb: PresetExtendCallback<Tags, NewTags, RootOptions>
) => PresetFactory<NewTags, RootOptions>;
}
@@ -2,8 +2,8 @@ export type StringNode = string | number
export interface TagNodeObject { export interface TagNodeObject {
readonly tag: string readonly tag: string
attrs: Record<string, unknown> attrs?: Record<string, unknown>
content: TagNodeTree content?: TagNodeTree
} }
export type NodeContent = TagNodeObject | StringNode | null export type NodeContent = TagNodeObject | StringNode | null
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"outDir": "./types"
},
"include": [
"./src/**/*"
]
}
+2 -1
View File
@@ -11,7 +11,8 @@
"dependencies": { "dependencies": {
"@bbob/core": "*", "@bbob/core": "*",
"@bbob/html": "*", "@bbob/html": "*",
"@bbob/plugin-helper": "*" "@bbob/plugin-helper": "*",
"@bbob/types": "*"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "2.x" "vue": "2.x"
+1 -1
View File
@@ -1,7 +1,7 @@
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import type { BBobCoreOptions, BBobPlugins } from '@bbob/types';
import { render } from './render'; import { render } from './render';
import type { BBobCoreOptions, BBobPlugins } from '@bbob/core';
export type BBobVueComponentProps = { export type BBobVueComponentProps = {
container: string container: string
+17 -17
View File
@@ -1,36 +1,36 @@
/* eslint-disable no-use-before-define,import/prefer-default-export */ /* eslint-disable no-use-before-define,import/prefer-default-export */
import core, { BBobPlugins, BBobCoreOptions } from '@bbob/core'; import core from '@bbob/core';
import * as html from '@bbob/html'; import * as html from '@bbob/html';
import { isStringNode, isTagNode } from '@bbob/plugin-helper'; import { isStringNode, isTagNode } from '@bbob/plugin-helper';
import type { TagNodeTree, TagNode } from "@bbob/plugin-helper"; import type { TagNodeTree, TagNode, BBobPlugins, BBobCoreOptions } from '@bbob/types';
import type { CreateElement, VNodeChildrenArrayContents } from 'vue'; import type { CreateElement, VNodeChildrenArrayContents } from 'vue';
import type { StyleValue } from 'vue/types/jsx'; import type { StyleValue } from 'vue/types/jsx';
const toAST = (source: string, plugins: BBobPlugins = [], options: BBobCoreOptions = {}) => core(plugins) const toAST = (source: string, plugins: BBobPlugins = [], options: BBobCoreOptions = {}) => core(plugins)
.process(source, { .process(source, {
...options, ...options,
render: (input) => html.render(input, { stripTags: true }), render: (input) => html.render(input, { stripTags: true }),
}).tree; }).tree;
const isContentEmpty = (content: TagNodeTree) => (!content || Array.isArray(content) && content?.length === 0); const isContentEmpty = (content?: TagNodeTree) => (!content || Array.isArray(content) && content?.length === 0);
function tagToVueNode(createElement: CreateElement, node: TagNode, index: number) { function tagToVueNode(createElement: CreateElement, node: TagNode, index: number) {
const { class: className, style, ...domProps } = node.attrs || {}; const { class: className, style, ...domProps } = node.attrs || {};
return createElement( return createElement(
node.tag, node.tag,
{ {
key: index, key: index,
class: className, class: className,
style: style as StyleValue, style: style as StyleValue,
domProps, domProps,
}, },
isContentEmpty(node.content) ? null : renderToVueNodes(createElement, node.content), isContentEmpty(node.content) ? null : renderToVueNodes(createElement, node.content),
); );
} }
function renderToVueNodes(createElement: CreateElement, nodes: TagNodeTree) { function renderToVueNodes(createElement: CreateElement, nodes?: TagNodeTree) {
if (Array.isArray(nodes)) { if (Array.isArray(nodes)) {
return nodes.reduce((arr, node, index) => { return nodes.reduce((arr, node, index) => {
if (isTagNode(node)) { if (isTagNode(node)) {
@@ -38,7 +38,7 @@ function renderToVueNodes(createElement: CreateElement, nodes: TagNodeTree) {
} else if (isStringNode(node)) { } else if (isStringNode(node)) {
arr.push(String(node)); arr.push(String(node));
} }
return arr; return arr;
}, [] as VNodeChildrenArrayContents); }, [] as VNodeChildrenArrayContents);
} }
+2 -1
View File
@@ -11,7 +11,8 @@
"dependencies": { "dependencies": {
"@bbob/core": "*", "@bbob/core": "*",
"@bbob/html": "*", "@bbob/html": "*",
"@bbob/plugin-helper": "*" "@bbob/plugin-helper": "*",
"@bbob/types": "*"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "3.x" "vue": "3.x"
+1 -1
View File
@@ -1,7 +1,7 @@
import { defineComponent, h, VNode } from "vue"; import { defineComponent, h, VNode } from "vue";
import { render } from "./render"; import { render } from "./render";
import type { BBobPlugins, BBobCoreOptions } from "@bbob/core"; import type { BBobPlugins, BBobCoreOptions } from "@bbob/types";
type VueComponentProps = { type VueComponentProps = {
container: string; container: string;
+3 -2
View File
@@ -1,11 +1,12 @@
/* eslint-disable no-use-before-define,import/prefer-default-export */ /* eslint-disable no-use-before-define,import/prefer-default-export */
import core, { BBobCoreOptions, BBobPlugins } from "@bbob/core"; import core from "@bbob/core";
import * as html from "@bbob/html"; import * as html from "@bbob/html";
import { h, VNodeArrayChildren } from "vue"; import { h, VNodeArrayChildren } from "vue";
import type { BBobCoreOptions, BBobPlugins, TagNodeTree } from "@bbob/types";
import { import {
TagNode, TagNode,
TagNodeTree,
isStringNode, isStringNode,
isTagNode, isTagNode,
} from "@bbob/plugin-helper"; } from "@bbob/plugin-helper";
+70 -22
View File
@@ -160,6 +160,9 @@ importers:
benchmark: benchmark:
specifier: 2.1.4 specifier: 2.1.4
version: 2.1.4 version: 2.1.4
cpupro:
specifier: '*'
version: 0.5.0
picocolors: picocolors:
specifier: 1.0.0 specifier: 1.0.0
version: 1.0.0 version: 1.0.0
@@ -216,6 +219,9 @@ importers:
'@bbob/plugin-helper': '@bbob/plugin-helper':
specifier: '*' specifier: '*'
version: link:../bbob-plugin-helper version: link:../bbob-plugin-helper
'@bbob/types':
specifier: '*'
version: link:../bbob-types
packages/bbob-html: packages/bbob-html:
dependencies: dependencies:
@@ -225,23 +231,37 @@ importers:
'@bbob/plugin-helper': '@bbob/plugin-helper':
specifier: '*' specifier: '*'
version: link:../bbob-plugin-helper version: link:../bbob-plugin-helper
'@bbob/types':
specifier: '*'
version: link:../bbob-types
packages/bbob-parser: packages/bbob-parser:
dependencies: dependencies:
'@bbob/plugin-helper': '@bbob/plugin-helper':
specifier: '*' specifier: '*'
version: link:../bbob-plugin-helper version: link:../bbob-plugin-helper
'@bbob/types':
specifier: '*'
version: link:../bbob-types
packages/bbob-plugin-helper: {} packages/bbob-plugin-helper:
dependencies:
'@bbob/types':
specifier: '*'
version: link:../bbob-types
packages/bbob-preset: packages/bbob-preset:
dependencies: dependencies:
'@bbob/core':
specifier: '*'
version: link:../bbob-core
'@bbob/plugin-helper': '@bbob/plugin-helper':
specifier: '*' specifier: '*'
version: link:../bbob-plugin-helper version: link:../bbob-plugin-helper
'@bbob/types':
specifier: '*'
version: link:../bbob-types
devDependencies:
'@bbob/core':
specifier: '*'
version: link:../bbob-core
packages/bbob-preset-html5: packages/bbob-preset-html5:
dependencies: dependencies:
@@ -251,6 +271,9 @@ importers:
'@bbob/preset': '@bbob/preset':
specifier: '*' specifier: '*'
version: link:../bbob-preset version: link:../bbob-preset
'@bbob/types':
specifier: '*'
version: link:../bbob-types
devDependencies: devDependencies:
'@bbob/core': '@bbob/core':
specifier: '*' specifier: '*'
@@ -261,29 +284,21 @@ importers:
packages/bbob-preset-react: packages/bbob-preset-react:
dependencies: dependencies:
'@bbob/preset':
specifier: '*'
version: link:../bbob-preset
'@bbob/preset-html5': '@bbob/preset-html5':
specifier: '*' specifier: '*'
version: link:../bbob-preset-html5 version: link:../bbob-preset-html5
devDependencies: '@bbob/types':
'@bbob/core':
specifier: '*' specifier: '*'
version: link:../bbob-core version: link:../bbob-types
packages/bbob-preset-vue: packages/bbob-preset-vue:
dependencies: dependencies:
'@bbob/preset':
specifier: '*'
version: link:../bbob-preset
'@bbob/preset-html5': '@bbob/preset-html5':
specifier: '*' specifier: '*'
version: link:../bbob-preset-html5 version: link:../bbob-preset-html5
devDependencies: '@bbob/types':
'@bbob/core':
specifier: '*' specifier: '*'
version: link:../bbob-core version: link:../bbob-types
packages/bbob-react: packages/bbob-react:
dependencies: dependencies:
@@ -296,6 +311,9 @@ importers:
'@bbob/plugin-helper': '@bbob/plugin-helper':
specifier: '*' specifier: '*'
version: link:../bbob-plugin-helper version: link:../bbob-plugin-helper
'@bbob/types':
specifier: '*'
version: link:../bbob-types
devDependencies: devDependencies:
'@bbob/preset-react': '@bbob/preset-react':
specifier: ^3.0.2 specifier: ^3.0.2
@@ -316,6 +334,8 @@ importers:
specifier: 18.x specifier: 18.x
version: 18.2.0(react@18.2.0) version: 18.2.0(react@18.2.0)
packages/bbob-types: {}
packages/bbob-vue2: packages/bbob-vue2:
dependencies: dependencies:
'@bbob/core': '@bbob/core':
@@ -327,6 +347,9 @@ importers:
'@bbob/plugin-helper': '@bbob/plugin-helper':
specifier: '*' specifier: '*'
version: link:../bbob-plugin-helper version: link:../bbob-plugin-helper
'@bbob/types':
specifier: '*'
version: link:../bbob-types
devDependencies: devDependencies:
'@bbob/preset-vue': '@bbob/preset-vue':
specifier: '*' specifier: '*'
@@ -352,6 +375,9 @@ importers:
'@bbob/plugin-helper': '@bbob/plugin-helper':
specifier: '*' specifier: '*'
version: link:../bbob-plugin-helper version: link:../bbob-plugin-helper
'@bbob/types':
specifier: '*'
version: link:../bbob-types
devDependencies: devDependencies:
'@bbob/preset-vue': '@bbob/preset-vue':
specifier: '*' specifier: '*'
@@ -2191,7 +2217,6 @@ packages:
/@discoveryjs/json-ext@0.5.7: /@discoveryjs/json-ext@0.5.7:
resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
dev: true
/@endemolshinegroup/cosmiconfig-typescript-loader@3.0.2(cosmiconfig@7.1.0)(typescript@4.9.5): /@endemolshinegroup/cosmiconfig-typescript-loader@3.0.2(cosmiconfig@7.1.0)(typescript@4.9.5):
resolution: {integrity: sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==} resolution: {integrity: sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==}
@@ -5777,7 +5802,6 @@ packages:
/ansi-colors@4.1.3: /ansi-colors@4.1.3:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
engines: {node: '>=6'} engines: {node: '>=6'}
dev: true
/ansi-escapes@3.2.0: /ansi-escapes@3.2.0:
resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==} resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==}
@@ -6650,6 +6674,13 @@ packages:
resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==}
dev: true dev: true
/clap@3.1.1:
resolution: {integrity: sha512-vp42956Ax06WwaaheYEqEOgXZ3VKJxgccZ0gJL0HpyiupkIS9RVJFo5eDU1BPeQAOqz+cclndZg4DCqG1sJReQ==}
engines: {node: ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
dependencies:
ansi-colors: 4.1.3
dev: false
/clean-css@5.3.3: /clean-css@5.3.3:
resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==}
engines: {node: '>= 10.0'} engines: {node: '>= 10.0'}
@@ -7326,6 +7357,16 @@ packages:
typescript: 5.1.6 typescript: 5.1.6
dev: true dev: true
/cpupro@0.5.0:
resolution: {integrity: sha512-NEoLapQrQwrSrEBj5c9vxyUHSYiUv2aGOJ3EuO8g0j5zc7rxdNzzvT1PPY7G1H2guXBQrziHUvgdg8NkZYGMeA==}
hasBin: true
dependencies:
'@discoveryjs/json-ext': 0.5.7
clap: 3.1.1
open: 8.4.2
v8-profiler-next: 1.5.1
dev: false
/create-jest@29.7.0(@types/node@20.4.5): /create-jest@29.7.0(@types/node@20.4.5):
resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -7819,7 +7860,6 @@ packages:
/define-lazy-prop@2.0.0: /define-lazy-prop@2.0.0:
resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true
/define-properties@1.2.1: /define-properties@1.2.1:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
@@ -10173,7 +10213,6 @@ packages:
resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
hasBin: true hasBin: true
dev: true
/is-extendable@0.1.1: /is-extendable@0.1.1:
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
@@ -10419,7 +10458,6 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
is-docker: 2.2.1 is-docker: 2.2.1
dev: true
/isarray@1.0.0: /isarray@1.0.0:
resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
@@ -12081,6 +12119,10 @@ packages:
thenify-all: 1.6.0 thenify-all: 1.6.0
dev: true dev: true
/nan@2.19.0:
resolution: {integrity: sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==}
dev: false
/nanoid@3.3.6: /nanoid@3.3.6:
resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@@ -12653,7 +12695,6 @@ packages:
define-lazy-prop: 2.0.0 define-lazy-prop: 2.0.0
is-docker: 2.2.1 is-docker: 2.2.1
is-wsl: 2.2.0 is-wsl: 2.2.0
dev: true
/opener@1.5.2: /opener@1.5.2:
resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==}
@@ -15994,6 +16035,13 @@ packages:
resolution: {integrity: sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==} resolution: {integrity: sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==}
dev: true dev: true
/v8-profiler-next@1.5.1:
resolution: {integrity: sha512-7gnfJ3x7zN3gzmVs69OvJBNze5dLCIeY2Necy+IzomWmprSCRsBbCn5GfwAJHkWJxzoex3gyRexxvYGlgR93yg==}
requiresBuild: true
dependencies:
nan: 2.19.0
dev: false
/v8-to-istanbul@9.1.3: /v8-to-istanbul@9.1.3:
resolution: {integrity: sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==} resolution: {integrity: sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==}
engines: {node: '>=10.12.0'} engines: {node: '>=10.12.0'}
+1
View File
@@ -6,6 +6,7 @@
"dom.iterable", "dom.iterable",
"esnext" "esnext"
], ],
"baseUrl": ".",
"checkJs": false, "checkJs": false,
"skipLibCheck": true, "skipLibCheck": true,
"strict": true, "strict": true,