mirror of
https://github.com/tenrok/BBob.git
synced 2026-06-17 19:21:20 +03:00
feat(vue3): add vue3 support (#179)
* feat(vue3): add vue3 package * fix(vue3): add package to lerna config
This commit is contained in:
committed by
GitHub
parent
05e3f6de87
commit
f6dfc7dcf4
+2
-1
@@ -15,7 +15,8 @@
|
|||||||
"packages/bbob-preset-react",
|
"packages/bbob-preset-react",
|
||||||
"packages/bbob-preset-vue",
|
"packages/bbob-preset-vue",
|
||||||
"packages/bbob-react",
|
"packages/bbob-react",
|
||||||
"packages/bbob-vue2"
|
"packages/bbob-vue2",
|
||||||
|
"packages/bbob-vue3"
|
||||||
],
|
],
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public",
|
"access": "public",
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
dist
|
||||||
|
es
|
||||||
|
lib
|
||||||
|
test
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
coverage
|
||||||
|
dist
|
||||||
|
lib
|
||||||
|
es
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package-lock.json
|
||||||
|
coverage
|
||||||
|
src
|
||||||
|
!dist
|
||||||
|
!lib
|
||||||
|
!es
|
||||||
|
*.test.js
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
# @bbob/vue3
|
||||||
|
|
||||||
|
[](https://packagephobia.now.sh/result?p=@bbob/vue3) [](https://snyk.io/test/github/JiLiZART/bbob?targetFile=packages%2Fbbob-vue3%2Fpackage.json)
|
||||||
|
|
||||||
|
> Converts @bbob/parser AST tree to Vue 3
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm i @bbob/vue3 @bbob/preset-vue
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
import VueBbob from '@bbob/vue3';
|
||||||
|
|
||||||
|
Vue.use(VueBbob);
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div class="vue3">
|
||||||
|
<h2>Generated vue3 here</h2>
|
||||||
|
<bbob-bbcode container="div" :plugins="plugins">{{ bbcode }}</bbob-bbcode>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Vue from 'vue'
|
||||||
|
import preset from '@bbob/preset-vue'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'App',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
bbcode: 'Text [b]bolded[/b] and [i]Some Name[/i]',
|
||||||
|
plugins: [
|
||||||
|
preset()
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
```
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require('../../jest.config');
|
||||||
Generated
+1459
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"name": "@bbob/vue3",
|
||||||
|
"version": "2.9.0",
|
||||||
|
"description": "A BBCode to Vue3 Renderer part of @bbob",
|
||||||
|
"keywords": [
|
||||||
|
"vue",
|
||||||
|
"bbcode",
|
||||||
|
"parser",
|
||||||
|
"bbob"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@bbob/core": "^2.9.0",
|
||||||
|
"@bbob/html": "^2.9.0",
|
||||||
|
"@bbob/plugin-helper": "^2.9.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "3.x"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@bbob/preset-vue": "^2.9.0",
|
||||||
|
"@testing-library/vue": "7.0.0",
|
||||||
|
"vue": "3.3.4"
|
||||||
|
},
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"module": "es/index.js",
|
||||||
|
"jsnext:main": "es/index.js",
|
||||||
|
"browser": "dist/index.js",
|
||||||
|
"browserName": "BbobVue",
|
||||||
|
"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": {
|
||||||
|
"build:commonjs": "../../scripts/pkg-task build-commonjs",
|
||||||
|
"build:es": "../../scripts/pkg-task build-es",
|
||||||
|
"build:umd": "../../scripts/pkg-task build-umd",
|
||||||
|
"build": "npm run build:commonjs && npm run build:es && npm run build:umd",
|
||||||
|
"test": "../../scripts/pkg-task test",
|
||||||
|
"cover": "../../scripts/pkg-task cover",
|
||||||
|
"lint": "../../scripts/pkg-task lint",
|
||||||
|
"size": "../../scripts/pkg-task size",
|
||||||
|
"bundlesize": "../../scripts/pkg-task bundlesize"
|
||||||
|
},
|
||||||
|
"size-limit": [
|
||||||
|
{
|
||||||
|
"path": "lib/index.js"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bundlesize": [
|
||||||
|
{
|
||||||
|
"path": "./dist/index.min.js",
|
||||||
|
"maxSize": "8 KB"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"registry": "https://registry.npmjs.org/"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"lib",
|
||||||
|
"src",
|
||||||
|
"es"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { defineComponent, h } from 'vue';
|
||||||
|
|
||||||
|
import { render } from './render';
|
||||||
|
|
||||||
|
const Component = defineComponent({
|
||||||
|
props: {
|
||||||
|
container: {
|
||||||
|
type: String,
|
||||||
|
default: 'span',
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
type: Array,
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
render(props) {
|
||||||
|
if (this.$slots.default) {
|
||||||
|
const source = this.$slots.default().reduce((acc, vnode) => acc + vnode.children, '');
|
||||||
|
|
||||||
|
return h(
|
||||||
|
props.container,
|
||||||
|
render(h, source, props.plugins, props.options),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Component;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import Component from './Component';
|
||||||
|
|
||||||
|
export { render } from './render';
|
||||||
|
export { Component };
|
||||||
|
|
||||||
|
function install(Vue) {
|
||||||
|
Vue.component('bbob-bbcode', Component);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default install;
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/* eslint-disable no-use-before-define,import/prefer-default-export */
|
||||||
|
import core from '@bbob/core';
|
||||||
|
import * as html from '@bbob/html';
|
||||||
|
|
||||||
|
import { isStringNode, isTagNode } from '@bbob/plugin-helper';
|
||||||
|
|
||||||
|
const toAST = (source, plugins = [], options = {}) => core(plugins)
|
||||||
|
.process(source, {
|
||||||
|
...options,
|
||||||
|
render: (input) => html.render(input, { stripTags: true }),
|
||||||
|
}).tree;
|
||||||
|
|
||||||
|
const isContentEmpty = (content) => (!content || content.length === 0);
|
||||||
|
|
||||||
|
function tagToVueNode(createElement, node, index) {
|
||||||
|
const { class: className, style, ...domProps } = node.attrs || {};
|
||||||
|
|
||||||
|
return createElement(
|
||||||
|
node.tag,
|
||||||
|
{
|
||||||
|
key: index,
|
||||||
|
class: className,
|
||||||
|
style,
|
||||||
|
...domProps,
|
||||||
|
},
|
||||||
|
isContentEmpty(node.content) ? null : renderToVueNodes(createElement, node.content),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderToVueNodes(createElement, nodes) {
|
||||||
|
return [].concat(nodes).reduce((arr, node, index) => {
|
||||||
|
if (isTagNode(node)) {
|
||||||
|
arr.push(tagToVueNode(createElement, node, index));
|
||||||
|
} else if (isStringNode(node)) {
|
||||||
|
arr.push(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts string to Vue 3 VNodes
|
||||||
|
* @param createElement {CreateElement}
|
||||||
|
* @param source {String}
|
||||||
|
* @param plugins {Array<Function>}
|
||||||
|
* @param options {Object}
|
||||||
|
* @returns {Array<VNode>}
|
||||||
|
*/
|
||||||
|
export function render(createElement, source, plugins, options) {
|
||||||
|
return renderToVueNodes(createElement, toAST(source, plugins, options));
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* @jest-environment jsdom
|
||||||
|
*/
|
||||||
|
|
||||||
|
import preset from '@bbob/preset-vue';
|
||||||
|
import { render } from '@testing-library/vue';
|
||||||
|
import Component from '../src/Component';
|
||||||
|
|
||||||
|
const renderBBCode = (input, options) => {
|
||||||
|
const { html } = render(Component, {
|
||||||
|
props: {
|
||||||
|
plugins: [preset()],
|
||||||
|
options,
|
||||||
|
},
|
||||||
|
slots: {
|
||||||
|
default: input
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return html()
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('@bbob/vue3', () => {
|
||||||
|
test('[b]bolded text[/b]', () => {
|
||||||
|
const html = renderBBCode('[b]bolded text[/b]');
|
||||||
|
|
||||||
|
expect(html).toBe('<span><span style="font-weight: bold;">bolded text</span></span>')
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[i]italicized text[/i]', () => {
|
||||||
|
const html = renderBBCode('[i]italicized text[/i]');
|
||||||
|
|
||||||
|
expect(html).toBe('<span><span style="font-style: italic;">italicized text</span></span>')
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[u]underlined text[/u]', () => {
|
||||||
|
const html = renderBBCode('[u]underlined text[/u]');
|
||||||
|
|
||||||
|
expect(html).toBe('<span><span style="text-decoration: underline;">underlined text</span></span>')
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[s]strikethrough text[/s]', () => {
|
||||||
|
const html = renderBBCode('[s]strikethrough text[/s]');
|
||||||
|
|
||||||
|
expect(html).toBe('<span><span style="text-decoration: line-through;">strikethrough text</span></span>')
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[url]https://en.wikipedia.org[/url]', () => {
|
||||||
|
const html = renderBBCode('[url]https://en.wikipedia.org[/url]');
|
||||||
|
|
||||||
|
expect(html).toBe('<span><a href="https://en.wikipedia.org">https://en.wikipedia.org</a></span>')
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[b]Testing[/b][hr]', () => {
|
||||||
|
const html = renderBBCode('[b]Testing[/b][hr]');
|
||||||
|
|
||||||
|
expect(html).toBe(`<span><span style="font-weight: bold;">Testing</span>
|
||||||
|
<hr></span>`)
|
||||||
|
});
|
||||||
|
|
||||||
|
test('render empty <slot></slot>', () => {
|
||||||
|
const { html } = render(Component, {
|
||||||
|
props: {
|
||||||
|
plugins: [preset()],
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(html()).toBe('')
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('options.onlyAllowTags', () => {
|
||||||
|
test('render "[Super Feature] and [i]super[/i]" when only [i] allowed', () => {
|
||||||
|
const html = renderBBCode('[Super Feature] and [i]super[/i]', { onlyAllowTags: ['i'] });
|
||||||
|
|
||||||
|
expect(html).toBe('<span>[Super Feature] and <span style="font-style: italic;">super</span></span>')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { render } from "../src";
|
||||||
|
|
||||||
|
describe('@bbob/vue3 render', () => {
|
||||||
|
|
||||||
|
const createElement = (tagName, props, children) => {
|
||||||
|
return { tagName, props, children }
|
||||||
|
}
|
||||||
|
|
||||||
|
test('render simple b tag', () => {
|
||||||
|
const html = render(createElement, '[b]bolded text[/b]');
|
||||||
|
|
||||||
|
expect(html).toStrictEqual([
|
||||||
|
{
|
||||||
|
"children": ["bolded", " ", "text"],
|
||||||
|
"props": { "class": undefined, "key": 0, "style": undefined },
|
||||||
|
"tagName": "b"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
})
|
||||||
|
test('render self closed b tag', () => {
|
||||||
|
const html = render(createElement, '[b][/b]');
|
||||||
|
|
||||||
|
expect(html).toStrictEqual([
|
||||||
|
{
|
||||||
|
"children": null,
|
||||||
|
"props": { "class": undefined, "key": 0, "style": undefined },
|
||||||
|
"tagName": "b"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
})
|
||||||
|
test('render simple text nodes', () => {
|
||||||
|
const html = render(createElement, 'some example words');
|
||||||
|
|
||||||
|
expect(html).toStrictEqual([
|
||||||
|
"some", " ", "example", " ", "words"
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user