2
0
mirror of https://github.com/tenrok/BBob.git synced 2026-06-17 19:21:20 +03:00

feat: react, vue3 and vanilla examples (#242)

* feat: react, vue3 and vanilla examples

* fix: vue3 example

* Create rare-worms-tease.md

* fix: vue3 types

* fix: vue3 ts checks

* fix: vue3 render types

* fix: vue3 component types
This commit is contained in:
Nikolay Kost
2024-07-12 03:35:51 +03:00
committed by GitHub
parent 1490bd6a8b
commit 16ad5216db
63 changed files with 2389 additions and 226 deletions
+5 -5
View File
@@ -53,12 +53,12 @@ const renderContent = (content: TagNodeTree, openTag: string, closeTag: string)
return null
}
export class TagNode implements TagNodeObject {
public readonly tag: string
export class TagNode<TagValue extends any = any> implements TagNodeObject {
public readonly tag: string | TagValue
public attrs: Record<string, unknown>
public content: TagNodeTree
constructor(tag: string, attrs: Record<string, unknown>, content: TagNodeTree) {
constructor(tag: string | TagValue, attrs: Record<string, unknown>, content: TagNodeTree) {
this.tag = tag;
this.attrs = attrs;
this.content = content
@@ -81,7 +81,7 @@ export class TagNode implements TagNodeObject {
}
toTagStart({ openTag = OPEN_BRAKET, closeTag = CLOSE_BRAKET } = {}) {
const tagAttrs = getTagAttrs(this.tag, this.attrs);
const tagAttrs = getTagAttrs(String(this.tag), this.attrs);
return `${openTag}${tagAttrs}${closeTag}`;
}
@@ -91,7 +91,7 @@ export class TagNode implements TagNodeObject {
}
toTagNode() {
return new TagNode(this.tag.toLowerCase(), this.attrs, this.content);
return new TagNode(String(this.tag).toLowerCase(), this.attrs, this.content);
}
toString({ openTag = OPEN_BRAKET, closeTag = CLOSE_BRAKET } = {}): string {
+8
View File
@@ -11,6 +11,14 @@
"@bbob/preset-html5": "*",
"@bbob/types": "*"
},
"peerDependencies": {
"react": "> 15.0"
},
"devDependencies": {
"react": "18.x",
"react-dom": "18.x",
"@types/react": "18.x"
},
"main": "lib/index.js",
"module": "es/index.js",
"jsnext:main": "es/index.js",
+2 -1
View File
@@ -1,4 +1,5 @@
import presetHTML5 from '@bbob/preset-html5';
import type { PresetTagsDefinition } from '@bbob/types';
const tagAttr = (style: Record<string, string>) => ({
@@ -7,7 +8,7 @@ const tagAttr = (style: Record<string, string>) => ({
},
});
const presetReact = presetHTML5.extend((tags: PresetTagsDefinition<'b' | 'i' | 'u' | 's'>) => ({
const presetReact = presetHTML5.extend<PresetTagsDefinition>((tags) => ({
...tags,
b: (...args) => ({
+10 -5
View File
@@ -5,14 +5,19 @@ 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)
(child) => {
if (typeof child === 'string') {
return render(child, plugins, options)
}
return child
}
);
export type BBobReactComponentProps = {
children: ReactNode
container: string
componentProps: Record<string, unknown>
container?: string
componentProps?: Record<string, unknown>
plugins?: BBobPlugins
options?: BBobCoreOptions
}
@@ -23,7 +28,7 @@ const Component = ({
children,
plugins = [],
options = {},
}: BBobReactComponentProps) => React.createElement(
}: BBobReactComponentProps): React.JSX.Element => React.createElement(
container,
componentProps,
content(children, plugins, options),
+4 -2
View File
@@ -24,7 +24,9 @@ const toAST = (
) =>
core(plugins).process(source, {
...options,
render: (input) => htmlrender(input, { stripTags: true }),
render: (input) => {
return htmlrender(input, { stripTags: true })
},
}).tree;
const isContentEmpty = (content: TagNodeTree) => {
@@ -65,7 +67,7 @@ function renderToReactNodes(nodes?: BBobCoreTagNodeTree | TagNodeTree) {
const prevArr = arr; // stupid eslint
const prevNode = lastIdx >= 0 ? prevArr[lastIdx] : null;
if (prevArr[lastIdx] && prevNode !== null && !isEOL(String(prevNode))) {
if (prevArr[lastIdx] && isStringNode(prevArr[lastIdx]) && prevNode !== null && !isEOL(String(prevNode))) {
prevArr[lastIdx] += String(node);
return prevArr;
+13
View File
@@ -0,0 +1,13 @@
export type StringNode = string | number
export interface TagNodeObject<TagValue extends any = any> {
readonly tag: TagValue
attrs?: Record<string, unknown>
content?: TagNodeTree<TagValue>
}
export type NodeContent<TagValue extends any = any> = TagNodeObject<TagValue> | StringNode | null
export type PartialNodeContent<TagValue extends any = any> = Partial<TagNodeObject<TagValue>> | StringNode | null
export type TagNodeTree<TagValue extends any = any> = NodeContent<TagValue> | NodeContent<TagValue>[] | null
+1 -1
View File
@@ -1,5 +1,5 @@
import { ParseOptions } from "./parser";
import { NodeContent, PartialNodeContent, TagNodeObject, TagNodeTree } from "./types";
import { NodeContent, PartialNodeContent, TagNodeObject, TagNodeTree } from "./common";
export interface BBobCoreOptions<
Data = unknown | null,
+1 -1
View File
@@ -1,4 +1,4 @@
export * from './types'
export * from './common'
export * from './parser'
export * from './core'
export * from './preset'
+1 -1
View File
@@ -1,4 +1,4 @@
import { TagNodeTree } from "./types";
import { TagNodeTree } from "./common";
export interface ParseError {
tagName: string;
+6 -3
View File
@@ -1,10 +1,13 @@
import { BBobCoreTagNodeTree, BBobPluginFunction, BBobPluginOptions } from "./core";
import { TagNodeObject } from "./types";
import { TagNodeObject } from "./common";
export type PartialRecord<K extends keyof any, T> = Partial<Record<K, T>>
export type PresetTagsDefinition<Key extends string = string> = Record<Key, PresetTagFunction>
export type PresetTagsDefinition<
Key extends string = string,
TagValue extends any = any
> = Record<Key, PresetTagFunction<TagNodeObject<TagValue>>>
export type PresetOptions = Record<string, unknown>
@@ -15,7 +18,7 @@ export type ProcessorFunction<Tags extends PresetTagsDefinition = PresetTagsDefi
options: Options
) => BBobCoreTagNodeTree
// export type ProcessorReturnType = ReturnType<ProcessorFunction>;
export type ProcessorReturnType = ReturnType<ProcessorFunction>;
export interface PresetTagFunction<Node extends TagNodeObject = TagNodeObject, Options extends PresetOptions = PresetOptions> {
(
-13
View File
@@ -1,13 +0,0 @@
export type StringNode = string | number
export interface TagNodeObject {
readonly tag: string
attrs?: Record<string, unknown>
content?: TagNodeTree
}
export type NodeContent = TagNodeObject | StringNode | null
export type PartialNodeContent = Partial<TagNodeObject> | StringNode | null
export type TagNodeTree = NodeContent | NodeContent[] | null
+1
View File
@@ -4,6 +4,7 @@
"description": "A BBCode to Vue2 Renderer part of @bbob",
"keywords": [
"vue",
"vue2",
"bbcode",
"parser",
"bbob"
+7 -6
View File
@@ -1,11 +1,12 @@
import type{ VueConstructor } from 'vue';
import type { VueConstructor } from 'vue';
import Component from './Component';
function install(vue: VueConstructor) {
vue.component("bbob-bbcode", Component);
vue.component("BBobBBCode", Component);
vue.component("BBCode", Component);
}
export { render } from './render';
export { Component };
function install(vue: VueConstructor) {
vue.component('bbob-bbcode', Component);
}
export default install;
+6 -5
View File
@@ -4,6 +4,7 @@
"description": "A BBCode to Vue3 Renderer part of @bbob",
"keywords": [
"vue",
"vue3",
"bbcode",
"parser",
"bbob"
@@ -20,12 +21,12 @@
"devDependencies": {
"@bbob/preset-vue": "*",
"@testing-library/vue": "7.0.0",
"@vue/compiler-sfc": "3.4.21",
"@vue/runtime-dom": "3.4.21",
"@vue/runtime-core": "3.4.21",
"@vue/compiler-dom": "3.4.21",
"@vue/compiler-sfc": "*",
"@vue/runtime-dom": "*",
"@vue/runtime-core": "*",
"@vue/compiler-dom": "*",
"@vue/test-utils": "2.4.5",
"vue": "3.4.21"
"vue": "*"
},
"main": "lib/index.js",
"module": "es/index.js",
+12 -9
View File
@@ -3,7 +3,7 @@ import { render } from "./render";
import type { BBobPlugins, BBobCoreOptions } from "@bbob/types";
type VueComponentProps = {
export type VueComponentProps = {
container: string;
componentProps: Record<string, unknown>;
plugins?: BBobPlugins;
@@ -26,18 +26,21 @@ const Component = defineComponent({
render(props: VueComponentProps) {
if (this.$slots.default) {
const source = this.$slots
.default()
.reduce((acc: VNode, vnode: VNode) => {
if (typeof acc === "string") {
const content = this.$slots.default()
const source = content.reduce((acc: string, vnode: VNode) => {
if (vnode && typeof vnode.children === "string") {
return acc + vnode.children;
}
return acc
}, "");
return h(
props.container,
render(h, source, props.plugins, props.options)
);
if (source) {
return h(
props.container,
render(h, String(source), props.plugins, props.options)
);
}
}
return null;
+10 -7
View File
@@ -1,11 +1,14 @@
import type { App } from "vue";
import type { Plugin } from "@vue/runtime-core";
import Component from "./Component";
const plugin = {
install(app) {
app.component("bbob-bbcode", Component);
app.component("BBobBBCode", Component);
app.component("BBCode", Component);
}
} as Plugin<any[]>;
export { render } from "./render";
export { Component };
function install(Vue: App) {
Vue.component("bbob-bbcode", Component);
}
export default install;
export default plugin;
-2
View File
@@ -7,8 +7,6 @@ import { render } from '@testing-library/vue';
import Component from '../src/Component';
console.log('Vue.v', Vue.version, Vue.createApp);
const renderBBCode = (input, options) => {
const { html } = render(Component, {
props: {