Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/JiLiZART/BBob
⚡️Blazing fast js bbcode parser, that transforms and parses bbcode to AST and transform it to HTML, React, Vue with plugin support in pure javascript, no dependencies
https://github.com/JiLiZART/BBob
ast bbcode bbcode-parser bbob html javascript parse parser posthtml react reactjs tree vue vuejs
Last synced: 9 days ago
JSON representation
⚡️Blazing fast js bbcode parser, that transforms and parses bbcode to AST and transform it to HTML, React, Vue with plugin support in pure javascript, no dependencies
- Host: GitHub
- URL: https://github.com/JiLiZART/BBob
- Owner: JiLiZART
- License: mit
- Created: 2018-06-04T21:13:58.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2024-10-25T08:41:46.000Z (17 days ago)
- Last Synced: 2024-10-28T08:14:20.184Z (14 days ago)
- Topics: ast, bbcode, bbcode-parser, bbob, html, javascript, parse, parser, posthtml, react, reactjs, tree, vue, vuejs
- Language: TypeScript
- Homepage: https://codepen.io/JiLiZART/full/vzMvpd
- Size: 4.76 MB
- Stars: 163
- Watchers: 7
- Forks: 19
- Open Issues: 24
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-blazingly-fast - BBob - ⚡️Blazing-fast js-bbcode-parser, bbcode js, that transforms and parses to AST with plugin support in pure javascript, no dependencies (JavaScript)
README
BBob is a tool to parse and transform [BBCode](https://en.wikipedia.org/wiki/BBCode)
written in pure javascript, no dependencies[![Tests](https://github.com/JiLiZART/BBob/actions/workflows/test.yml/badge.svg)](https://github.com/JiLiZART/BBob/actions/workflows/test.yml)
[![Benchmark](https://github.com/JiLiZART/BBob/actions/workflows/benchmark.yml/badge.svg)](https://github.com/JiLiZART/BBob/actions/workflows/benchmark.yml)
## Packages
| Package | Status | Size | Description |
|----------------------|------------------------------------------------------------|-----------------------------|---------------------------|
| @bbob/react | [![@bbob/react-status]][@bbob/react-package] | ![@bbob/react-size] | React renderer |
| @bbob/preset-react | [![@bbob/preset-react-status]][@bbob/preset-react-package] | ![@bbob/preset-react-size] | React default tags preset |
| @bbob/vue3 | [![@bbob/vue3-status]][@bbob/vue3-package] | ![@bbob/vue3-size] | Vue 3 renderer |
| @bbob/vue2 | [![@bbob/vue2-status]][@bbob/vue2-package] | ![@bbob/vue2-size] | Vue 2 renderer |
| @bbob/preset-vue | [![@bbob/preset-vue-status]][@bbob/preset-vue-package] | ![@bbob/preset-vue-size] | Vue default tags preset |
| @bbob/html | [![@bbob/html-status]][@bbob/html-package] | ![@bbob/html-size] | HTML renderer |
| @bbob/preset-html5 | [![@bbob/preset-html5-status]][@bbob/preset-html5-package] | ![@bbob/preset-html5-size] | HTML5 default tags preset |
| @bbob/core | [![@bbob/core-status]][@bbob/core-package] | ![@bbob/core-size] | Core package |[@bbob/core-status]: https://img.shields.io/npm/v/@bbob/core.svg
[@bbob/react-status]: https://img.shields.io/npm/v/@bbob/react.svg
[@bbob/preset-react-status]: https://img.shields.io/npm/v/@bbob/preset-react.svg[@bbob/vue3-status]: https://img.shields.io/npm/v/@bbob/vue3.svg
[@bbob/vue2-status]: https://img.shields.io/npm/v/@bbob/vue2.svg
[@bbob/preset-vue-status]: https://img.shields.io/npm/v/@bbob/preset-vue.svg[@bbob/html-status]: https://img.shields.io/npm/v/@bbob/html.svg
[@bbob/preset-html5-status]: https://img.shields.io/npm/v/@bbob/preset-html5.svg[@bbob/core-size]: https://badgen.net/bundlephobia/minzip/@bbob/core
[@bbob/react-size]: https://badgen.net/bundlephobia/minzip/@bbob/react
[@bbob/preset-react-size]: https://badgen.net/bundlephobia/minzip/@bbob/preset-react[@bbob/vue3-size]: https://badgen.net/bundlephobia/minzip/@bbob/vue3
[@bbob/vue2-size]: https://badgen.net/bundlephobia/minzip/@bbob/vue2
[@bbob/preset-vue-size]: https://badgen.net/bundlephobia/minzip/@bbob/preset-vue[@bbob/html-size]: https://badgen.net/bundlephobia/minzip/@bbob/html
[@bbob/preset-html5-size]: https://badgen.net/bundlephobia/minzip/@bbob/preset-html5[@bbob/core-package]: https://npmjs.com/package/@bbob/core
[@bbob/react-package]: https://npmjs.com/package/@bbob/react
[@bbob/preset-react-package]: https://npmjs.com/package/@bbob/preset-react[@bbob/vue3-package]: https://npmjs.com/package/@bbob/vue3
[@bbob/vue2-package]: https://npmjs.com/package/@bbob/vue2
[@bbob/preset-vue-package]: https://npmjs.com/package/@bbob/preset-vue[@bbob/html-package]: https://npmjs.com/package/@bbob/html
[@bbob/preset-html5-package]: https://npmjs.com/package/@bbob/preset-html5[DEMO Playground](https://codepen.io/JiLiZART/full/vzMvpd)
## Table of contents
* [Usage](#usage)
* [Basic usage](#basic-usage)
* [React usage](#react-usage)
* [Vue 2 usage](#vue2-usage)
* [Parse Options](#parse-options)
* [Presets](#presets)
* [Create your own preset](#create-preset)
* [HTML Preset](#html-preset)
* [React Preset](#react-preset)
* [React usage](#react)
* [Component](#react-component)
* [Render prop](#react-render)
* [PostHTML usage](#posthtml)
* [Create Plugin](#plugin)
* [Benchmarks](#benchmarks)
* [Donate](#donations)```shell
npm i @bbob/html @bbob/preset-html5
``````js
import bbobHTML from '@bbob/html'
import presetHTML5 from '@bbob/preset-html5'const processed = bbobHTML(`[i]Text[/i]`, presetHTML5())
console.log(processed); // Text
``````shell
npm i @bbob/react @bbob/preset-react
``````jsx
import React from 'react'
import BBCode from '@bbob/react';
import presetReact from '@bbob/preset-react';const plugins = [presetReact()];
export default () => (
[table]
[tr]
[td]table 1[/td]
[td]table 2[/td]
[/tr]
[tr]
[td]table 3[/td]
[td]table 4[/td]
[/tr]
[/table]
)
``````jsx
import { render } from '@bbob/react'export default () => render(`
[table]
[tr]
[td]table 1[/td]
[td]table 2[/td]
[/tr]
[tr]
[td]table 3[/td]
[td]table 4[/td]
[/tr]
[/table]
`)
``````shell
npm i @bbob/vue2 @bbob/preset-vue
``````js
import Vue from 'vue'
import VueBbob from '@bbob/vue2';Vue.use(VueBbob);
``````html
Generated HTML here
{{ bbcode }}
import Vue from 'vue'
import preset from '@bbob/preset-vue'
export default Vue.extend({
name: 'App',
data() {
return {
bbcode: 'Text [b]bolded[/b] and [i]Some Name[/i]',
plugins: [
preset()
],
}
}
})```
More examples available in examples folder
#### onlyAllowTags
Parse only allowed tags
```js
import bbobHTML from '@bbob/html'
import presetHTML5 from '@bbob/preset-html5'const processed = bbobHTML(`[i][b]Text[/b][/i]`, presetHTML5(), { onlyAllowTags: ['i'] })
console.log(processed); // [b]Text[/b]
```#### contextFreeTags
Enable context free mode that ignores parsing all tags inside given tags
```js
import bbobHTML from '@bbob/html'
import presetHTML5 from '@bbob/preset-html5'const processed = bbobHTML(`[b]Text[/b][code][b]Text[/b][/code]`, presetHTML5(), { contextFreeTags: ['code'] })
console.log(processed); // Text
[b]Text[/b]
```#### enableEscapeTags
Enable escape support for tags
```js
import bbobHTML from '@bbob/html'
import presetHTML5 from '@bbob/preset-html5'const processed = bbobHTML(`[b]Text[/b]'\\[b\\]Text\\[/b\\]'`, presetHTML5(), { enableEscapeTags: true })
console.log(processed); // Text[b]Text[/b]
```#### caseFreeTags
Allows to parse case insensitive tags like `[h1]some[/H1]` -> `
some
````js
import bbobHTML from '@bbob/html'
import presetHTML5 from '@bbob/preset-html5'const processed = bbobHTML(`[h1]some[/H1]`, presetHTML5(), { caseFreeTags: true })
console.log(processed); //
some
``````js
import bbobHTML from '@bbob/html'
import presetHTML5 from '@bbob/preset-html5'const processed = bbobHTML(`[b]Text[/b]'\\[b\\]Text\\[/b\\]'`, presetHTML5(), { enableEscapeTags: true })
console.log(processed); // Text[b]Text[/b]
```Its a way to transform parsed BBCode AST tree to another tree by rules in preset
```js
import { createPreset } from '@bbob/preset'export default createPreset({
quote: (node) => ({
tag: 'blockquote',
attrs: node.attrs,
content: [{
tag: 'p',
attrs: {},
content: node.content,
}],
}),
})
```Also you can use predefined preset for HTML
```js
import html5Preset from '@bbob/preset-html5/es'
import { render } from '@bbob/html/es'
import bbob from '@bbob/core'console.log(bbob(html5Preset()).process(`[quote]Text[/quote]`, { render }).html) //
Text
```Also you can use predefined preset for React
```js
import reactPreset from "@bbob/preset-react";
import reactRender from "@bbob/react/es/render";const preset = reactPreset.extend((tags, options) => ({
...tags,
quote: node => ({
tag: "blockquote",
content: node.content
})
}));const result = reactRender(`[quote]Text[/quote]`, reactPreset());
/*
It produces a VDOM Nodes equal to
React.createElement('blockquote', 'Text')
*/
document.getElementById("root").innerHTML = JSON.stringify(result, 4);
```[![Edit lp7q9yj0lq](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/lp7q9yj0lq)
Or you can use React Component
```js
import React from 'react'
import { render } from 'react-dom'import BBCode from '@bbob/react/es/Component'
import reactPreset from '@bbob/preset-react/es'const MyComponent = () => (
[quote]Text[/quote]
)render() //
Text
```
[![Edit 306pzr9k5p](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/306pzr9k5p)Or pass result as render prop
```js
import React from "react";
import { render } from 'react-dom'import reactRender from '@bbob/react/es/render'
import reactPreset from '@bbob/preset-react/es'const toReact = input => reactRender(input, reactPreset())
const text = toReact('[b]Super [i]easy[/i][/b] [u]to[/u] render')
const App = ({ renderProp }) => (
{text}
)render() // Super easy to render
```[![Edit x7w52lqmzz](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/jovial-cohen-bvo08)
For example lets parse all strings that similar to links like "https://some-site.com"
```js
import { createRoot } from "react-dom/client";import BBCode from "@bbob/react/es/Component";
import TagNode from "@bbob/plugin-helper/es/TagNode";
import { isStringNode } from "@bbob/plugin-helper/es";const URL_RE = new RegExp(
`([--:\\w?@%&+~#=]+\\/*\\.[a-z]{2,4}\\/{0,2})((?:[?&](?:\\w+)=(?:\\w+))+|[^^).|,][--:\\w?@%&+~#=()_]+)?`,
"g"
);const isValidUrl = (url) => URL_RE.test(url);
const linkParsePlugin = (tree) => {
return tree.walk((node) => {
if (isStringNode(node) && isValidUrl(node)) {
return TagNode.create(
"a",
{
href: node
},
`Url to: ${node}`
);
}return node;
});
};const rootElement = document.getElementById("root");
const root = createRoot(rootElement);root.render(
https://github.com/JiLiZART/BBob Other text without link
);
```[![Edit x7w52lqmzz](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/bbob-plugin-example-dmq1bh)
To test on your machine run
```shell
npm run build
node benchmark
```Tested on Node v20.11.1
| Package | Ops/sec |
|----------------------|----------------------|
| regex/parser | `6 ops/sec` |
| ya-bbcode | `11 ops/sec` |
| xbbcode/parser | `102 ops/sec` |
| @bbob/parser | `174 ops/sec` |[Checkout Benckmark job results](https://github.com/JiLiZART/BBob/actions/workflows/benchmark.yml)
You can support this projecti with donation in:
*Bitcoin:* `bc1qx34sx3zmfd5e2km607p8s8t30d4rt33d2l9pwt`
*USDT(TRC20):* `TT94uVjJho8n47xbdfNYz6vdebgmKFpxAT`
Also thanks to support
![Jetbrains IDEA](https://resources.jetbrains.com/storage/products/company/brand/logos/jb_square.svg)
Developed with <3 using JetBrains