├── .github ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE.md ├── dist ├── index.d.ts ├── index.min.js └── renderers │ ├── checklist.d.ts │ ├── codeBox.d.ts │ ├── delimiter.d.ts │ ├── embed.d.ts │ ├── header.d.ts │ ├── image.d.ts │ ├── linkTool.d.ts │ ├── list.d.ts │ ├── paragraph.d.ts │ ├── personality.d.ts │ ├── quote.d.ts │ ├── table.d.ts │ ├── video.d.ts │ └── warning.d.ts ├── docs └── example │ ├── .gitignore │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ └── index.html │ ├── src │ ├── components │ │ ├── app │ │ │ ├── App.css │ │ │ ├── App.test.js │ │ │ ├── App.tsx │ │ │ └── testData.ts │ │ └── post │ │ │ ├── Post.css │ │ │ ├── Post.test.js │ │ │ └── Post.tsx │ ├── index.css │ └── index.tsx │ └── tsconfig.json ├── err.d.ts ├── index.tsx ├── package-lock.json ├── package.json ├── readme.md ├── renderers ├── checklist.tsx ├── codeBox.tsx ├── delimiter.tsx ├── embed.tsx ├── header.tsx ├── image.tsx ├── linkTool.tsx ├── list.tsx ├── paragraph.tsx ├── personality.tsx ├── quote.tsx ├── table.tsx ├── video.tsx └── warning.tsx ├── tsconfig.json └── webpack.config.js /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to EditorJS-React Renderer (ERR) 2 | 3 | The following is a set of guidelines for contributing to EditorJS-React Renderer. Please spend several minutes reading these guidelines before you create an issue or pull request. 4 | 5 | ## Code of Conduct 6 | We have adopted a Code of Conduct that we expect project participants to adhere to. Please read the full text so that you can understand what actions will and will not be tolerated. 7 | 8 | ## Open Development 9 | All work on EditorJS-React Renderer happens directly on GitHub. Both core team members and external contributors send pull requests which go through the same review process. 10 | 11 | ## Branch Organization 12 | According to our release schedule, we maintain two branches, master and feature. If you send a bugfix pull request, please do it against the master branch, if it's a feature pull request, please do it against the feature branch. 13 | 14 | ## Bugs 15 | We are using GitHub Issues for bug tracking. The best way to get your bug fixed is using our issue helper and provide reproduction steps with this template. 16 | 17 | Before you report a bug, please make sure you've searched exists issues, and read our FAQ. 18 | 19 | ## Proposing a Change 20 | If you intend to change the public API or introduce new feature, we also recommend you use our issue helper to create a feature request issue. 21 | 22 | If you want to help on new API, please follow our API Naming Rules. 23 | 24 | ## Your First Pull Request 25 | Working on your first Pull Request? You can learn how from this free video series: 26 | 27 | [How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github) 28 | 29 | 30 | ## Sending a Pull Request 31 | The core team is monitoring for pull requests. We will review your pull request and either merge it, request changes to it, or close it with an explanation. 32 | 33 | **Before submitting a pull request**, please make sure the following is done: 34 | 35 | 1) Fork the repository and create your branch from the correct branch. 36 | 37 | 2) Run npm install in the repository root. 38 | 39 | 3) If you've fixed a bug or added code that should be tested, add tests! 40 | 41 | 4) Ensure the test suite passes (npm run test). Tip: npm test -- --watch TestName is helpful in development. 42 | 43 | 5) Run npm test -- -u to update the jest snapshots and commit these changes as well (if there are any updates). 44 | 45 | 6) Make sure you follow our style guide (take a look at .eslint.js in the root directory). 46 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: dev-juju 4 | patreon: bomdisoft 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | ### 🤔 This is a ... 12 | 13 | - [ ] New feature 14 | - [ ] Bug fix 15 | - [ ] Site / document update 16 | - [ ] Component style update 17 | - [ ] Refactoring 18 | - [ ] Code style optimization 19 | - [ ] Test Case 20 | - [ ] Branch merge 21 | - [ ] Other (what?) 22 | 23 | ### 🔗 Related issue link 24 | 25 | 28 | 29 | ### 💡 Background and solution 30 | 31 | 36 | 37 | ### 📝 Changelog 38 | 39 | 42 | 43 | | Language | Changelog | 44 | | ---------- | --------- | 45 | | 🇺🇸 English | | 46 | 47 | ### ☑️ Self Check before Merge 48 | 49 | - [ ] Doc is updated/provided or not needed 50 | - [ ] Demo/Example is updated/provided or not needed 51 | - [ ] Changelog is provided or not needed 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | test.js 3 | *~ 4 | .env* 5 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at support@bomdisoft.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-juju/EditorJS-React-Renderer/153dded43ec61efccd7a0b2d9a0c38380dbaec49/LICENSE.md -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import HeaderOutput from './renderers/header'; 3 | import ParagraphOutput from './renderers/paragraph'; 4 | import ImageOutput from './renderers/image'; 5 | import VideoOutput from './renderers/video'; 6 | import EmbedOutput from './renderers/embed'; 7 | import ListOutput from './renderers/list'; 8 | import QuoteOutput from './renderers/quote'; 9 | import ChecklistOutput from './renderers/checklist'; 10 | import WarningOutput from './renderers/warning'; 11 | import TableOutput from './renderers/table'; 12 | import DelimiterOutput from './renderers/delimiter'; 13 | import CodeBoxOutput from './renderers/codeBox'; 14 | import LinkToolOutput from './renderers/linkTool'; 15 | import PersonalityOutput from './renderers/personality'; 16 | declare const Output: ({ data, style, classNames, config, renderers }: ErrOutputProps) => JSX.Element; 17 | export { HeaderOutput, ParagraphOutput, ImageOutput, VideoOutput, EmbedOutput, TableOutput, CodeBoxOutput, ListOutput, QuoteOutput, ChecklistOutput, WarningOutput, DelimiterOutput, LinkToolOutput, PersonalityOutput, Output as default }; 18 | -------------------------------------------------------------------------------- /dist/index.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("react"));else if("function"==typeof define&&define.amd)define(["React"],t);else{var n="object"==typeof exports?t(require("react")):t(e.React);for(var r in n)("object"==typeof exports?exports:e)[r]=n[r]}}("undefined"!=typeof self?self:this,(e=>{return t={990:function(e,t,n){"use strict";function r(e){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r(e)}var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.default=t.PersonalityOutput=t.LinkToolOutput=t.DelimiterOutput=t.WarningOutput=t.ChecklistOutput=t.QuoteOutput=t.ListOutput=t.CodeBoxOutput=t.TableOutput=t.EmbedOutput=t.VideoOutput=t.ImageOutput=t.ParagraphOutput=t.HeaderOutput=void 0;var i=o(n(639)),a=o(n(274));t.HeaderOutput=a.default;var l=o(n(59));t.ParagraphOutput=l.default;var s=o(n(725));t.ImageOutput=s.default;var c=o(n(83));t.VideoOutput=c.default;var u=o(n(933));t.EmbedOutput=u.default;var f=o(n(117));t.ListOutput=f.default;var d=o(n(324));t.QuoteOutput=d.default;var p=o(n(174));t.ChecklistOutput=p.default;var m=o(n(252));t.WarningOutput=m.default;var y=o(n(448));t.TableOutput=y.default;var h=o(n(92));t.DelimiterOutput=h.default;var g=o(n(439));t.CodeBoxOutput=g.default;var b=o(n(658));t.LinkToolOutput=b.default;var v=o(n(801));t.PersonalityOutput=v.default,t.default=function(e){var t=e.data,n=e.style,o=e.classNames,a=e.config,l=e.renderers;return t&&"object"===r(t)?(n&&"object"===r(n)||(n={}),o&&"object"===r(o)||(o={}),a&&"object"===r(a)||(a={}),l&&"object"===r(l)||(l={}),i.default.createElement(i.default.Fragment,null,t.blocks.map((function(e,t){var r=e.type.toLowerCase(),s=l[r]||x(r);return s?i.default.createElement(s,{key:t,data:e.data,style:n[r]||{},config:a[r]||{},classNames:o[r]||{}}):i.default.createElement(i.default.Fragment,null)})))):i.default.createElement(i.default.Fragment,null)};var x=function(e){switch(e){case"codebox":return g.default;case"header":return a.default;case"paragraph":return l.default;case"image":return s.default;case"video":return c.default;case"embed":return u.default;case"table":return y.default;case"list":return f.default;case"checklist":return p.default;case"quote":return d.default;case"warning":return m.default;case"linktool":return b.default;case"personality":return v.default;case"delimiter":return h.default;default:return null}}},905:(e,t)=>{"use strict";var n;Object.defineProperty(t,"__esModule",{value:!0}),t.Doctype=t.CDATA=t.Tag=t.Style=t.Script=t.Comment=t.Directive=t.Text=t.Root=t.isTag=t.ElementType=void 0,function(e){e.Root="root",e.Text="text",e.Directive="directive",e.Comment="comment",e.Script="script",e.Style="style",e.Tag="tag",e.CDATA="cdata",e.Doctype="doctype"}(n=t.ElementType||(t.ElementType={})),t.isTag=function(e){return e.type===n.Tag||e.type===n.Script||e.type===n.Style},t.Root=n.Root,t.Text=n.Text,t.Directive=n.Directive,t.Comment=n.Comment,t.Script=n.Script,t.Style=n.Style,t.Tag=n.Tag,t.CDATA=n.CDATA,t.Doctype=n.Doctype},853:function(e,t,n){"use strict";function r(e){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r(e)}var o=this&&this.__createBinding||(Object.create?function(e,t,n,r){void 0===r&&(r=n);var o=Object.getOwnPropertyDescriptor(t,n);o&&!("get"in o?!t.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return t[n]}}),Object.defineProperty(e,r,o)}:function(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}),i=this&&this.__exportStar||function(e,t){for(var n in e)"default"===n||Object.prototype.hasOwnProperty.call(t,n)||o(t,e,n)};Object.defineProperty(t,"__esModule",{value:!0}),t.DomHandler=void 0;var a=n(905),l=n(497);i(n(497),t);var s={withStartIndices:!1,withEndIndices:!1,xmlMode:!1},c=function(){function e(e,t,n){this.dom=[],this.root=new l.Document(this.dom),this.done=!1,this.tagStack=[this.root],this.lastNode=null,this.parser=null,"function"==typeof t&&(n=t,t=s),"object"===r(e)&&(t=e,e=void 0),this.callback=null!=e?e:null,this.options=null!=t?t:s,this.elementCB=null!=n?n:null}return e.prototype.onparserinit=function(e){this.parser=e},e.prototype.onreset=function(){this.dom=[],this.root=new l.Document(this.dom),this.done=!1,this.tagStack=[this.root],this.lastNode=null,this.parser=null},e.prototype.onend=function(){this.done||(this.done=!0,this.parser=null,this.handleCallback(null))},e.prototype.onerror=function(e){this.handleCallback(e)},e.prototype.onclosetag=function(){this.lastNode=null;var e=this.tagStack.pop();this.options.withEndIndices&&(e.endIndex=this.parser.endIndex),this.elementCB&&this.elementCB(e)},e.prototype.onopentag=function(e,t){var n=this.options.xmlMode?a.ElementType.Tag:void 0,r=new l.Element(e,t,void 0,n);this.addNode(r),this.tagStack.push(r)},e.prototype.ontext=function(e){var t=this.lastNode;if(t&&t.type===a.ElementType.Text)t.data+=e,this.options.withEndIndices&&(t.endIndex=this.parser.endIndex);else{var n=new l.Text(e);this.addNode(n),this.lastNode=n}},e.prototype.oncomment=function(e){if(this.lastNode&&this.lastNode.type===a.ElementType.Comment)this.lastNode.data+=e;else{var t=new l.Comment(e);this.addNode(t),this.lastNode=t}},e.prototype.oncommentend=function(){this.lastNode=null},e.prototype.oncdatastart=function(){var e=new l.Text(""),t=new l.CDATA([e]);this.addNode(t),e.parent=t,this.lastNode=e},e.prototype.oncdataend=function(){this.lastNode=null},e.prototype.onprocessinginstruction=function(e,t){var n=new l.ProcessingInstruction(e,t);this.addNode(n)},e.prototype.handleCallback=function(e){if("function"==typeof this.callback)this.callback(e,this.dom);else if(e)throw e},e.prototype.addNode=function(e){var t=this.tagStack[this.tagStack.length-1],n=t.children[t.children.length-1];this.options.withStartIndices&&(e.startIndex=this.parser.startIndex),this.options.withEndIndices&&(e.endIndex=this.parser.endIndex),t.children.push(e),n&&(e.prev=n,n.next=e),e.parent=t,this.lastNode=null},e}();t.DomHandler=c,t.default=c},497:function(e,t,n){"use strict";var r,o=this&&this.__extends||(r=function(e,t){return r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])},r(e,t)},function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),i=this&&this.__assign||function(){return i=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0?this.children[this.children.length-1]:null},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"childNodes",{get:function(){return this.children},set:function(e){this.children=e},enumerable:!1,configurable:!0}),t}(l);t.NodeWithChildren=d;var p=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.type=a.ElementType.CDATA,t}return o(t,e),Object.defineProperty(t.prototype,"nodeType",{get:function(){return 4},enumerable:!1,configurable:!0}),t}(d);t.CDATA=p;var m=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.type=a.ElementType.Root,t}return o(t,e),Object.defineProperty(t.prototype,"nodeType",{get:function(){return 9},enumerable:!1,configurable:!0}),t}(d);t.Document=m;var y=function(e){function t(t,n,r,o){void 0===r&&(r=[]),void 0===o&&(o="script"===t?a.ElementType.Script:"style"===t?a.ElementType.Style:a.ElementType.Tag);var i=e.call(this,r)||this;return i.name=t,i.attribs=n,i.type=o,i}return o(t,e),Object.defineProperty(t.prototype,"nodeType",{get:function(){return 1},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"tagName",{get:function(){return this.name},set:function(e){this.name=e},enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,"attributes",{get:function(){var e=this;return Object.keys(this.attribs).map((function(t){var n,r;return{name:t,value:e.attribs[t],namespace:null===(n=e["x-attribsNamespace"])||void 0===n?void 0:n[t],prefix:null===(r=e["x-attribsPrefix"])||void 0===r?void 0:r[t]}}))},enumerable:!1,configurable:!0}),t}(d);function h(e){return(0,a.isTag)(e)}function g(e){return e.type===a.ElementType.CDATA}function b(e){return e.type===a.ElementType.Text}function v(e){return e.type===a.ElementType.Comment}function x(e){return e.type===a.ElementType.Directive}function S(e){return e.type===a.ElementType.Root}function w(e,t){var n;if(void 0===t&&(t=!1),b(e))n=new c(e.data);else if(v(e))n=new u(e.data);else if(h(e)){var r=t?E(e.children):[],o=new y(e.name,i({},e.attribs),r);r.forEach((function(e){return e.parent=o})),null!=e.namespace&&(o.namespace=e.namespace),e["x-attribsNamespace"]&&(o["x-attribsNamespace"]=i({},e["x-attribsNamespace"])),e["x-attribsPrefix"]&&(o["x-attribsPrefix"]=i({},e["x-attribsPrefix"])),n=o}else if(g(e)){r=t?E(e.children):[];var a=new p(r);r.forEach((function(e){return e.parent=a})),n=a}else if(S(e)){r=t?E(e.children):[];var l=new m(r);r.forEach((function(e){return e.parent=l})),e["x-mode"]&&(l["x-mode"]=e["x-mode"]),n=l}else{if(!x(e))throw new Error("Not implemented yet: ".concat(e.type));var s=new f(e.name,e.data);null!=e["x-name"]&&(s["x-name"]=e["x-name"],s["x-publicId"]=e["x-publicId"],s["x-systemId"]=e["x-systemId"]),n=s}return n.startIndex=e.startIndex,n.endIndex=e.endIndex,null!=e.sourceCodeLocation&&(n.sourceCodeLocation=e.sourceCodeLocation),n}function E(e){for(var t=e.map((function(e){return w(e,!0)})),n=1;n{t.CASE_SENSITIVE_TAG_NAMES=["animateMotion","animateTransform","clipPath","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussainBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","foreignObject","linearGradient","radialGradient","textPath"]},253:e=>{function t(e){return t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t(e)}var n="html",r="head",o="body",i=/<([a-zA-Z]+[0-9]?)/,a=//i,l=//i,s=function(){throw new Error("This browser does not support `document.implementation.createHTMLDocument`")},c=function(){throw new Error("This browser does not support `DOMParser.prototype.parseFromString`")},u="object"===("undefined"==typeof window?"undefined":t(window))&&window.DOMParser;if("function"==typeof u){var f=new u;s=c=function(e,t){return t&&(e="<"+t+">"+e+""),f.parseFromString(e,"text/html")}}if("object"===("undefined"==typeof document?"undefined":t(document))&&document.implementation){var d=document.implementation.createHTMLDocument();s=function(e,t){return t?(d.documentElement.querySelector(t).innerHTML=e,d):(d.documentElement.innerHTML=e,d)}}var p,m="object"===("undefined"==typeof document?"undefined":t(document))?document.createElement("template"):{};m.content&&(p=function(e){return m.innerHTML=e,m.content.childNodes}),e.exports=function(e){var t,u,f,d,m=e.match(i);switch(m&&m[1]&&(t=m[1].toLowerCase()),t){case n:return u=c(e),a.test(e)||(f=u.querySelector(r))&&f.parentNode.removeChild(f),l.test(e)||(f=u.querySelector(o))&&f.parentNode.removeChild(f),u.querySelectorAll(n);case r:case o:return d=(u=s(e)).querySelectorAll(t),l.test(e)&&a.test(e)?d[0].parentNode.childNodes:d;default:return p?p(e):(f=s(e,o).querySelector(o)).childNodes}}},995:(e,t,n)=>{var r=n(253),o=n(755).formatDOM,i=/<(![a-zA-Z\s]+)>/;e.exports=function(e){if("string"!=typeof e)throw new TypeError("First argument must be a string");if(""===e)return[];var t,n=e.match(i);return n&&n[1]&&(t=n[1]),o(r(e),null,t)}},755:(e,t,n)=>{for(var r,o=n(853),i=n(692).CASE_SENSITIVE_TAG_NAMES,a=o.Comment,l=o.Element,s=o.ProcessingInstruction,c=o.Text,u={},f=0,d=i.length;f{var r=n(495),o=n(578),i=n(995);i="function"==typeof i.default?i.default:i;var a={lowerCaseAttributeNames:!1};function l(e,t){if("string"!=typeof e)throw new TypeError("First argument must be a string");return""===e?[]:r(i(e,(t=t||{}).htmlparser2||a),t)}l.domToReact=r,l.htmlToDOM=i,l.attributesToProps=o,l.Element=n(853).Element,e.exports=l,e.exports.default=l},578:(e,t,n)=>{var r=n(583),o=n(370);function i(e){return r.possibleStandardNames[e]}e.exports=function(e){var t,n,a,l,s,c={},u=(e=e||{}).type&&{reset:!0,submit:!0}[e.type];for(t in e)if(a=e[t],r.isCustomAttribute(t))c[t]=a;else if(l=i(n=t.toLowerCase()))switch(s=r.getPropertyInfo(l),"checked"!==l&&"value"!==l||u||(l=i("default"+n)),c[l]=a,s&&s.type){case r.BOOLEAN:c[l]=!0;break;case r.OVERLOADED_BOOLEAN:""===a&&(c[l]=!0)}else o.PRESERVE_CUSTOM_ATTRIBUTES&&(c[t]=a);return o.setStyleProp(e.style,c),c}},495:(e,t,n)=>{var r=n(639),o=n(578),i=n(370),a=i.setStyleProp,l=i.canTextBeChildOfNode;function s(e){return i.PRESERVE_CUSTOM_ATTRIBUTES&&"tag"===e.type&&i.isCustomComponent(e.name,e.attribs)}e.exports=function e(t,n){for(var i,c,u,f,d,p=(n=n||{}).library||r,m=p.cloneElement,y=p.createElement,h=p.isValidElement,g=[],b="function"==typeof n.replace,v=n.trim,x=0,S=t.length;x1&&(u=m(u,{key:u.key||x})),g.push(u);else if("text"!==i.type){switch(f=i.attribs,s(i)?a(f.style,f):f&&(f=o(f)),d=null,i.type){case"script":case"style":i.children[0]&&(f.dangerouslySetInnerHTML={__html:i.children[0].data});break;case"tag":"textarea"===i.name&&i.children[0]?f.defaultValue=i.children[0].data:i.children&&i.children.length&&(d=e(i.children,n));break;default:continue}S>1&&(f.key=x),g.push(y(i.name,f,d))}else{if((c=!i.data.trim().length)&&i.parent&&!l(i.parent))continue;if(v&&c)continue;g.push(i.data)}return 1===g.length?g[0]:g}},370:(e,t,n)=>{function r(e){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r(e)}var o=n(639),i=n(405).default,a={reactCompat:!0},l=o.version.split(".")[0]>=16,s=new Set(["tr","tbody","thead","tfoot","colgroup","table","head","html","frameset"]);e.exports={PRESERVE_CUSTOM_ATTRIBUTES:l,invertObject:function(e,t){if(!e||"object"!==r(e))throw new TypeError("First argument must be an object");var n,o,i="function"==typeof t,a={},l={};for(n in e)o=e[n],i&&(a=t(n,o))&&2===a.length?l[a[0]]=a[1]:"string"==typeof o&&(l[o]=n);return l},isCustomComponent:function(e,t){if(-1===e.indexOf("-"))return t&&"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}},setStyleProp:function(e,t){if(null!=e)try{t.style=i(e,a)}catch(e){t.style={}}},canTextBeChildOfNode:function(e){return!s.has(e.name)},elementsWithNoTextChildren:s}},242:e=>{var t=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//g,n=/\n/g,r=/^\s*/,o=/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/,i=/^:\s*/,a=/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/,l=/^[;\s]*/,s=/^\s+|\s+$/g,c="";function u(e){return e?e.replace(s,c):c}e.exports=function(e,s){if("string"!=typeof e)throw new TypeError("First argument must be a string");if(!e)return[];s=s||{};var f=1,d=1;function p(e){var t=e.match(n);t&&(f+=t.length);var r=e.lastIndexOf("\n");d=~r?e.length-r:d+e.length}function m(){var e={line:f,column:d};return function(t){return t.position=new y(e),v(),t}}function y(e){this.start=e,this.end={line:f,column:d},this.source=s.source}y.prototype.content=e;var h=[];function g(t){var n=new Error(s.source+":"+f+":"+d+": "+t);if(n.reason=t,n.filename=s.source,n.line=f,n.column=d,n.source=e,!s.silent)throw n;h.push(n)}function b(t){var n=t.exec(e);if(n){var r=n[0];return p(r),e=e.slice(r.length),n}}function v(){b(r)}function x(e){var t;for(e=e||[];t=S();)!1!==t&&e.push(t);return e}function S(){var t=m();if("/"==e.charAt(0)&&"*"==e.charAt(1)){for(var n=2;c!=e.charAt(n)&&("*"!=e.charAt(n)||"/"!=e.charAt(n+1));)++n;if(n+=2,c===e.charAt(n-1))return g("End of comment missing");var r=e.slice(2,n-2);return d+=2,p(r),e=e.slice(n),d+=2,t({type:"comment",comment:r})}}function w(){var e=m(),n=b(o);if(n){if(S(),!b(i))return g("property missing ':'");var r=b(a),s=e({type:"declaration",property:u(n[0].replace(t,c)),value:r?u(r[0].replace(t,c)):c});return b(l),s}}return v(),function(){var e,t=[];for(x(t);e=w();)!1!==e&&(t.push(e),x(t));return t}()}},583:(e,t,n)=>{"use strict";function r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n{t.SAME=0,t.CAMELCASE=1,t.possibleStandardNames={accept:0,acceptCharset:1,"accept-charset":"acceptCharset",accessKey:1,action:0,allowFullScreen:1,alt:0,as:0,async:0,autoCapitalize:1,autoComplete:1,autoCorrect:1,autoFocus:1,autoPlay:1,autoSave:1,capture:0,cellPadding:1,cellSpacing:1,challenge:0,charSet:1,checked:0,children:0,cite:0,class:"className",classID:1,className:1,cols:0,colSpan:1,content:0,contentEditable:1,contextMenu:1,controls:0,controlsList:1,coords:0,crossOrigin:1,dangerouslySetInnerHTML:1,data:0,dateTime:1,default:0,defaultChecked:1,defaultValue:1,defer:0,dir:0,disabled:0,disablePictureInPicture:1,disableRemotePlayback:1,download:0,draggable:0,encType:1,enterKeyHint:1,for:"htmlFor",form:0,formMethod:1,formAction:1,formEncType:1,formNoValidate:1,formTarget:1,frameBorder:1,headers:0,height:0,hidden:0,high:0,href:0,hrefLang:1,htmlFor:1,httpEquiv:1,"http-equiv":"httpEquiv",icon:0,id:0,innerHTML:1,inputMode:1,integrity:0,is:0,itemID:1,itemProp:1,itemRef:1,itemScope:1,itemType:1,keyParams:1,keyType:1,kind:0,label:0,lang:0,list:0,loop:0,low:0,manifest:0,marginWidth:1,marginHeight:1,max:0,maxLength:1,media:0,mediaGroup:1,method:0,min:0,minLength:1,multiple:0,muted:0,name:0,noModule:1,nonce:0,noValidate:1,open:0,optimum:0,pattern:0,placeholder:0,playsInline:1,poster:0,preload:0,profile:0,radioGroup:1,readOnly:1,referrerPolicy:1,rel:0,required:0,reversed:0,role:0,rows:0,rowSpan:1,sandbox:0,scope:0,scoped:0,scrolling:0,seamless:0,selected:0,shape:0,size:0,sizes:0,span:0,spellCheck:1,src:0,srcDoc:1,srcLang:1,srcSet:1,start:0,step:0,style:0,summary:0,tabIndex:1,target:0,title:0,type:0,useMap:1,value:0,width:0,wmode:0,wrap:0,about:0,accentHeight:1,"accent-height":"accentHeight",accumulate:0,additive:0,alignmentBaseline:1,"alignment-baseline":"alignmentBaseline",allowReorder:1,alphabetic:0,amplitude:0,arabicForm:1,"arabic-form":"arabicForm",ascent:0,attributeName:1,attributeType:1,autoReverse:1,azimuth:0,baseFrequency:1,baselineShift:1,"baseline-shift":"baselineShift",baseProfile:1,bbox:0,begin:0,bias:0,by:0,calcMode:1,capHeight:1,"cap-height":"capHeight",clip:0,clipPath:1,"clip-path":"clipPath",clipPathUnits:1,clipRule:1,"clip-rule":"clipRule",color:0,colorInterpolation:1,"color-interpolation":"colorInterpolation",colorInterpolationFilters:1,"color-interpolation-filters":"colorInterpolationFilters",colorProfile:1,"color-profile":"colorProfile",colorRendering:1,"color-rendering":"colorRendering",contentScriptType:1,contentStyleType:1,cursor:0,cx:0,cy:0,d:0,datatype:0,decelerate:0,descent:0,diffuseConstant:1,direction:0,display:0,divisor:0,dominantBaseline:1,"dominant-baseline":"dominantBaseline",dur:0,dx:0,dy:0,edgeMode:1,elevation:0,enableBackground:1,"enable-background":"enableBackground",end:0,exponent:0,externalResourcesRequired:1,fill:0,fillOpacity:1,"fill-opacity":"fillOpacity",fillRule:1,"fill-rule":"fillRule",filter:0,filterRes:1,filterUnits:1,floodOpacity:1,"flood-opacity":"floodOpacity",floodColor:1,"flood-color":"floodColor",focusable:0,fontFamily:1,"font-family":"fontFamily",fontSize:1,"font-size":"fontSize",fontSizeAdjust:1,"font-size-adjust":"fontSizeAdjust",fontStretch:1,"font-stretch":"fontStretch",fontStyle:1,"font-style":"fontStyle",fontVariant:1,"font-variant":"fontVariant",fontWeight:1,"font-weight":"fontWeight",format:0,from:0,fx:0,fy:0,g1:0,g2:0,glyphName:1,"glyph-name":"glyphName",glyphOrientationHorizontal:1,"glyph-orientation-horizontal":"glyphOrientationHorizontal",glyphOrientationVertical:1,"glyph-orientation-vertical":"glyphOrientationVertical",glyphRef:1,gradientTransform:1,gradientUnits:1,hanging:0,horizAdvX:1,"horiz-adv-x":"horizAdvX",horizOriginX:1,"horiz-origin-x":"horizOriginX",ideographic:0,imageRendering:1,"image-rendering":"imageRendering",in2:0,in:0,inlist:0,intercept:0,k1:0,k2:0,k3:0,k4:0,k:0,kernelMatrix:1,kernelUnitLength:1,kerning:0,keyPoints:1,keySplines:1,keyTimes:1,lengthAdjust:1,letterSpacing:1,"letter-spacing":"letterSpacing",lightingColor:1,"lighting-color":"lightingColor",limitingConeAngle:1,local:0,markerEnd:1,"marker-end":"markerEnd",markerHeight:1,markerMid:1,"marker-mid":"markerMid",markerStart:1,"marker-start":"markerStart",markerUnits:1,markerWidth:1,mask:0,maskContentUnits:1,maskUnits:1,mathematical:0,mode:0,numOctaves:1,offset:0,opacity:0,operator:0,order:0,orient:0,orientation:0,origin:0,overflow:0,overlinePosition:1,"overline-position":"overlinePosition",overlineThickness:1,"overline-thickness":"overlineThickness",paintOrder:1,"paint-order":"paintOrder",panose1:0,"panose-1":"panose1",pathLength:1,patternContentUnits:1,patternTransform:1,patternUnits:1,pointerEvents:1,"pointer-events":"pointerEvents",points:0,pointsAtX:1,pointsAtY:1,pointsAtZ:1,prefix:0,preserveAlpha:1,preserveAspectRatio:1,primitiveUnits:1,property:0,r:0,radius:0,refX:1,refY:1,renderingIntent:1,"rendering-intent":"renderingIntent",repeatCount:1,repeatDur:1,requiredExtensions:1,requiredFeatures:1,resource:0,restart:0,result:0,results:0,rotate:0,rx:0,ry:0,scale:0,security:0,seed:0,shapeRendering:1,"shape-rendering":"shapeRendering",slope:0,spacing:0,specularConstant:1,specularExponent:1,speed:0,spreadMethod:1,startOffset:1,stdDeviation:1,stemh:0,stemv:0,stitchTiles:1,stopColor:1,"stop-color":"stopColor",stopOpacity:1,"stop-opacity":"stopOpacity",strikethroughPosition:1,"strikethrough-position":"strikethroughPosition",strikethroughThickness:1,"strikethrough-thickness":"strikethroughThickness",string:0,stroke:0,strokeDasharray:1,"stroke-dasharray":"strokeDasharray",strokeDashoffset:1,"stroke-dashoffset":"strokeDashoffset",strokeLinecap:1,"stroke-linecap":"strokeLinecap",strokeLinejoin:1,"stroke-linejoin":"strokeLinejoin",strokeMiterlimit:1,"stroke-miterlimit":"strokeMiterlimit",strokeWidth:1,"stroke-width":"strokeWidth",strokeOpacity:1,"stroke-opacity":"strokeOpacity",suppressContentEditableWarning:1,suppressHydrationWarning:1,surfaceScale:1,systemLanguage:1,tableValues:1,targetX:1,targetY:1,textAnchor:1,"text-anchor":"textAnchor",textDecoration:1,"text-decoration":"textDecoration",textLength:1,textRendering:1,"text-rendering":"textRendering",to:0,transform:0,typeof:0,u1:0,u2:0,underlinePosition:1,"underline-position":"underlinePosition",underlineThickness:1,"underline-thickness":"underlineThickness",unicode:0,unicodeBidi:1,"unicode-bidi":"unicodeBidi",unicodeRange:1,"unicode-range":"unicodeRange",unitsPerEm:1,"units-per-em":"unitsPerEm",unselectable:0,vAlphabetic:1,"v-alphabetic":"vAlphabetic",values:0,vectorEffect:1,"vector-effect":"vectorEffect",version:0,vertAdvY:1,"vert-adv-y":"vertAdvY",vertOriginX:1,"vert-origin-x":"vertOriginX",vertOriginY:1,"vert-origin-y":"vertOriginY",vHanging:1,"v-hanging":"vHanging",vIdeographic:1,"v-ideographic":"vIdeographic",viewBox:1,viewTarget:1,visibility:0,vMathematical:1,"v-mathematical":"vMathematical",vocab:0,widths:0,wordSpacing:1,"word-spacing":"wordSpacing",writingMode:1,"writing-mode":"writingMode",x1:0,x2:0,x:0,xChannelSelector:1,xHeight:1,"x-height":"xHeight",xlinkActuate:1,"xlink:actuate":"xlinkActuate",xlinkArcrole:1,"xlink:arcrole":"xlinkArcrole",xlinkHref:1,"xlink:href":"xlinkHref",xlinkRole:1,"xlink:role":"xlinkRole",xlinkShow:1,"xlink:show":"xlinkShow",xlinkTitle:1,"xlink:title":"xlinkTitle",xlinkType:1,"xlink:type":"xlinkType",xmlBase:1,"xml:base":"xmlBase",xmlLang:1,"xml:lang":"xmlLang",xmlns:0,"xml:space":"xmlSpace",xmlnsXlink:1,"xmlns:xlink":"xmlnsXlink",xmlSpace:1,y1:0,y2:0,y:0,yChannelSelector:1,z:0,zoomAndPan:1}},405:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};t.__esModule=!0;var o=r(n(558)),i=n(207);t.default=function(e,t){var n={};return e&&"string"==typeof e?((0,o.default)(e,(function(e,r){e&&r&&(n[(0,i.camelCase)(e,t)]=r)})),n):n}},207:(e,t)=>{"use strict";t.__esModule=!0,t.camelCase=void 0;var n=/^--[a-zA-Z0-9-]+$/,r=/-([a-z])/g,o=/^[^-]+$/,i=/^-(webkit|moz|ms|o|khtml)-/,a=/^-(ms)-/,l=function(e,t){return t.toUpperCase()},s=function(e,t){return"".concat(t,"-")};t.camelCase=function(e,t){return void 0===t&&(t={}),function(e){return!e||o.test(e)||n.test(e)}(e)?e:(e=e.toLowerCase(),(e=t.reactCompat?e.replace(a,s):e.replace(i,s)).replace(r,l))}},558:(e,t,n)=>{var r=n(242);e.exports=function(e,t){var n,o=null;if(!e||"string"!=typeof e)return o;for(var i,a,l=r(e),s="function"==typeof t,c=0,u=l.length;c1&&e.map((function(e,t){return a.default.createElement("td",{key:t,style:m,className:i.td},(0,l.default)(e))})))}))))}},83:function(e,t,n){"use strict";function r(e){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r(e)}var o=this&&this.__assign||function(){return o=Object.assign||function(e){for(var t,n=1,r=arguments.length;n{"use strict";t.exports=e}},n={},function e(r){var o=n[r];if(void 0!==o)return o.exports;var i=n[r]={exports:{}};return t[r].call(i.exports,i,i.exports,e),i.exports}(990);var t,n})); -------------------------------------------------------------------------------- /dist/renderers/checklist.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type ChecklistOutputItemData = { 3 | text: string; 4 | checked: boolean; 5 | }; 6 | type ChecklistOutputData = { 7 | items: ChecklistOutputItemData[]; 8 | }; 9 | type ChecklistOutputClassNames = { 10 | container?: string; 11 | item?: string; 12 | checkbox?: string; 13 | label?: string; 14 | }; 15 | type ChecklistOutputStyles = { 16 | container?: CSSProperties; 17 | item?: CSSProperties; 18 | checkbox?: CSSProperties; 19 | label?: CSSProperties; 20 | }; 21 | type ChecklistOutputProps = { 22 | data: ChecklistOutputData; 23 | style?: ChecklistOutputStyles; 24 | classNames?: ChecklistOutputClassNames; 25 | config?: ErrConfig; 26 | }; 27 | declare const ChecklistOutput: ({ data, style, classNames, config }: ChecklistOutputProps) => JSX.Element; 28 | export default ChecklistOutput; 29 | -------------------------------------------------------------------------------- /dist/renderers/codeBox.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type CodeBoxOutputData = { 3 | code: string; 4 | theme?: string; 5 | language?: string; 6 | }; 7 | type CodeBoxOutputClassNames = { 8 | container?: string; 9 | code?: string; 10 | }; 11 | type CodeBoxOutputStyles = { 12 | container?: CSSProperties; 13 | code?: CSSProperties; 14 | }; 15 | type CodeBoxOutputProps = { 16 | data: CodeBoxOutputData; 17 | style?: CodeBoxOutputStyles; 18 | classNames?: CodeBoxOutputClassNames; 19 | config?: ErrConfig; 20 | }; 21 | declare const CodeBoxOutput: ({ data, style, classNames, config }: CodeBoxOutputProps) => JSX.Element; 22 | export default CodeBoxOutput; 23 | -------------------------------------------------------------------------------- /dist/renderers/delimiter.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type DelimiterOutputClassNames = { 3 | container?: string; 4 | svg?: string; 5 | path?: string; 6 | }; 7 | type DelimiterOutputStyles = { 8 | container?: CSSProperties; 9 | svg?: CSSProperties; 10 | path?: CSSProperties; 11 | }; 12 | type DelimiterOutputProps = { 13 | style?: DelimiterOutputStyles; 14 | classNames?: DelimiterOutputClassNames; 15 | config?: ErrConfig; 16 | }; 17 | declare const DelimiterOutput: ({ style, classNames, config }: DelimiterOutputProps) => JSX.Element; 18 | export default DelimiterOutput; 19 | -------------------------------------------------------------------------------- /dist/renderers/embed.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type EmbedOutputData = { 3 | embed: string; 4 | width?: number; 5 | height?: number; 6 | caption?: string; 7 | }; 8 | type EmbedOutputClassNames = { 9 | video?: string; 10 | figure?: string; 11 | figcaption?: string; 12 | }; 13 | type EmbedOutputStyles = { 14 | video?: CSSProperties; 15 | figure?: CSSProperties; 16 | figcaption?: CSSProperties; 17 | }; 18 | type EmbedOutputProps = { 19 | data: EmbedOutputData; 20 | style?: EmbedOutputStyles; 21 | classNames?: EmbedOutputClassNames; 22 | config?: ErrConfig; 23 | }; 24 | declare const EmbedOutput: ({ data, style, classNames, config }: EmbedOutputProps) => JSX.Element; 25 | export default EmbedOutput; 26 | -------------------------------------------------------------------------------- /dist/renderers/header.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type HeaderOutputData = { 3 | text: string; 4 | level?: 1 | 2 | 3 | 4 | 5 | 6; 5 | }; 6 | type HeaderOutputClassNames = { 7 | h1?: string; 8 | h2?: string; 9 | h3?: string; 10 | h4?: string; 11 | h5?: string; 12 | h6?: string; 13 | }; 14 | type HeaderOutputStyles = { 15 | h1?: CSSProperties; 16 | h2?: CSSProperties; 17 | h3?: CSSProperties; 18 | h4?: CSSProperties; 19 | h5?: CSSProperties; 20 | h6?: CSSProperties; 21 | }; 22 | type HeaderOutputProps = { 23 | data: HeaderOutputData; 24 | style?: HeaderOutputStyles; 25 | classNames?: HeaderOutputClassNames; 26 | config?: ErrConfig; 27 | }; 28 | declare const HeaderOutput: ({ data, style, classNames, config }: HeaderOutputProps) => JSX.Element; 29 | export default HeaderOutput; 30 | -------------------------------------------------------------------------------- /dist/renderers/image.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type ImageOutputData = { 3 | file: { 4 | url: string; 5 | }; 6 | caption?: string; 7 | stretched?: boolean; 8 | withBorder?: boolean; 9 | withBackground?: boolean; 10 | }; 11 | type ImageOutputClassNames = { 12 | img?: string; 13 | figure?: string; 14 | figcaption?: string; 15 | }; 16 | type ImageOutputStyles = { 17 | img?: CSSProperties; 18 | figure?: CSSProperties; 19 | figcaption?: CSSProperties; 20 | }; 21 | type ImageOutputProps = { 22 | data: ImageOutputData; 23 | style?: ImageOutputStyles; 24 | classNames?: ImageOutputClassNames; 25 | config?: ErrConfig; 26 | }; 27 | declare const ImageOutput: ({ data, style, classNames, config }: ImageOutputProps) => JSX.Element; 28 | export default ImageOutput; 29 | -------------------------------------------------------------------------------- /dist/renderers/linkTool.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type LinkToolOutputData = { 3 | link: string; 4 | meta?: { 5 | title?: string; 6 | description?: string; 7 | site_name?: string; 8 | image?: { 9 | url: string; 10 | }; 11 | }; 12 | }; 13 | type LinkToolOutputClassNames = { 14 | container?: string; 15 | textHolder?: string; 16 | title?: string; 17 | description?: string; 18 | image?: string; 19 | siteName?: string; 20 | }; 21 | type LinkToolOutputStyles = { 22 | container?: CSSProperties; 23 | textHolder?: CSSProperties; 24 | title?: CSSProperties; 25 | description?: CSSProperties; 26 | image?: CSSProperties; 27 | siteName?: CSSProperties; 28 | }; 29 | type LinkToolOutputProps = { 30 | data: LinkToolOutputData; 31 | style?: LinkToolOutputStyles; 32 | classNames?: LinkToolOutputClassNames; 33 | config?: ErrConfig; 34 | }; 35 | declare const LinkToolOutput: ({ data, style, classNames, config }: LinkToolOutputProps) => JSX.Element; 36 | export default LinkToolOutput; 37 | -------------------------------------------------------------------------------- /dist/renderers/list.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type ListOutputData = { 3 | items: string[]; 4 | style?: 'ordered' | 'unordered'; 5 | }; 6 | type ListOutputClassNames = { 7 | container?: string; 8 | listItem?: string; 9 | }; 10 | type ListOutputStyles = { 11 | container?: CSSProperties; 12 | listItem?: CSSProperties; 13 | }; 14 | type ListOutputProps = { 15 | data: ListOutputData; 16 | style?: ListOutputStyles; 17 | classNames?: ListOutputClassNames; 18 | config?: ErrConfig; 19 | }; 20 | declare const ListOutput: ({ data, style, classNames, config }: ListOutputProps) => JSX.Element; 21 | export default ListOutput; 22 | -------------------------------------------------------------------------------- /dist/renderers/paragraph.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type ParagraphOutputData = { 3 | text: string; 4 | }; 5 | type ParagraphOutputProps = { 6 | data: string | ParagraphOutputData; 7 | style?: CSSProperties; 8 | classNames?: string; 9 | config?: ErrConfig; 10 | }; 11 | declare const ParagraphOutput: ({ data, style, classNames, config }: ParagraphOutputProps) => JSX.Element; 12 | export default ParagraphOutput; 13 | -------------------------------------------------------------------------------- /dist/renderers/personality.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type PersonalityOutputData = { 3 | link: string; 4 | name?: string; 5 | description?: string; 6 | photo?: string; 7 | }; 8 | type PersonalityOutputClassNames = { 9 | container?: string; 10 | textHolder?: string; 11 | description?: string; 12 | name?: string; 13 | link?: string; 14 | photo?: string; 15 | }; 16 | type PersonalityOutputStyles = { 17 | container?: CSSProperties; 18 | textHolder?: CSSProperties; 19 | description?: CSSProperties; 20 | name?: CSSProperties; 21 | link?: CSSProperties; 22 | photo?: CSSProperties; 23 | }; 24 | type PersonalityOutputProps = { 25 | data: PersonalityOutputData; 26 | style?: PersonalityOutputStyles; 27 | classNames?: PersonalityOutputClassNames; 28 | config?: ErrConfig; 29 | }; 30 | declare const PersonalityOutput: ({ data, style, classNames, config }: PersonalityOutputProps) => JSX.Element; 31 | export default PersonalityOutput; 32 | -------------------------------------------------------------------------------- /dist/renderers/quote.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type QuoteOutputData = { 3 | text: string; 4 | caption?: string; 5 | alignment?: string; 6 | }; 7 | type QuoteOutputClassNames = { 8 | container?: string; 9 | content?: string; 10 | author?: string; 11 | message?: string; 12 | }; 13 | type QuoteOutputStyles = { 14 | container?: CSSProperties; 15 | content?: CSSProperties; 16 | author?: CSSProperties; 17 | message?: CSSProperties; 18 | }; 19 | type QuoteOutputProps = { 20 | data: QuoteOutputData; 21 | style?: QuoteOutputStyles; 22 | classNames?: QuoteOutputClassNames; 23 | config?: ErrConfig; 24 | }; 25 | declare const QuoteOutput: ({ data, style, classNames, config }: QuoteOutputProps) => JSX.Element; 26 | export default QuoteOutput; 27 | -------------------------------------------------------------------------------- /dist/renderers/table.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type TableOutputData = { 3 | content: string[][]; 4 | }; 5 | type TableOutputClassNames = { 6 | table?: string; 7 | tr?: string; 8 | th?: string; 9 | td?: string; 10 | }; 11 | type TableOutputStyles = { 12 | table?: CSSProperties; 13 | tr?: CSSProperties; 14 | th?: CSSProperties; 15 | td?: CSSProperties; 16 | }; 17 | type TableOutputProps = { 18 | data: TableOutputData; 19 | style?: TableOutputStyles; 20 | classNames?: TableOutputClassNames; 21 | config?: ErrConfig; 22 | }; 23 | declare const TableOutput: ({ data, style, classNames, config }: TableOutputProps) => JSX.Element; 24 | export default TableOutput; 25 | -------------------------------------------------------------------------------- /dist/renderers/video.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type VideoOutputData = { 3 | url?: string; 4 | file?: { 5 | url: string; 6 | }; 7 | caption?: string; 8 | autoPlay?: boolean; 9 | muted?: boolean; 10 | controls?: boolean; 11 | stretched?: boolean; 12 | withBorder?: boolean; 13 | withBackground?: boolean; 14 | }; 15 | type VideoOutputClassNames = { 16 | video?: string; 17 | figure?: string; 18 | figcaption?: string; 19 | }; 20 | type VideoOutputStyles = { 21 | video?: CSSProperties; 22 | figure?: CSSProperties; 23 | figcaption?: CSSProperties; 24 | }; 25 | type VideoOutputProps = { 26 | data: VideoOutputData; 27 | style?: VideoOutputStyles; 28 | classNames?: VideoOutputClassNames; 29 | config?: ErrConfig; 30 | }; 31 | declare const VideoOutput: ({ data, style, classNames, config }: VideoOutputProps) => JSX.Element; 32 | export default VideoOutput; 33 | -------------------------------------------------------------------------------- /dist/renderers/warning.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react'; 2 | type WarningOutputData = { 3 | message: string; 4 | title?: string; 5 | }; 6 | type WarningOutputClassNames = { 7 | container?: string; 8 | icon?: string; 9 | title?: string; 10 | message?: string; 11 | }; 12 | type WarningOutputStyles = { 13 | container?: CSSProperties; 14 | icon?: CSSProperties; 15 | title?: CSSProperties; 16 | message?: CSSProperties; 17 | }; 18 | type WarningOutputProps = { 19 | data: WarningOutputData; 20 | style?: WarningOutputStyles; 21 | classNames?: WarningOutputClassNames; 22 | config?: ErrConfig; 23 | }; 24 | declare const WarningOutput: ({ data, style, classNames, config }: WarningOutputProps) => JSX.Element; 25 | export default WarningOutput; 26 | -------------------------------------------------------------------------------- /docs/example/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | npm-debug.log* 16 | yarn-debug.log* 17 | yarn-error.log* 18 | 19 | 20 | .now 21 | .vercel -------------------------------------------------------------------------------- /docs/example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "err", 3 | "version": "1.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "editorjs-react-renderer": "^3.5.0", 7 | "prop-types": "^15.8.1", 8 | "react": "^18.2.0", 9 | "react-dom": "^18.2.0", 10 | "react-scripts": "^5.0.1", 11 | "typescript": "^4.9.3" 12 | }, 13 | "devDependencies": { 14 | "@types/jest": "^29.2.3", 15 | "@types/node": "^18.11.10" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test --env=jsdom", 21 | "predeploy": "npm run build", 22 | "eject": "react-scripts eject" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /docs/example/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | EditorJS React Renderer 17 | 18 | 19 |
20 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /docs/example/src/components/app/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | header { 6 | text-align: left; 7 | padding: 15px 5%; 8 | background-color: darkcyan; 9 | color: white; 10 | } 11 | 12 | .App-intro { 13 | font-size: large; 14 | } 15 | -------------------------------------------------------------------------------- /docs/example/src/components/app/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /docs/example/src/components/app/App.tsx: -------------------------------------------------------------------------------- 1 | import Post from '../post/Post'; 2 | import './App.css'; 3 | import { data } from './testData'; 4 | 5 | const App = () => ( 6 |
7 |
Editor.js React Renderer
8 | 9 |
10 | ); 11 | 12 | export default App; 13 | -------------------------------------------------------------------------------- /docs/example/src/components/app/testData.ts: -------------------------------------------------------------------------------- 1 | export const data = { 2 | "time": 1572712253468, 3 | "blocks": [ 4 | { 5 | "type": "header", 6 | "data": { 7 | "text": "Image", 8 | "level": 4 9 | } 10 | }, 11 | { 12 | "type": "paragraph", 13 | "data": { 14 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 15 | } 16 | }, 17 | { 18 | "type": "image", 19 | "data": { 20 | "file": { 21 | "url": "https://firebasestorage.googleapis.com/v0/b/editorjs-react-renderer.appspot.com/o/editorjs-react-renderer%20-%20npm%206.png?alt=media&token=74f2d7e5-2c9c-4cd4-bcd0-1c99282dd266" 22 | }, 23 | "caption": "https://bomdisoft.com", 24 | "withBorder": false, 25 | "stretched": false, 26 | "withBackground": false 27 | } 28 | }, 29 | { 30 | "type": "header", 31 | "data": { 32 | "text": "Embed", 33 | "level": 4 34 | } 35 | }, 36 | { 37 | "type": "paragraph", 38 | "data": { 39 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 40 | } 41 | }, 42 | { 43 | "type" : "embed", 44 | "data" : { 45 | "service" : "coub", 46 | "source" : "https://coub.com/view/1czcdf", 47 | "embed" : "https://www.youtube.com/embed/RsMikJZhnSQ", 48 | "caption" : "My Life", 49 | } 50 | }, 51 | { 52 | "type": "header", 53 | "data": { 54 | "text": "Delimiter", 55 | "level": 4 56 | } 57 | }, 58 | { 59 | "type": "paragraph", 60 | "data": { 61 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur! Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 62 | } 63 | }, 64 | { 65 | "type": "delimiter", 66 | "data": {} 67 | }, 68 | { 69 | "type": "paragraph", 70 | "data": { 71 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur! Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 72 | } 73 | }, 74 | { 75 | "type": "header", 76 | "data": { 77 | "text": "Personality", 78 | "level": 4 79 | } 80 | }, 81 | { 82 | "type": "paragraph", 83 | "data": { 84 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur! Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 85 | } 86 | }, 87 | { 88 | "type" : "personality", 89 | "data" : { 90 | "name" : "Elon Musk", 91 | "description" : "Elon Reeve Musk FRS is a technology entrepreneur, investor, and engineer. He holds South African, Canadian, and U.S. citizenship and is the founder", 92 | "link" : "https://twitter.com/elonmusk", 93 | "photo" : "https://capella.pics/3c0e1b97-bc56-4961-b54e-2a6c2c3260f2.jpg" 94 | } 95 | }, 96 | { 97 | "type": "paragraph", 98 | "data": { 99 | "text": "Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 100 | } 101 | }, 102 | { 103 | "type": "header", 104 | "data": { 105 | "text": "Link", 106 | "level": 4 107 | } 108 | }, 109 | { 110 | "type": "paragraph", 111 | "data": { 112 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur! Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 113 | } 114 | }, 115 | { 116 | "type" : "linkTool", 117 | "data" : { 118 | "link" : "https://codex.so", 119 | "meta" : { 120 | "title" : "CodeX Team", 121 | "site_name" : "CodeX", 122 | "description" : "Club of web-development, design and marketing. We build team learning how to build full-valued projects on the world market.", 123 | "image" : { 124 | "url" : "https://codex.so/public/app/img/meta_img.png" 125 | } 126 | } 127 | } 128 | }, 129 | { 130 | "type": "paragraph", 131 | "data": { 132 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur! Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 133 | } 134 | }, 135 | { 136 | "type": "header", 137 | "data": { 138 | "text": "Code block", 139 | "level": 4 140 | } 141 | }, 142 | { 143 | "type": "codeBox", 144 | "data": { 145 | "code": ".codeBoxTextArea{\n width: 100%;\n min-height: 30px;\n padding: 10px;\n border-radius: 2px 2px 2px 0;\n border: none !important;\n outline: none !important;\n font: 14px monospace;\n}\n\n.codeBoxSelectDiv{\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: flex-start;\n position: relative;\n}", 146 | "language": "css", 147 | "theme": "https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.18.1/build/styles/atom-one-dark.min.css" 148 | } 149 | }, 150 | { 151 | "type": "paragraph", 152 | "data": { 153 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 154 | } 155 | }, 156 | { 157 | "type": "header", 158 | "data": { 159 | "text": "Lists", 160 | "level": 4 161 | } 162 | }, 163 | { 164 | "type": "paragraph", 165 | "data": { 166 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 167 | } 168 | }, 169 | { 170 | "type": "checklist", 171 | "data": { 172 | "items": [ 173 | { 174 | "text": "Gather requirements", 175 | "checked": true 176 | }, 177 | { 178 | "text": "Develop API", 179 | "checked": true 180 | }, 181 | { 182 | "text": "Notify stakeholders", 183 | "checked": false 184 | }, 185 | { 186 | "text": "Develop Web App", 187 | "checked": false 188 | } 189 | ] 190 | } 191 | }, 192 | { 193 | "type": "paragraph", 194 | "data": { 195 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 196 | } 197 | }, 198 | { 199 | "type": "list", 200 | "data": { 201 | "style": "ordered", 202 | "items": [ 203 | "First iteration", 204 | "Second iteration" 205 | ] 206 | } 207 | }, 208 | { 209 | "type": "paragraph", 210 | "data": { 211 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 212 | } 213 | }, 214 | { 215 | "type": "list", 216 | "data": { 217 | "style": "unordered", 218 | "items": [ 219 | "Item one", 220 | "Item two" 221 | ] 222 | } 223 | }, 224 | { 225 | "type": "header", 226 | "data": { 227 | "text": "Table", 228 | "level": 4 229 | } 230 | }, 231 | { 232 | "type": "paragraph", 233 | "data": { 234 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 235 | } 236 | }, 237 | { 238 | "type": "table", 239 | "data": { 240 | "content": [ 241 | [ 242 | "
Name
", 243 | "
Age
", 244 | "
Position
", 245 | "
SSN
" 246 | ], 247 | [ 248 | "
Jack 
", 249 | "
51
", 250 | "
All trades
", 251 | "
654654414131333
" 252 | ], 253 | [ 254 | "
John Doe
", 255 | "
21
", 256 | "
Senior Consultant
", 257 | "
0002145465145641
" 258 | ] 259 | ] 260 | } 261 | }, 262 | { 263 | "type": "header", 264 | "data": { 265 | "text": "Warning and simple video", 266 | "level": 4 267 | } 268 | }, 269 | { 270 | "type": "warning", 271 | "data": { 272 | "title": "", 273 | "message": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorem temporibus quae distinctio facilis in minus quaerat non illum adipisci ab similique eos est eligendi cumque, quibusdam, fugit voluptates omnis pariatur!" 274 | } 275 | }, 276 | { 277 | "type" : "video", 278 | "data" : { 279 | // "url" : "https://paul.kinlan.me/videos/2019-11-05--test-post-video-upload-0.mp4", 280 | "file": { "url" : "https://paul.kinlan.me/videos/2019-11-05--test-post-video-upload-0.mp4" }, 281 | "caption" : "An aweomse video", 282 | "autoplay" : false, 283 | "controls" : false, 284 | "muted": false, 285 | "stretched" : false 286 | } 287 | }, 288 | { 289 | "type": "header", 290 | "data": { 291 | "text": "Custom Renderer", 292 | "level": 4 293 | } 294 | }, 295 | { 296 | "type": "avatar", 297 | "data": { 298 | "imageURL": "https://firebasestorage.googleapis.com/v0/b/bomdisoft-28c17.appspot.com/o/logo%2Flogo%20icon%20white%20-%20192.png?alt=media&token=b1cf145a-89b9-43f4-bcbe-7380cce32138" 299 | } 300 | }, 301 | ], 302 | "version": "2.14.0" 303 | }; 304 | -------------------------------------------------------------------------------- /docs/example/src/components/post/Post.css: -------------------------------------------------------------------------------- 1 | section { 2 | overflow-x: hidden; 3 | padding: 10px 20%; 4 | margin: 10px 0; 5 | display: flex; 6 | flex-direction: column; 7 | justify-content: flex-start; 8 | align-items: flex-start; 9 | } 10 | -------------------------------------------------------------------------------- /docs/example/src/components/post/Post.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Post from './Post'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /docs/example/src/components/post/Post.tsx: -------------------------------------------------------------------------------- 1 | import Output from 'editorjs-react-renderer'; 2 | import './Post.css'; 3 | 4 | const style = { 5 | header: { 6 | h1: { 7 | color: 'lightseagreen', 8 | fontFamily: 'cursive' 9 | }, 10 | }, 11 | image: { 12 | img: {}, 13 | figure: {}, 14 | figcaption: {} 15 | }, 16 | paragraph: { 17 | textAlign: 'justify', 18 | margin: '8px 0', 19 | fontSize: '18px', 20 | lineHeight: '1.7', 21 | fontWeight: 200, 22 | }, 23 | list: {}, 24 | table: { 25 | table: {}, 26 | tr: {}, 27 | th: {}, 28 | td: {}, 29 | }, 30 | quote: { 31 | container: {}, 32 | content: {}, 33 | author: {}, 34 | message: {} 35 | }, 36 | codebox: { 37 | code: { lineHeight: '22px' }, 38 | }, 39 | warning: { 40 | icon: { 41 | width: '28px', 42 | }, 43 | title: { 44 | marginRight: '10px' 45 | }, 46 | message: { 47 | textAlign: 'left' 48 | }, 49 | }, 50 | avatar: { 51 | height: '40px', 52 | width: '40px', 53 | borderRadius: '20px', 54 | margin: '8px', 55 | boxShadow: '0 0 4px 0 rgba(0,0,0,0.5)', 56 | backgroundColor: '#1e242a' 57 | } 58 | }; 59 | 60 | const AvatarRenderer = ({ data, style, classNames, config }: any) => { 61 | let content = null; 62 | 63 | if (typeof data === 'string') content = data; 64 | else if (typeof data === 'object' && data.imageURL && typeof data.imageURL === 'string') content = data.imageURL; 65 | 66 | return content ? : <>; 67 | }; 68 | 69 | const renderers = { 70 | avatar: AvatarRenderer 71 | }; 72 | 73 | const Post = ({ data }) => ( 74 |
75 | 76 |
77 | ); 78 | 79 | export default Post; 80 | -------------------------------------------------------------------------------- /docs/example/src/index.css: -------------------------------------------------------------------------------- 1 | @import url(https://fonts.googleapis.com/css?family=Open+Sans|Indie+Flower); 2 | 3 | * { 4 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 5 | } 6 | 7 | body { 8 | margin: 0; 9 | padding: 0; 10 | overflow: 'hidden', 11 | } 12 | -------------------------------------------------------------------------------- /docs/example/src/index.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from 'react-dom/client'; 2 | import App from './components/app/App'; 3 | import './index.css'; 4 | 5 | const root = createRoot(document.getElementById('root')); 6 | root.render(); 7 | -------------------------------------------------------------------------------- /docs/example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": false, 12 | "forceConsistentCasingInFileNames": true, 13 | "noEmit": true, 14 | "esModuleInterop": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "incremental": true, 20 | "jsx": "preserve", 21 | }, 22 | "include": [ 23 | "next-env.d.ts", 24 | "**/*.ts", 25 | "**/*.tsx" ], 26 | "exclude": [ 27 | "node_modules", 28 | "builds" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /err.d.ts: -------------------------------------------------------------------------------- 1 | import type { CSSProperties } from 'react' 2 | 3 | declare global { 4 | 5 | // GENERICS 6 | type ErrConfig = { 7 | disableDefaultStyle: boolean 8 | } 9 | 10 | type ErrOutputData = { 11 | blocks: ErrBlock[] 12 | time?: number 13 | version?: string 14 | } 15 | 16 | type ErrBlock = { type: 'checklist', data: ChecklistOutputData } 17 | | { type: 'codebox', data: CodeBoxOutputData } 18 | | { type: 'delimiter', data: DelimiterOutputData } 19 | | { type: 'embed', data: EmbedOutputData } 20 | | { type: 'header', data: HeaderOutputData } 21 | | { type: 'image', data: ImageOutputData } 22 | | { type: 'list', data: ListOutputData } 23 | | { type: 'paragraph', data: ParagraphOutputData } 24 | | { type: 'quote', data: QuoteOutputData } 25 | | { type: 'table', data: TableOutputData } 26 | | { type: 'video', data: VideoOutputData } 27 | | { type: 'warning', data: WarningOutputData } 28 | | { type: 'linktool', data: LinktoolOutputData } 29 | | { type: 'personality', data: PersonalityOutputData } 30 | 31 | type ErrOutputProps = { 32 | data: ErrOutputData 33 | style?: ErrOutputStyle 34 | classNames?: ErrOutputClassNames 35 | config?: ErrOutputConfig 36 | renderers?: ErrOutputRenderers 37 | } 38 | 39 | type ErrOutputConfig = { 40 | checklist?: ErrConfig 41 | codebox?: ErrConfig 42 | delimiter?: ErrConfig 43 | embed?: ErrConfig 44 | header?: ErrConfig 45 | image?: ErrConfig 46 | list?: ErrConfig 47 | paragraph?: ErrConfig 48 | quote?: ErrConfig 49 | table?: ErrConfig 50 | video?: ErrConfig 51 | warning?: ErrConfig 52 | linktool?: ErrConfig 53 | personality?: ErrConfig 54 | } 55 | 56 | type ErrOutputClassNames = { 57 | checklist?: ChecklistOutputClassNames 58 | codebox?: CodeBoxOutputClassNames 59 | delimiter?: DelimiterOutputClassNames 60 | embed?: EmbedOutputClassNames 61 | header?: HeaderOutputClassNames 62 | image?: ImageOutputClassNames 63 | list?: ListOutputClassNames 64 | paragraph?: string 65 | quote?: QuoteOutputClassNames 66 | table?: TableOutputClassNames 67 | video?: VideoOutputClassNames 68 | warning?: WarningOutputClassNames 69 | linktool?: LinkToolOutputClassNames 70 | personality?: PersonalityOutputClassNames 71 | } 72 | 73 | type ErrOutputStyle = { 74 | checklist?: ChecklistOutputStyles 75 | codebox?: CodeBoxOutputStyles 76 | delimiter?: DelimiterOutputStyles 77 | embed?: EmbedOutputStyles 78 | header?: HeaderOutputStyles 79 | image?: ImageOutputStyles 80 | list?: ListOutputStyles 81 | paragraph?: CSSProperties 82 | quote?: QuoteOutputStyles 83 | table?: TableOutputStyles 84 | video?: VideoOutputStyles 85 | warning?: WarningOutputStyles 86 | linktool?: LinkToolOutputStyles 87 | personality?: PersonalityOutputStyles 88 | } 89 | 90 | type ErrOutputRenderers = { 91 | checklist?: (props: ChecklistOutputProps) => JSX.Element 92 | codebox?: (props: CodeBoxOutputProps) => JSX.Element 93 | delimiter?: (props: DelimiterOutputProps) => JSX.Element 94 | embed?: (props: EmbedOutputProps) => JSX.Element 95 | header?: (props: HeaderOutputProps) => JSX.Element 96 | image?: (props: ImageOutputProps) => JSX.Element 97 | list?: (props: ListOutputProps) => JSX.Element 98 | paragraph?: (props: ParagraphOutputProps) => JSX.Element 99 | quote?: (props: QuoteOutputProps) => JSX.Element 100 | table?: (props: TableOutputProps) => JSX.Element 101 | video?: (props: VideoOutputProps) => JSX.Element 102 | warning?: (props: WarningOutputProps) => JSX.Element 103 | linktool?: (props: LinkToolOutputProps) => JSX.Element 104 | personality?: (props: PersonalityOutputProps) => JSX.Element 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /index.tsx: -------------------------------------------------------------------------------- 1 | /** EditorJS-React Renderer 2 | * 3 | * A small library that provides functions to parse and render data saved by 4 | * EditorJS into react components 5 | * 6 | * @version 1.0.0 7 | * @created - 2019.08.20 8 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 9 | * 10 | * Version History 11 | * --------------- 12 | * @version 1.0.1 - 2020.02.12 - Covert functions to React component 13 | * - Add CodeBoxOutput 14 | * @version 1.0.2 - 2020.05.21 - Add key to list items 15 | * @version 1.0.3 - 2020.07.17 - Add config parameter 16 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 17 | * @version 1.2.0 - 2022.05.19 - Add LinkToolOutput and PersonalityOutput 18 | * @version 1.3.0 - 2022.08.21 - Allow custom renderers for unsupported blocks 19 | * @version 1.3.1 - 2022.11.26 - Redefine types 20 | */ 21 | 22 | //#region imports 23 | import React from 'react'; 24 | import HeaderOutput from './renderers/header'; 25 | import ParagraphOutput from './renderers/paragraph'; 26 | import ImageOutput from './renderers/image'; 27 | import VideoOutput from './renderers/video'; 28 | import EmbedOutput from './renderers/embed'; 29 | import ListOutput from './renderers/list'; 30 | import QuoteOutput from './renderers/quote'; 31 | import ChecklistOutput from './renderers/checklist'; 32 | import WarningOutput from './renderers/warning'; 33 | import TableOutput from './renderers/table'; 34 | import DelimiterOutput from './renderers/delimiter'; 35 | import CodeBoxOutput from './renderers/codeBox'; 36 | import LinkToolOutput from './renderers/linkTool'; 37 | import PersonalityOutput from './renderers/personality'; 38 | //#endregion 39 | 40 | const Output = ({ data, style, classNames, config, renderers }: ErrOutputProps): JSX.Element => { 41 | if (!data || typeof data !== 'object') return <>; 42 | if (!style || typeof style !== 'object') style = {}; 43 | if (!classNames || typeof classNames !== 'object') classNames = {}; 44 | if (!config || typeof config !== 'object') config = {}; 45 | if (!renderers || typeof renderers !== 'object') renderers = {}; 46 | 47 | return ( 48 | <> 49 | { 50 | data.blocks.map((block, i) => { 51 | const key = block.type.toLowerCase(); 52 | let Renderer = renderers[key] || getDefaultRenderer(key); 53 | 54 | if (!Renderer) return <>; 55 | 56 | return ; 58 | }) 59 | } 60 | 61 | ); 62 | }; 63 | 64 | const getDefaultRenderer = (key: string) => { 65 | switch (key) { 66 | case 'codebox': return CodeBoxOutput; 67 | case 'header': return HeaderOutput; 68 | case 'paragraph': return ParagraphOutput; 69 | case 'image': return ImageOutput; 70 | case 'video': return VideoOutput; 71 | case 'embed': return EmbedOutput; 72 | case 'table': return TableOutput; 73 | case 'list': return ListOutput; 74 | case 'checklist': return ChecklistOutput; 75 | case 'quote': return QuoteOutput; 76 | case 'warning': return WarningOutput; 77 | case 'linktool': return LinkToolOutput; 78 | case 'personality': return PersonalityOutput; 79 | case 'delimiter': return DelimiterOutput; 80 | default: return null; 81 | } 82 | }; 83 | 84 | export { 85 | HeaderOutput, ParagraphOutput, ImageOutput, VideoOutput, EmbedOutput, TableOutput, 86 | CodeBoxOutput, ListOutput, QuoteOutput, ChecklistOutput, WarningOutput, DelimiterOutput, 87 | LinkToolOutput, PersonalityOutput, Output as default 88 | }; 89 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "editorjs-react-renderer", 3 | "version": "3.5.1", 4 | "license": "ISC", 5 | "description": "A library for rendering styled, responsive and flexible React components from block style data objects", 6 | "keywords": [ 7 | "EditorJS React Renderer", 8 | "Editor.js", 9 | "React", 10 | "Codex Editor", 11 | "Rich Text Editor", 12 | "EditorJS React", 13 | "EditorJS Renderer" 14 | ], 15 | "author": "Adombang Munang Mbomndih (https://bomdisoft.com)", 16 | "homepage": "https://err.bomdisoft.com/", 17 | "contributors": [ 18 | "Tomáš Hylský (https://linktr.ee/thylsky)", 19 | "Gabrijel Gavranović", 20 | "Alvaro Lozano", 21 | "remoblaser (http://www.remoblaser.ch)" 22 | ], 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/dev-juju/EditorJS-React-Renderer.git" 26 | }, 27 | "scripts": { 28 | "build": "webpack --progress", 29 | "start": "babel-node test.js", 30 | "test": "jest", 31 | "test:watch": "jest --watch", 32 | "test:coverage": "jest --coverage" 33 | }, 34 | "dependencies": { 35 | "html-react-parser": "^3.0.4", 36 | "react": "^18.2.0" 37 | }, 38 | "devDependencies": { 39 | "@babel/cli": "^7.19.3", 40 | "@babel/core": "^7.20.5", 41 | "@babel/node": "^7.20.5", 42 | "@babel/plugin-proposal-class-properties": "^7.18.6", 43 | "@babel/plugin-proposal-object-rest-spread": "^7.20.2", 44 | "@babel/preset-env": "^7.20.2", 45 | "@babel/preset-react": "^7.18.6", 46 | "@types/react": "^18.0.25", 47 | "babel-core": "^7.0.0-bridge.0", 48 | "babel-loader": "^9.1.0", 49 | "ts-loader": "^9.4.2", 50 | "typescript": "^4.9.3", 51 | "webpack": "^5.75.0", 52 | "webpack-cli": "^5.0.0" 53 | }, 54 | "babel": { 55 | "presets": [ 56 | "@babel/env", 57 | "@babel/react" 58 | ], 59 | "plugins": [ 60 | "@babel/plugin-proposal-class-properties", 61 | "@babel/plugin-proposal-object-rest-spread" 62 | ] 63 | }, 64 | "files": [ 65 | "dist" 66 | ], 67 | "main": "dist/index.min.js", 68 | "types": "dist/index.d.ts" 69 | } 70 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # [EditorJS-React Renderer (ERR)](https://err.bomdisoft.com/) 2 | 3 | [View live example](https://err.bomdisoft.com/) 4 | 5 | [![](https://flat.badgen.net/npm/v/editorjs-react-renderer?icon=npm)](https://www.npmjs.com/package/editorjs-react-renderer) 6 | ![npm](https://img.shields.io/npm/dw/editorjs-react-renderer) 7 | [![](https://flat.badgen.net/npm/license/editorjs-react-renderer)](https://www.npmjs.com/package/editorjs-react-renderer) 8 | [![](https://flat.badgen.net/github/stars/dev-juju/editorjs-react-renderer)](https://www.npmjs.com/package/editorjs-react-renderer) 9 | [![](https://flat.badgen.net/badge/icon/typescript?icon=typescript&label)](https://www.npmjs.com/package/editorjs-react-renderer) 10 | 11 | A library for rendering styled, responsive and flexible React components from [block style](https://editorjs.io/saving-data) data objects. 12 | 13 | This package works well with output from the [Editor.js](https://editorjs.io/) rich text editor library. 14 | However, there is no dependency on Editor.js. We only require that your data is in a similar block style format. 15 | 16 | 17 | ## Setup 18 | 19 | Install the package via NPM 20 | 21 | ```shell 22 | npm i editorjs-react-renderer 23 | ``` 24 | 25 | Install React if you don't already have it in your project 26 | 27 | ```shell 28 | npm i react 29 | ``` 30 | 31 | CDN usage will be available soon... 32 | 33 | Add to your module/application 34 | 35 | ```javascript 36 | import Output from 'editorjs-react-renderer'; 37 | OR 38 | const Output = require('editorjs-react-renderer'); 39 | ``` 40 | 41 | **Output** accepts a block style data object as prop 42 | 43 | ```javascript 44 | const data = { 45 | "time": 1564767102436, 46 | "blocks": [ 47 | { 48 | "type" : "header", 49 | "data" : { 50 | "level" : 4, 51 | "text" : "Editor.js React Renderer" 52 | } 53 | }, 54 | { 55 | "type": "image", 56 | "data": { 57 | "file": { 58 | "url": "" 59 | }, 60 | "caption": "Test Caption", 61 | "withBorder": false, 62 | "stretched": false, 63 | "withBackground": false 64 | } 65 | }, 66 | { 67 | "type": "paragraph", 68 | "data": { 69 | "text": "Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque accusantium veritatis dolorum cum amet! Ipsa ullam nisi, dolor explicabo ut nobis repudiandae saepe illo error facilis consectetur, quisquam assumenda dolorum." 70 | } 71 | }, 72 | ... 73 | ], 74 | "version": "2.14.0" 75 | }; 76 | ``` 77 | 78 | *The **time** and **version** properties are not required. Only the **blocks** array is required* 79 | 80 | Notice that your block data can also be HTML markup. 81 | Pass your block style data to **Output()** and ERR will take care of the rest :) 82 | 83 | ```javascript 84 | const Post = () =>
; 85 | 86 | export default Post; 87 | ``` 88 | 89 | Each object in the *blocks* property of your block style data is converted to a responsive, styled React component. 90 | 91 | **Output()** accepts a style prop through which you can add custom style to the supported components. 92 | 93 | See the [Style](#style) section for more 94 | 95 | 96 | ## Render Single Block 97 | 98 | Sometimes you might want to render just a single component like a paragraph or header. While this is possible with the **Output** component, you should consider using one of the more specific block output components. 99 | 100 | ```javascript 101 | import { ListOutput } from 'editorjs-react-renderer'; 102 | 103 | const listData = { 104 | "items" : ["Item one", "Another item", "Item 3"], 105 | "style" : "unordered" // ordered or unordered 106 | }; 107 | 108 | // Your custom style will be merged with the defaults, with yours as priority 109 | // You can use inline styles or classes 110 | const listStyle = { 111 | textAlign: 'left' 112 | }; 113 | const listClass = 'some-class-name'; 114 | 115 | const Todo = () => ; 116 | 117 | export default Todo; 118 | ``` 119 | 120 | See the [API](#api) section for more block output components 121 | 122 | 123 | ## Custom Renderers 124 | 125 | We provide several granular styling options so that you have the ability and flexibility to customize the look and feel of the rendered components. 126 | However, you might still have a need to override the default renderers for certain blocks or implement a renderer for an unsupported block. 127 | You can do that by passing a *renderers* prop to the **Output** component. The renderers prop is an object whose keys are the names of the supported components and whose values are the corresponding renderer definitions to override the defaults. 128 | Custom renderers should expect to receive *data*, *style*, *classNames* and *config* props. 129 | 130 | ```javascript 131 | // Define your custom renderer 132 | // It should expect to receive data, style, classNames and config props. It's up to you to handle those props. 133 | const CustomParagraphRenderer = ({ data, style, classNames, config }) => { 134 | // validate props here...or not :) 135 | 136 | let content = null; 137 | 138 | if (typeof data === 'string') content = data; 139 | else if (typeof data === 'object' && data.text && typeof data.text === 'string') content = data.text; 140 | 141 | return content ?

{ ReactHtmlParser(content) }

: ''; 142 | }; 143 | 144 | // You can define a renderer for unsupported blocks. 145 | // Structure your data however you like, and handle it in your custom renderer. 146 | const AvatarRenderer = ({ data, style, classNames, config }) => { 147 | let content = null; 148 | 149 | if (typeof data === 'string') content = data; 150 | else if (typeof data === 'object' && data.imageURL && typeof data.imageURL === 'string') content = data.imageURL; 151 | 152 | return content ? : ''; 153 | }; 154 | 155 | // Pass your custom renderers to Output 156 | const renderers = { 157 | paragraph: CustomParagraphRenderer, 158 | avatar: AvatarRenderer 159 | }; 160 | 161 | // **Your data type should match the renderer key 162 | const data = { 163 | blocks: [ 164 | ..., 165 | { 166 | "type": "avatar", 167 | "data": { 168 | "imageURL": "" 169 | } 170 | }, 171 | ] 172 | } 173 | 174 | const Todo = () => ; 175 | 176 | export default Todo; 177 | ``` 178 | 179 | 180 | 181 | ## Style 182 | You can use inline and/or className styling to change the default look and feel of all supported components 183 | The following examples will show you how to use both 184 | 185 | ```javascript 186 | import { HeaderOutput, ParagraphOutput } from 'editorjs-react-renderer'; 187 | 188 | const data = { 189 | header: {...}, 190 | paragraph: {...} 191 | }; 192 | 193 | // All valid JSX inline styles are allowed 194 | const style = { 195 | header: { 196 | textAlign: 'left', 197 | margin: '10px 20px', 198 | }, 199 | paragraph: { 200 | fontSize: '16px', 201 | } 202 | }; 203 | 204 | const classes = { 205 | header: 'header-class1 header-class2', 206 | paragraph: 'paragraph-class', 207 | }; 208 | 209 | const Post = () => ( 210 |
211 | 212 | 213 |
214 | ); 215 | 216 | export default Post; 217 | ``` 218 | 219 | Most components have sub-components which can also be styled separately 220 | 221 | ```javascript 222 | import { ImageOutput } from 'editorjs-react-renderer'; 223 | 224 | const image = {...}; 225 | 226 | // All valid JSX inline styles are allowed 227 | const style = { 228 | image: { 229 | img: { 230 | maxHeight: '400px', 231 | }, 232 | figure: {...}, 233 | figcaption: {...} 234 | }, 235 | }; 236 | 237 | const classes = { 238 | image: { 239 | img: 'img-class', 240 | figure: 'figure-c', 241 | figcaption: 'someClassName' 242 | }, 243 | }; 244 | 245 | const Post = () => ( 246 |
247 | 248 |
249 | ); 250 | 251 | export default Post; 252 | ``` 253 | 254 | You can also pass these styles through the **Output** component. 255 | In this case, the style prop must be an object whose keys correspond to the names of the supported blocks you intend to style. 256 | The following example highlights the current possible nestings and keys for the supported block. 257 | 258 | **NB** If you prefer classes, remember the keys are the same but the values must be class names (strings NOT objects) and the prop name should be classNames 259 | 260 | ```javascript 261 | // All valid JSX inline styles are allowed 262 | const style = { 263 | paragraph: {...}, 264 | header: { 265 | h1: {...}, 266 | h2: {...}, 267 | h3: {...}, 268 | h4: {...}, 269 | h5: {...}, 270 | h6: {...}, 271 | }, 272 | image: { 273 | img: {...}, 274 | figure: {...}, 275 | figcaption: {...} 276 | }, 277 | video: { 278 | video: {...}, 279 | figure: {...}, 280 | figcaption: {...} 281 | }, 282 | embed: { 283 | video: {...}, 284 | figure: {...}, 285 | figcaption: {...} 286 | }, 287 | list: { 288 | container: {...}, 289 | listItem: {...}, 290 | }, 291 | checklist: { 292 | container: {...}, 293 | item: {...}, 294 | checkbox: {...}, 295 | label: {...}, 296 | }, 297 | table: { 298 | table: {...}, 299 | tr: {...}, 300 | th: {...}, 301 | td: {...}, 302 | }, 303 | quote: { 304 | container: {...}, 305 | content: {...}, 306 | author: {...}, 307 | message: {...} 308 | }, 309 | codeBox: { 310 | container: {...}, 311 | code: {...}, 312 | }, 313 | warning: { 314 | container: {...}, 315 | icon: {...}, 316 | title: {...}, 317 | message: {...}, 318 | }, 319 | delimiter: { 320 | container: {...}, 321 | svg: {...}, 322 | path: {...} 323 | }, 324 | personality: { 325 | container: {...}, 326 | textHolder: {...}, 327 | name: {...}, 328 | description: {...}, 329 | photo: {...}, 330 | link: {...} 331 | }, 332 | linkTool: { 333 | container: {...}, 334 | textHolder: {...}, 335 | title: {...}, 336 | description: {...}, 337 | image: {...}, 338 | siteName: {...} 339 | }, 340 | }; 341 | 342 | const Post = () =>
; 343 | 344 | export default Post; 345 | ``` 346 | 347 | 348 | ## Config 349 | 350 | All renderers accept a **config** object parameter. If you wish to disable a default styles and only apply your own, you can pass a **disableDefaultStyle** value of **true** to the element's config options 351 | 352 | ```javascript 353 | const config = { 354 | header: { 355 | disableDefaultStyle: true, 356 | }, 357 | image: { 358 | disableDefaultStyle: true, 359 | }, 360 | video: { 361 | disableDefaultStyle: true, 362 | }, 363 | }; 364 | 365 | const Post = () =>
; 366 | 367 | export default Post; 368 | ``` 369 | 370 | 371 | ## Server Side Rendering 372 | 373 | SSR was broken in V3 to reduce bundle size. 374 | This package can only be loaded client-side. 375 | 376 | In nextjs you can use dynamic imports to only load the renderers on the client. 377 | 378 | ```javascript 379 | import dynamic from 'next/dynamic'; 380 | 381 | const Output = dynamic( 382 | async () => (await import('editorjs-react-renderer')).default, 383 | { ssr: false } 384 | ); 385 | ``` 386 | 387 | Note that dynamic imports only work with nextjs 12.0 and above. If you are using a lower version you might need another solution. e.g only import inside useEffect hook. 388 | 389 | 390 | ## API 391 | 392 | * Output(data[,style, config, classNames, renderers]) 393 | * CodeBoxOutput(data[,style, config, classNames]) 394 | * HeaderOutput(data[,style, config, classNames]) 395 | * ParagraphOutput(data[,style, config, classNames]) 396 | * TableOutput(data[,style, config, classNames]) 397 | * ImageOutput(data[,style, config, classNames]) 398 | * VideoOutput(data[,style, config, classNames]) 399 | * EmbedOutput(data[,style, config, classNames]) 400 | * ListOutput(data[,style, config, classNames]) 401 | * ChecklistOutput(data[,style, config, classNames]) 402 | * QuoteOutput(data[,style, config, classNames]) 403 | * WarningOutput(data[,style, config, classNames]) 404 | * DelimiterOutput([,style, config, classNames]) 405 | * LinkToolOutput([,style, config, classNames]) 406 | * PersonalityOutput([,style, config, classNames]) 407 | 408 | 409 | ## Supported blocks 410 | * [CodeBox](https://github.com/BomdiZane/codebox) 411 | * [Header](https://github.com/editor-js/header) 412 | * [Paragraph](https://github.com/editor-js/paragraph) 413 | * [Image](https://github.com/editor-js/image) 414 | * [Video](https://github.com/weekwood/editorjs-video) 415 | * [Simple Video](https://github.com/PaulKinlan/simple-video) 416 | * [Embed](https://github.com/editor-js/embed) 417 | * [List](https://github.com/editor-js/list) 418 | * [Checklist](https://github.com/editor-js/checklist) 419 | * [Table](https://github.com/editor-js/table) 420 | * [Quote](https://github.com/editor-js/quote) 421 | * [Warning](https://github.com/editor-js/warning) 422 | * [Delimiter](https://github.com/editor-js/delimiter) 423 | * [Personality](https://github.com/editor-js/personality) 424 | * [Link](https://github.com/editor-js/link) 425 | 426 | There's more coming... 427 | 428 | 429 | ## Author 430 | 431 | Dev Juju 432 | 433 | [Contact Us](https://bomdisoft.com) 434 | 435 | [Learn](https://devjuju.com) 436 | -------------------------------------------------------------------------------- /renderers/checklist.tsx: -------------------------------------------------------------------------------- 1 | /** ChecklistOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2020.05.25 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.07.17 - Add config parameter 10 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 11 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 12 | * @version 1.1.2 - 2022.04.20 - fix console errors (make input readOnly) 13 | * @version 1.1.3 - 2022.11.26 - Redefine types 14 | */ 15 | 16 | //#region imports 17 | import React from 'react'; 18 | import parse from 'html-react-parser'; 19 | import type { CSSProperties } from 'react'; 20 | //#endregion 21 | 22 | /********************************************** GLOBALS ******************************************/ 23 | 24 | const supportedKeys = ['container', 'item', 'checkbox', 'label']; 25 | 26 | const defaultStyle: {[key: string]: CSSProperties} = { 27 | container: { 28 | margin: '5px 0', 29 | padding: 0, 30 | listStyle: 'none', 31 | width: '100%', 32 | maxWidth: '320px', 33 | }, 34 | item: { 35 | display: 'flex', 36 | justifyContent: 'flex-start', 37 | alignItems: 'center' 38 | }, 39 | checkbox: { 40 | height: '17px', 41 | width: '17px', 42 | outline: 'none', 43 | display: 'inline-block', 44 | verticalAlign: 'top', 45 | position: 'relative', 46 | margin: 0, 47 | marginRight: '5px', 48 | cursor: 'pointer', 49 | border: '1px solid var(--bc, var(--border))', 50 | background: 'var(--b, var(--background))', 51 | transition: 'background .3s, border-color .3s, box-shadow .2s', 52 | }, 53 | label: { 54 | fontSize: '14px', 55 | lineHeight: '21px', 56 | display: 'inline-block', 57 | verticalAlign: 'top', 58 | cursor: 'pointer', 59 | marginLeft: '4px', 60 | }, 61 | }; 62 | 63 | 64 | /********************************************** TYPES ******************************************/ 65 | 66 | type ChecklistOutputItemData = { 67 | text: string 68 | checked: boolean 69 | } 70 | 71 | type ChecklistOutputData = { 72 | items: ChecklistOutputItemData[] 73 | } 74 | 75 | type ChecklistOutputClassNames = { 76 | container?: string 77 | item?: string 78 | checkbox?: string 79 | label?: string 80 | } 81 | 82 | type ChecklistOutputStyles = { 83 | container?: CSSProperties 84 | item?: CSSProperties 85 | checkbox?: CSSProperties 86 | label?: CSSProperties 87 | } 88 | 89 | type ChecklistOutputProps = { 90 | data: ChecklistOutputData 91 | style?: ChecklistOutputStyles 92 | classNames?: ChecklistOutputClassNames 93 | config?: ErrConfig 94 | } 95 | 96 | 97 | /********************************************** FUNCTIONS ******************************************/ 98 | 99 | const ChecklistOutput = ({ data, style, classNames, config }: ChecklistOutputProps): JSX.Element => { 100 | if (!data || !data.items || !Array.isArray(data.items) || data.items.length < 1) return <>; 101 | if (!style || typeof style !== 'object') style = {}; 102 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 103 | if (!classNames || typeof classNames !== 'object') classNames = {}; 104 | 105 | supportedKeys.forEach(key => { 106 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 107 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 108 | }); 109 | 110 | const containerStyle = config.disableDefaultStyle ? style.container : { ...defaultStyle.container, ...style.container }; 111 | const itemStyle = config.disableDefaultStyle ? style.item : { ...defaultStyle.item, ...style.item }; 112 | const checkboxStyle = config.disableDefaultStyle ? style.checkbox : { ...defaultStyle.checkbox, ...style.checkbox }; 113 | const labelStyle = config.disableDefaultStyle ? style.label : { ...defaultStyle.label, ...style.label }; 114 | 115 | const content = data.items.map((item, index) => 116 |
117 | 118 | 119 |
120 | ); 121 | 122 | return
    { content }
; 123 | }; 124 | 125 | export default ChecklistOutput; 126 | -------------------------------------------------------------------------------- /renderers/codeBox.tsx: -------------------------------------------------------------------------------- 1 | /** CodeBoxOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2020.02.12 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.07.17 - Add config parameter 10 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 11 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 12 | * @version 1.1.2 - 2022.11.26 - Redefine types 13 | */ 14 | 15 | //#region imports 16 | import React, { createRef, useEffect, useCallback } from 'react'; 17 | import type { CSSProperties } from 'react'; 18 | import parse from 'html-react-parser'; 19 | //#endregion 20 | 21 | /********************************************** GLOBALS ******************************************/ 22 | 23 | const supportedKeys = ['container', 'code']; 24 | 25 | const injectHighlightJSScriptElement = () => { 26 | const highlightJSScriptURL = 'https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.18.1/build/highlight.min.js'; 27 | const highlightJSScriptElements = document.querySelectorAll('script'); 28 | let isAlreadyIncluded = false; 29 | 30 | for (let i = 0; i < highlightJSScriptElements.length; i++) { 31 | if (highlightJSScriptElements[i].src.includes('highlight.min.js')) { 32 | isAlreadyIncluded = true; 33 | break; 34 | } 35 | } 36 | if (!isAlreadyIncluded) { 37 | const script = document.createElement('script'); 38 | const head = document.querySelector('head'); 39 | script.setAttribute('src', highlightJSScriptURL); 40 | 41 | if (head) head.appendChild(script); 42 | } 43 | }; 44 | 45 | const injectHighlightJSCSSElement = highlightJSCSSURL => { 46 | if (!highlightJSCSSURL || typeof highlightJSCSSURL !== 'string') return; 47 | 48 | const highlightJSCSSElements = document.querySelectorAll('link'); 49 | let isAlreadyIncluded = false; 50 | 51 | for (let i = 0; i < highlightJSCSSElements.length; i++) { 52 | if (highlightJSCSSElements[i].href === highlightJSCSSURL) { 53 | isAlreadyIncluded = true; 54 | break; 55 | } 56 | } 57 | if (!isAlreadyIncluded) { 58 | const link = document.createElement('link'); 59 | const head = document.querySelector('head'); 60 | link.setAttribute('rel', 'stylesheet'); 61 | link.setAttribute('href', highlightJSCSSURL); 62 | 63 | if (head) head.appendChild(link); 64 | } 65 | }; 66 | 67 | const defaultStyle: {[key: string]: CSSProperties} = { 68 | container: { 69 | width: '100%', 70 | }, 71 | code: { 72 | width: '100%', 73 | minHeight: '30px', 74 | boxSizing: 'border-box', 75 | textAlign: 'left', 76 | margin: '8px 0', 77 | marginTop: '15px', 78 | padding: '10px', 79 | borderRadius: '2px 2px 2px 0', 80 | border: 'none !important', 81 | outline: 'none !important', 82 | fontSize: '14px', 83 | } 84 | }; 85 | 86 | 87 | /********************************************** TYPES ******************************************/ 88 | 89 | type CodeBoxOutputData = { 90 | code: string 91 | theme?: string 92 | language?: string 93 | } 94 | 95 | type CodeBoxOutputClassNames = { 96 | container?: string 97 | code?: string 98 | } 99 | 100 | type CodeBoxOutputStyles = { 101 | container?: CSSProperties 102 | code?: CSSProperties 103 | } 104 | 105 | type CodeBoxOutputProps = { 106 | data: CodeBoxOutputData 107 | style?: CodeBoxOutputStyles 108 | classNames?: CodeBoxOutputClassNames 109 | config?: ErrConfig 110 | } 111 | 112 | 113 | /********************************************** FUNCTIONS ******************************************/ 114 | 115 | const CodeBoxOutput = ({ data, style, classNames, config }: CodeBoxOutputProps): JSX.Element => { 116 | if (!style || typeof style !== 'object') style = {}; 117 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 118 | if (!classNames || typeof classNames !== 'object') classNames = {}; 119 | 120 | supportedKeys.forEach(key => { 121 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 122 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 123 | }); 124 | 125 | const codeAreaRef = createRef(); 126 | const highlightBlock = useCallback(() => { 127 | if (typeof (window as any).hljs !== 'undefined') (window as any).hljs.highlightBlock(codeAreaRef.current); 128 | else setTimeout(highlightBlock, 250); 129 | }, []); 130 | 131 | useEffect(() => { 132 | if (data && data.theme && codeAreaRef.current) { 133 | injectHighlightJSCSSElement(data.theme); 134 | injectHighlightJSScriptElement(); 135 | highlightBlock(); 136 | } 137 | }, []); 138 | 139 | if (!data || !data.code || typeof data.code != 'string') return <>; 140 | const containerStyle = config.disableDefaultStyle ? style.container : { ...defaultStyle.container, ...style.container }; 141 | const codeStyle = config.disableDefaultStyle ? style.code : { ...defaultStyle.code, ...style.code }; 142 | 143 | const language = data.language && typeof data.language === 'string' ? data.language : null; 144 | 145 | return ( 146 |
147 |       { parse(data.code) }
148 |     
149 | ); 150 | }; 151 | 152 | export default CodeBoxOutput; 153 | -------------------------------------------------------------------------------- /renderers/delimiter.tsx: -------------------------------------------------------------------------------- 1 | /** DelimiterOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2019.11.30 5 | * @author - Tomáš Hylský (https://linktr.ee/thylsky) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.02.12 - Covert to React component 10 | * @version 1.0.2 - 2020.02.13 - Use SVG stars as delimiter 11 | * @version 1.0.3 - 2020.07.17 - Add config parameter 12 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 13 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 14 | * @version 1.1.2 - 2022.11.26 - Redefine types 15 | */ 16 | 17 | //#region imports 18 | import React from 'react'; 19 | import type { CSSProperties } from 'react'; 20 | //#endregion 21 | 22 | /********************************************** GLOBALS ******************************************/ 23 | 24 | const supportedKeys = ['container', 'svg', 'path']; 25 | 26 | const defaultStyle: {[key: string]: CSSProperties} = { 27 | container: { 28 | width: '100%', 29 | margin: '8px 0', 30 | textAlign: 'center', 31 | display: 'flex', 32 | justifyContent: 'center', 33 | alignItems: 'center', 34 | enableBackground: 'new 0 0 100.353 100.353' 35 | } as any, 36 | svg: { 37 | width: '20px', 38 | height: '20px', 39 | margin: '5px', 40 | }, 41 | path: { 42 | fill: '#231F20' 43 | } 44 | }; 45 | 46 | 47 | /********************************************** TYPES ******************************************/ 48 | 49 | type DelimiterOutputClassNames = { 50 | container?: string 51 | svg?: string 52 | path?: string 53 | } 54 | 55 | type DelimiterOutputStyles = { 56 | container?: CSSProperties 57 | svg?: CSSProperties 58 | path?: CSSProperties 59 | } 60 | 61 | type DelimiterOutputProps = { 62 | style?: DelimiterOutputStyles 63 | classNames?: DelimiterOutputClassNames 64 | config?: ErrConfig 65 | } 66 | 67 | 68 | /********************************************** FUNCTIONS ******************************************/ 69 | 70 | const DelimiterOutput = ({ style, classNames, config }: DelimiterOutputProps): JSX.Element => { 71 | if (!style || typeof style !== 'object') style = {}; 72 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 73 | if (!classNames || typeof classNames !== 'object') classNames = {}; 74 | 75 | supportedKeys.forEach(key => { 76 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 77 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 78 | }); 79 | 80 | const containerStyle = config.disableDefaultStyle ? style.container : { ...defaultStyle.container, ...style.container }; 81 | const svgStyle = config.disableDefaultStyle ? style.svg : { ...defaultStyle.svg, ...style.svg }; 82 | const pathStyle = config.disableDefaultStyle ? style.path : { ...defaultStyle.path, ...style.path }; 83 | 84 | return ( 85 |
86 | 88 | 94 | 95 | 97 | 103 | 104 | 106 | 112 | 113 |
114 | ); 115 | }; 116 | 117 | export default DelimiterOutput; 118 | -------------------------------------------------------------------------------- /renderers/embed.tsx: -------------------------------------------------------------------------------- 1 | /** EmbedOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2020.05.25 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.07.17 - Add config parameter 10 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 11 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 12 | * @version 1.1.2 - 2022.11.26 - Redefine types 13 | * 14 | */ 15 | 16 | //#region imports 17 | import React from 'react'; 18 | import parse from 'html-react-parser'; 19 | import type { CSSProperties } from 'react'; 20 | //#endregion 21 | 22 | /********************************************** GLOBALS ******************************************/ 23 | 24 | const supportedKeys = ['video', 'figure', 'figcaption']; 25 | 26 | const defaultStyle: {[key: string]: CSSProperties} = { 27 | iframeStyle: { 28 | maxWidth: '100%', 29 | width: '100%', 30 | height: '400px', 31 | maxHeight: '400px', 32 | borderRadius: '5px', 33 | boxShadow: 'none', 34 | outline: 'none', 35 | border: 'none', 36 | }, 37 | figureStyle: { 38 | display: 'flex', 39 | flexDirection: 'column', 40 | justifyContent: 'center', 41 | alignItems: 'center', 42 | margin: '20px 0', 43 | width: '100%', 44 | maxWidth: '100%', 45 | height: '400px', 46 | maxHeight: '400px', 47 | overflow: 'hidden', 48 | }, 49 | figcaptionStyle: { 50 | padding: '5px 10px', 51 | fontSize: '12px', 52 | borderRadius: '2px', 53 | cursor: 'default', 54 | } 55 | }; 56 | 57 | 58 | /********************************************** TYPES ******************************************/ 59 | 60 | type EmbedOutputData = { 61 | embed: string 62 | width?: number 63 | height?: number 64 | caption?: string 65 | } 66 | 67 | type EmbedOutputClassNames = { 68 | video?: string 69 | figure?: string 70 | figcaption?: string 71 | } 72 | 73 | type EmbedOutputStyles = { 74 | video?: CSSProperties 75 | figure?: CSSProperties 76 | figcaption?: CSSProperties 77 | } 78 | 79 | type EmbedOutputProps = { 80 | data: EmbedOutputData 81 | style?: EmbedOutputStyles 82 | classNames?: EmbedOutputClassNames 83 | config?: ErrConfig 84 | } 85 | 86 | 87 | /********************************************** FUNCTIONS ******************************************/ 88 | 89 | const EmbedOutput = ({ data, style, classNames, config }: EmbedOutputProps): JSX.Element => { 90 | if (!data || !data.embed) return <>; 91 | if (!style || typeof style !== 'object') style = {}; 92 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 93 | if (!classNames || typeof classNames !== 'object') classNames = {}; 94 | 95 | supportedKeys.forEach(key => { 96 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 97 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 98 | }); 99 | 100 | const iframeStyle = config.disableDefaultStyle ? style.video : { ...defaultStyle.iframeStyle, ...style.video }; 101 | 102 | if (data.width) iframeStyle['width'] = data.width; 103 | if (data.height) iframeStyle['height'] = data.height; 104 | 105 | const figureStyle = config.disableDefaultStyle ? style.figure : { ...defaultStyle.figureStyle, ...style.figure }; 106 | const figcaptionStyle = config.disableDefaultStyle ? style.figcaption : { ...defaultStyle.figcaptionStyle, ...style.figcaption }; 107 | 108 | return ( 109 |
110 | 111 | { data.caption &&
{ parse(data.caption) }
} 112 |
113 | ); 114 | }; 115 | 116 | export default EmbedOutput; 117 | -------------------------------------------------------------------------------- /renderers/header.tsx: -------------------------------------------------------------------------------- 1 | /** HeaderOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2019.08.20 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.02.12 - Covert to React component 10 | * @version 1.0.2 - 2020.07.17 - Add config parameter 11 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 12 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 13 | * @version 1.2.0 - 2022.04.20 - Add support for applying different styles/classes to each header level 14 | * @version 1.2.1 - 2022.11.26 - Redefine types 15 | */ 16 | 17 | //#region imports 18 | import React from 'react'; 19 | import parse from 'html-react-parser'; 20 | import type { CSSProperties } from 'react'; 21 | //#endregion 22 | 23 | /********************************************** GLOBALS ******************************************/ 24 | 25 | const supportedKeys = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']; 26 | 27 | const defaultStyle: CSSProperties = { 28 | margin: '8px 0', 29 | marginTop: '15px', 30 | }; 31 | 32 | 33 | /********************************************** TYPES ******************************************/ 34 | 35 | type HeaderOutputData = { 36 | text: string 37 | level?: 1 | 2 | 3 | 4 | 5 | 6 38 | } 39 | 40 | type HeaderOutputClassNames = { 41 | h1?: string 42 | h2?: string 43 | h3?: string 44 | h4?: string 45 | h5?: string 46 | h6?: string 47 | } 48 | 49 | type HeaderOutputStyles = { 50 | h1?: CSSProperties 51 | h2?: CSSProperties 52 | h3?: CSSProperties 53 | h4?: CSSProperties 54 | h5?: CSSProperties 55 | h6?: CSSProperties 56 | } 57 | 58 | type HeaderOutputProps = { 59 | data: HeaderOutputData 60 | style?: HeaderOutputStyles 61 | classNames?: HeaderOutputClassNames 62 | config?: ErrConfig 63 | } 64 | 65 | 66 | /********************************************** FUNCTIONS ******************************************/ 67 | 68 | const HeaderOutput = ({ data, style, classNames, config }: HeaderOutputProps): JSX.Element => { 69 | if (!data || !data.text || typeof data.text != 'string') return <>; 70 | if (!style || typeof style !== 'object') style = {}; 71 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 72 | if (!classNames || typeof classNames !== 'object') classNames = {}; 73 | 74 | supportedKeys.forEach(key => { 75 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 76 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 77 | }); 78 | 79 | const h1Style = config.disableDefaultStyle ? style.h1 : { ...defaultStyle, ...style.h1 }; 80 | const h2Style = config.disableDefaultStyle ? style.h2 : { ...defaultStyle, ...style.h2 }; 81 | const h3Style = config.disableDefaultStyle ? style.h3 : { ...defaultStyle, ...style.h3 }; 82 | const h4Style = config.disableDefaultStyle ? style.h4 : { ...defaultStyle, ...style.h4 }; 83 | const h5Style = config.disableDefaultStyle ? style.h5 : { ...defaultStyle, ...style.h5 }; 84 | const h6Style = config.disableDefaultStyle ? style.h6 : { ...defaultStyle, ...style.h6 }; 85 | 86 | switch (data.level) { 87 | case 1: return

{ parse(data.text) }

; 88 | case 2: return

{ parse(data.text) }

; 89 | case 3: return

{ parse(data.text) }

; 90 | case 4: return

{ parse(data.text) }

; 91 | case 5: return
{ parse(data.text) }
; 92 | case 6: return
{ parse(data.text) }
; 93 | default: return

{ parse(data.text) }

; 94 | } 95 | }; 96 | 97 | export default HeaderOutput; 98 | -------------------------------------------------------------------------------- /renderers/image.tsx: -------------------------------------------------------------------------------- 1 | /** ImageOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2019.08.20 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.02.12 - Covert to React component 10 | * @version 1.0.2 - 2020.05.21 - Codex width overrides user defined width 11 | * @version 1.0.3 - 2020.07.17 - Add config parameter 12 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 13 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 14 | * @version 1.1.2 - 2022.11.26 - Redefine types 15 | */ 16 | 17 | //#region imports 18 | import React from 'react'; 19 | import parse from 'html-react-parser'; 20 | import type { CSSProperties } from 'react'; 21 | //#endregion 22 | 23 | /********************************************** GLOBALS ******************************************/ 24 | 25 | const supportedKeys = ['img', 'figure', 'figcaption']; 26 | 27 | const defaultStyle: {[key: string]: CSSProperties} = { 28 | image: { 29 | maxWidth: '100%', 30 | maxHeight: '400px', 31 | }, 32 | figure: { 33 | position: 'relative', 34 | display: 'flex', 35 | flexDirection: 'column', 36 | justifyContent: 'center', 37 | alignItems: 'center', 38 | margin: '20px 0', 39 | width: '100%', 40 | maxWidth: '100%', 41 | maxHeight: '400px', 42 | overflow: 'hidden', 43 | backgroundColor: 'aliceblue', 44 | border: '1px solid #eee' 45 | }, 46 | figcaption: { 47 | position: 'absolute', 48 | top: '8px', 49 | right: '8px', 50 | padding: '5px 10px', 51 | fontSize: '12px', 52 | backgroundColor: '#2d333a', 53 | color: 'white', 54 | borderRadius: '2px', 55 | cursor: 'default', 56 | } 57 | }; 58 | 59 | 60 | /********************************************** TYPES ******************************************/ 61 | 62 | type ImageOutputData = { 63 | file: { url: string } 64 | caption?: string 65 | stretched?: boolean 66 | withBorder?: boolean 67 | withBackground?: boolean 68 | } 69 | 70 | type ImageOutputClassNames = { 71 | img?: string 72 | figure?: string 73 | figcaption?: string 74 | } 75 | 76 | type ImageOutputStyles = { 77 | img?: CSSProperties 78 | figure?: CSSProperties 79 | figcaption?: CSSProperties 80 | } 81 | 82 | type ImageOutputProps = { 83 | data: ImageOutputData 84 | style?: ImageOutputStyles 85 | classNames?: ImageOutputClassNames 86 | config?: ErrConfig 87 | } 88 | 89 | 90 | /********************************************** FUNCTIONS ******************************************/ 91 | 92 | const ImageOutput = ({ data, style, classNames, config }: ImageOutputProps): JSX.Element => { 93 | if (!data || !data.file || !data.file.url) return <>; 94 | if (!style || typeof style !== 'object') style = {}; 95 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 96 | if (!classNames || typeof classNames !== 'object') classNames = {}; 97 | 98 | supportedKeys.forEach(key => { 99 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 100 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 101 | }); 102 | 103 | const imageStyle = config.disableDefaultStyle ? style.img : { ...defaultStyle.image, ...style.img }; 104 | imageStyle['width'] = data.stretched ? '100%' : ''; 105 | 106 | const figureStyle = config.disableDefaultStyle ? style.figure : { ...defaultStyle.figure, ...style.figure }; 107 | if (!data.withBorder) figureStyle['border'] = 'none'; 108 | if (!data.withBackground) figureStyle['backgroundColor'] = 'none'; 109 | 110 | const figcaptionStyle = config.disableDefaultStyle ? style.figcaption : { ...defaultStyle.figcaption, ...style.figcaption }; 111 | 112 | return ( 113 |
114 | { 115 | { data.caption &&
{ parse(data.caption) }
} 116 |
117 | ); 118 | }; 119 | 120 | export default ImageOutput; 121 | -------------------------------------------------------------------------------- /renderers/linkTool.tsx: -------------------------------------------------------------------------------- 1 | /** LinkToolOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2022.05.19 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2022.08.14 - image metadata is optional 10 | * @version 1.1.2 - 2022.11.26 - Redefine types 11 | * 12 | */ 13 | 14 | //#region imports 15 | import React from 'react'; 16 | import parse from 'html-react-parser'; 17 | import type { CSSProperties } from 'react'; 18 | //#endregion 19 | 20 | /********************************************** GLOBALS ******************************************/ 21 | 22 | const supportedKeys = ['container', 'textHolder', 'title', 'description', 'image', 'siteName']; 23 | 24 | const defaultStyle: {[key: string]: CSSProperties} = { 25 | container: { 26 | display: 'flex', 27 | justifyContent: 'space-between', 28 | alignItems: 'flex-end', 29 | width: '100%', 30 | minWidth: '280px', 31 | flexWrap: 'wrap-reverse', 32 | border: '1px solid #eee', 33 | boxShadow: '0px 1px 3px 0px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 2px 1px -1px rgba(0,0,0,0.12)', 34 | borderRadius: '4px', 35 | cursor: 'pointer' 36 | }, 37 | textHolder: { 38 | display: 'flex', 39 | flexDirection: 'column', 40 | justifyContent: 'flex-start', 41 | alignItems: 'flex-start', 42 | width: '80%', 43 | padding: '12px 20px' 44 | }, 45 | title: { 46 | fontSize: '18px', 47 | fontWeight: 'bold', 48 | margin: 0, 49 | cursor: 'pointer' 50 | }, 51 | description: { 52 | textAlign: 'left', 53 | lineHeight: '1.7', 54 | fontWeight: 200, 55 | fontSize: '15px', 56 | cursor: 'pointer' 57 | }, 58 | image: { 59 | width: '15%', 60 | borderRadius: '4px', 61 | cursor: 'pointer', 62 | flexGrow: 1 63 | }, 64 | siteName: { 65 | color: 'grey', 66 | cursor: 'pointer', 67 | margin: 0, 68 | fontSize: '12px', 69 | }, 70 | }; 71 | 72 | 73 | /********************************************** TYPES ******************************************/ 74 | 75 | type LinkToolOutputData = { 76 | link: string 77 | meta?: { 78 | title?: string 79 | description?: string 80 | site_name?: string 81 | image?: { url: string } 82 | } 83 | } 84 | 85 | type LinkToolOutputClassNames = { 86 | container?: string 87 | textHolder?: string 88 | title?: string 89 | description?: string 90 | image?: string 91 | siteName?: string 92 | } 93 | 94 | type LinkToolOutputStyles = { 95 | container?: CSSProperties 96 | textHolder?: CSSProperties 97 | title?: CSSProperties 98 | description?: CSSProperties 99 | image?: CSSProperties 100 | siteName?: CSSProperties 101 | } 102 | 103 | type LinkToolOutputProps = { 104 | data: LinkToolOutputData 105 | style?: LinkToolOutputStyles 106 | classNames?: LinkToolOutputClassNames 107 | config?: ErrConfig 108 | } 109 | 110 | 111 | /********************************************** FUNCTIONS ******************************************/ 112 | 113 | const LinkToolOutput = ({ data, style, classNames, config }: LinkToolOutputProps): JSX.Element => { 114 | if (!data || !data.link) return <>; 115 | if (!style || typeof style !== 'object') style = {}; 116 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 117 | if (!classNames || typeof classNames !== 'object') classNames = {}; 118 | 119 | supportedKeys.forEach(key => { 120 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 121 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 122 | }); 123 | 124 | const containerStyle = config.disableDefaultStyle ? style.container : { ...defaultStyle.container, ...style.container }; 125 | const textHolderStyle = config.disableDefaultStyle ? style.textHolder : { ...defaultStyle.textHolder, ...style.textHolder }; 126 | const titleStyle = config.disableDefaultStyle ? style.title : { ...defaultStyle.title, ...style.title }; 127 | const descriptionStyle = config.disableDefaultStyle ? style.description : { ...defaultStyle.description, ...style.description }; 128 | const siteNameStyle = config.disableDefaultStyle ? style.siteName : { ...defaultStyle.siteName, ...style.siteName }; 129 | const imageStyle = config.disableDefaultStyle ? style.image : { ...defaultStyle.image, ...style.image }; 130 | 131 | const handleClick = () => { 132 | let win = window.open(data.link, '_blank'); 133 | win?.focus(); 134 | }; 135 | 136 | return ( 137 |
138 |
139 | { data.meta?.title &&

{ parse(data.meta?.title) }

} 140 | { data.meta?.description &&

{ parse(data.meta?.description) }

} 141 | { data.meta?.site_name &&

{ parse(data.meta?.site_name) }

} 142 |
143 | { data.meta?.image?.url && image of link } 144 |
145 | ); 146 | }; 147 | 148 | export default LinkToolOutput; 149 | -------------------------------------------------------------------------------- /renderers/list.tsx: -------------------------------------------------------------------------------- 1 | /** ListOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2019.08.20 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.02.12 - Covert to React component 10 | * @version 1.0.2 - 2020.07.17 - Add config parameter 11 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 12 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 13 | * @version 1.1.2 - 2022.11.26 - Redefine types 14 | */ 15 | 16 | //#region imports 17 | import React from 'react'; 18 | import parse from 'html-react-parser'; 19 | import type { CSSProperties } from 'react'; 20 | //#endregion 21 | 22 | /********************************************** GLOBALS ******************************************/ 23 | 24 | const validListStyles = ['ordered', 'unordered']; 25 | const supportedKeys = ['container', 'listItem']; 26 | 27 | const defaultStyle: {[key: string]: CSSProperties} = { 28 | container: { 29 | margin: '5px 0', 30 | }, 31 | }; 32 | 33 | 34 | /********************************************** TYPES ******************************************/ 35 | 36 | type ListOutputData = { 37 | items: string[] 38 | style?: 'ordered' | 'unordered' 39 | } 40 | 41 | type ListOutputClassNames = { 42 | container?: string 43 | listItem?: string 44 | } 45 | 46 | type ListOutputStyles = { 47 | container?: CSSProperties 48 | listItem?: CSSProperties 49 | } 50 | 51 | type ListOutputProps = { 52 | data: ListOutputData 53 | style?: ListOutputStyles 54 | classNames?: ListOutputClassNames 55 | config?: ErrConfig 56 | } 57 | 58 | 59 | /********************************************** FUNCTIONS ******************************************/ 60 | 61 | const ListOutput = ({ data, style, classNames, config }: ListOutputProps): JSX.Element => { 62 | if (!data || !data.items || !Array.isArray(data.items)) return <>; 63 | if (!style || typeof style !== 'object') style = {}; 64 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 65 | if (!classNames || typeof classNames !== 'object') classNames = {}; 66 | 67 | supportedKeys.forEach(key => { 68 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 69 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 70 | }); 71 | 72 | const containerStyle = config.disableDefaultStyle ? style.container : { ...defaultStyle.container, ...style.container }; 73 | const listItemStyle = config.disableDefaultStyle ? style.listItem : { ...defaultStyle.listItem, ...style.listItem }; 74 | 75 | const listType = validListStyles.includes(data.style) ? data.style : 'unordered'; 76 | const content = data.items.map((item, index) =>
  • { parse(item) }
  • ); 77 | 78 | if (content.length <= 0) return <>; 79 | if (listType === 'ordered') return
      { content }
    ; 80 | 81 | return
      { content }
    ; 82 | }; 83 | 84 | export default ListOutput; 85 | -------------------------------------------------------------------------------- /renderers/paragraph.tsx: -------------------------------------------------------------------------------- 1 | /** ParagraphOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2019.08.20 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.02.12 - Covert to React component 10 | * @version 1.0.2 - 2020.07.17 - Add config parameter 11 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 12 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 13 | * @version 1.1.2 - 2022.11.26 - Redefine types 14 | */ 15 | 16 | //#region imports 17 | import React from 'react'; 18 | import parse from 'html-react-parser'; 19 | import type { CSSProperties } from 'react'; 20 | //#endregion 21 | 22 | /********************************************** GLOBALS ******************************************/ 23 | 24 | const defaultStyle: CSSProperties = { 25 | margin: '5px 0', 26 | textAlign: 'left', 27 | }; 28 | 29 | /********************************************** TYPES ******************************************/ 30 | 31 | type ParagraphOutputData = { 32 | text: string 33 | } 34 | 35 | type ParagraphOutputProps = { 36 | data: string | ParagraphOutputData 37 | style?: CSSProperties 38 | classNames?: string 39 | config?: ErrConfig 40 | } 41 | 42 | 43 | /********************************************** FUNCTIONS ******************************************/ 44 | 45 | const ParagraphOutput = ({ data, style, classNames, config }: ParagraphOutputProps): JSX.Element => { 46 | if (!data) return <>; 47 | if (!style || typeof style !== 'object') style = {}; 48 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 49 | 50 | const paragraphStyle = config.disableDefaultStyle ? style : { ...defaultStyle, ...style }; 51 | let content = null; 52 | 53 | if (typeof data === 'string') content = data; 54 | else if (typeof data === 'object' && data.text && typeof data.text === 'string') content = data.text; 55 | 56 | return content ?

    { parse(content) }

    : <>; 57 | }; 58 | 59 | export default ParagraphOutput; 60 | -------------------------------------------------------------------------------- /renderers/personality.tsx: -------------------------------------------------------------------------------- 1 | /** PersonalityOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2022.05.19 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2022.11.26 - Redefine types 10 | * 11 | */ 12 | 13 | //#region imports 14 | import React from 'react'; 15 | import parse from 'html-react-parser'; 16 | import type { CSSProperties } from 'react'; 17 | //#endregion 18 | 19 | /********************************************** GLOBALS ******************************************/ 20 | 21 | const supportedKeys = ['container', 'textHolder', 'name', 'description', 'photo', 'link']; 22 | 23 | const defaultStyle: {[key: string]: CSSProperties} = { 24 | container: { 25 | display: 'flex', 26 | justifyContent: 'space-between', 27 | alignItems: 'flex-end', 28 | width: '100%', 29 | minWidth: '280px', 30 | flexWrap: 'wrap-reverse', 31 | border: '1px solid #eee', 32 | boxShadow: '0px 1px 3px 0px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 2px 1px -1px rgba(0,0,0,0.12)', 33 | borderRadius: '4px', 34 | cursor: 'pointer' 35 | }, 36 | textHolder: { 37 | display: 'flex', 38 | flexDirection: 'column', 39 | justifyContent: 'flex-start', 40 | alignItems: 'flex-start', 41 | width: '80%', 42 | padding: '12px 20px' 43 | }, 44 | name: { 45 | fontSize: '18px', 46 | fontWeight: 'bold', 47 | cursor: 'pointer', 48 | margin: 0 49 | }, 50 | description: { 51 | textAlign: 'left', 52 | lineHeight: '1.7', 53 | cursor: 'pointer', 54 | fontWeight: 200, 55 | fontSize: '15px' 56 | }, 57 | photo: { 58 | width: '15%', 59 | borderRadius: '4px', 60 | flexGrow: 1 61 | }, 62 | link: { 63 | textDecoration: 'none', 64 | color: '#42A5F5', 65 | cursor: 'pointer', 66 | fontSize: '12px' 67 | }, 68 | }; 69 | 70 | 71 | /********************************************** TYPES ******************************************/ 72 | 73 | type PersonalityOutputData = { 74 | link: string 75 | name?: string 76 | description?: string 77 | photo?: string 78 | } 79 | 80 | type PersonalityOutputClassNames = { 81 | container?: string 82 | textHolder?: string 83 | description?: string 84 | name?: string 85 | link?: string 86 | photo?: string 87 | } 88 | 89 | type PersonalityOutputStyles = { 90 | container?: CSSProperties 91 | textHolder?: CSSProperties 92 | description?: CSSProperties 93 | name?: CSSProperties 94 | link?: CSSProperties 95 | photo?: CSSProperties 96 | } 97 | 98 | type PersonalityOutputProps = { 99 | data: PersonalityOutputData 100 | style?: PersonalityOutputStyles 101 | classNames?: PersonalityOutputClassNames 102 | config?: ErrConfig 103 | } 104 | 105 | 106 | /********************************************** FUNCTIONS ******************************************/ 107 | 108 | const PersonalityOutput = ({ data, style, classNames, config }: PersonalityOutputProps): JSX.Element => { 109 | if (!data || !data.link) return <>; 110 | if (!style || typeof style !== 'object') style = {}; 111 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 112 | if (!classNames || typeof classNames !== 'object') classNames = {}; 113 | 114 | supportedKeys.forEach(key => { 115 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 116 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 117 | }); 118 | 119 | const containerStyle = config.disableDefaultStyle ? style.container : { ...defaultStyle.container, ...style.container }; 120 | const textHolderStyle = config.disableDefaultStyle ? style.textHolder : { ...defaultStyle.textHolder, ...style.textHolder }; 121 | const nameStyle = config.disableDefaultStyle ? style.name : { ...defaultStyle.name, ...style.name }; 122 | const descriptionStyle = config.disableDefaultStyle ? style.description : { ...defaultStyle.description, ...style.description }; 123 | const linkStyle = config.disableDefaultStyle ? style.link : { ...defaultStyle.link, ...style.link }; 124 | const photoStyle = config.disableDefaultStyle ? style.photo : { ...defaultStyle.photo, ...style.photo }; 125 | 126 | const handleClick = () => { 127 | let win = window.open(data.link, '_blank'); 128 | win?.focus(); 129 | }; 130 | 131 | return ( 132 |
    133 |
    134 | { data.name &&

    { parse(data.name) }

    } 135 | { data.description &&

    { parse(data.description) }

    } 136 | { data.link } 137 |
    138 | { data.photo && image of person } 139 |
    140 | ); 141 | }; 142 | 143 | export default PersonalityOutput; 144 | -------------------------------------------------------------------------------- /renderers/quote.tsx: -------------------------------------------------------------------------------- 1 | /** QuoteOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2019.08.20 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.02.12 - Covert to React component 10 | * @version 1.0.2 - 2020.07.17 - Add config parameter 11 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 12 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 13 | * @version 1.1.3 - 2022.11.26 - Redefine types 14 | */ 15 | 16 | //#region imports 17 | import React from 'react'; 18 | import type { CSSProperties } from 'react'; 19 | import parse from 'html-react-parser'; 20 | //#endregion 21 | 22 | /********************************************** GLOBALS ******************************************/ 23 | 24 | const supportedKeys = ['container', 'content', 'author', 'message']; 25 | 26 | const defaultStyle: {[key: string]: CSSProperties} = { 27 | quote: { 28 | width: '100%', 29 | display: 'flex', 30 | justifyContent: 'center', 31 | alignItems: 'center', 32 | margin: '5px 0', 33 | textAlign: 'left', 34 | }, 35 | content: { 36 | minWidth: '240px', 37 | width: '80%', 38 | margin: '5px 0', 39 | padding: '10px', 40 | display: 'flex', 41 | flexDirection: 'column', 42 | justifyContent: 'space-between', 43 | alignItems: 'flex-start', 44 | border: '1px solid var(--primary-grey)', 45 | backgroundColor: 'var(--secondary-white)', 46 | borderRadius: 'var(--default-radius)', 47 | }, 48 | author: { 49 | fontWeight: 'bold', 50 | margin: '0 5px 5px 5px', 51 | }, 52 | }; 53 | 54 | 55 | /********************************************** TYPES ******************************************/ 56 | 57 | type QuoteOutputData = { 58 | text: string 59 | caption?: string 60 | alignment?: string 61 | } 62 | 63 | type QuoteOutputClassNames = { 64 | container?: string 65 | content?: string 66 | author?: string 67 | message?: string 68 | } 69 | 70 | type QuoteOutputStyles = { 71 | container?: CSSProperties 72 | content?: CSSProperties 73 | author?: CSSProperties 74 | message?: CSSProperties 75 | } 76 | 77 | type QuoteOutputProps = { 78 | data: QuoteOutputData 79 | style?: QuoteOutputStyles 80 | classNames?: QuoteOutputClassNames 81 | config?: ErrConfig 82 | } 83 | 84 | type QuoteProps = { 85 | author?: string 86 | message: string 87 | style: QuoteOutputStyles 88 | classNames: QuoteOutputClassNames 89 | config: ErrConfig 90 | } 91 | 92 | 93 | /********************************************** FUNCTIONS ******************************************/ 94 | 95 | const Quote = ({ author='Unknown', message, config, classNames, style }: QuoteProps): JSX.Element => { 96 | const containerStyle = config.disableDefaultStyle ? defaultStyle.quote : { ...defaultStyle.quote, ...style.container }; 97 | const contentStyle = config.disableDefaultStyle ? defaultStyle.contentStyle : { ...defaultStyle.contentStyle, ...style.content }; 98 | const messageStyle = config.disableDefaultStyle ? defaultStyle.messageStyle : { ...defaultStyle.messageStyle, ...style.message }; 99 | const authorStyle = config.disableDefaultStyle ? defaultStyle.author : { ...defaultStyle.author, ...style.author }; 100 | 101 | return ( 102 |
    103 | 104 |

    105 | "{ message }" 106 |

    107 |

    108 | { author } 109 |

    110 |
    111 |
    112 | ); 113 | }; 114 | 115 | const QuoteOutput = ({ data, style, classNames, config }: QuoteOutputProps): JSX.Element => { 116 | if (!data || !data.text || typeof data.text != 'string') return <>; 117 | if (!style || typeof style !== 'object') style = {}; 118 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 119 | if (!classNames || typeof classNames !== 'object') classNames = {}; 120 | 121 | supportedKeys.forEach(key => { 122 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 123 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 124 | }); 125 | 126 | const caption = data.caption && typeof data.caption === 'string' ? data.caption : 'Unknown'; 127 | if (data.alignment && typeof data.alignment === 'string') style['textAlign'] = data.alignment; 128 | 129 | return ; 131 | }; 132 | 133 | export default QuoteOutput; 134 | -------------------------------------------------------------------------------- /renderers/table.tsx: -------------------------------------------------------------------------------- 1 | /** TableOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2019.11.02 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.02.12 - Covert to React component 10 | * @version 1.0.2 - 2020.05.21 - Add key to list items 11 | * @version 1.0.3 - 2020.07.17 - Add config parameter 12 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 13 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 14 | * @version 1.1.2 - 2022.11.26 - Redefine types 15 | */ 16 | 17 | //#region imports 18 | import React from 'react'; 19 | import type { CSSProperties } from 'react'; 20 | import parse from 'html-react-parser'; 21 | //#endregion 22 | 23 | /********************************************** GLOBALS ******************************************/ 24 | 25 | const supportedKeys = ['table', 'tr', 'th', 'td']; 26 | 27 | const defaultStyle: {[key: string]: CSSProperties} = { 28 | table: { 29 | borderSpacing: '1px 2px', 30 | margin: '5px 0', 31 | }, 32 | th: { 33 | minWidth: '100px', 34 | padding: '8px 15px', 35 | borderRadius: '2px', 36 | backgroundColor: 'lightcoral', 37 | }, 38 | td: { 39 | minWidth: '100px', 40 | padding: '8px 15px', 41 | borderRadius: '2px', 42 | textAlign: 'left', 43 | }, 44 | }; 45 | 46 | 47 | /********************************************** TYPES ******************************************/ 48 | 49 | type TableOutputData = { 50 | content: string[][] 51 | } 52 | 53 | type TableOutputClassNames = { 54 | table?: string 55 | tr?: string 56 | th?: string 57 | td?: string 58 | } 59 | 60 | type TableOutputStyles = { 61 | table?: CSSProperties 62 | tr?: CSSProperties 63 | th?: CSSProperties 64 | td?: CSSProperties 65 | } 66 | 67 | type TableOutputProps = { 68 | data: TableOutputData 69 | style?: TableOutputStyles 70 | classNames?: TableOutputClassNames 71 | config?: ErrConfig 72 | } 73 | 74 | 75 | /********************************************** FUNCTIONS ******************************************/ 76 | 77 | const TableOutput = ({ data, style, classNames, config }: TableOutputProps): JSX.Element => { 78 | if (!data || !data.content || !Array.isArray(data.content)) return <>; 79 | if (!style || typeof style !== 'object') style = {}; 80 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 81 | if (!classNames || typeof classNames !== 'object') classNames = {}; 82 | 83 | supportedKeys.forEach(key => { 84 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 85 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 86 | }); 87 | 88 | const tableStyle = config.disableDefaultStyle ? style.table : { ...defaultStyle.table, ...style.table }; 89 | const trStyle = config.disableDefaultStyle ? style.tr : { ...defaultStyle.tr, ...style.tr }; 90 | const thStyle = config.disableDefaultStyle ? style.th : { ...defaultStyle.th, ...style.th }; 91 | const tdStyle = config.disableDefaultStyle ? style.td : { ...defaultStyle.td, ...style.td }; 92 | 93 | const columnNames = data.content.shift(); 94 | 95 | return ( 96 | 97 | 98 | 99 | { columnNames.map((columnName, index) => ) } 100 | 101 | 102 | 103 | { 104 | data.content.map((row, index) => ( 105 | 106 | { 107 | Array.isArray(row) && row.length > 1 && 108 | row.map((columnValue, i) => ) 109 | } 110 | 111 | )) 112 | } 113 | 114 |
    { parse(columnName) }
    { parse(columnValue) }
    115 | ); 116 | }; 117 | 118 | export default TableOutput; 119 | -------------------------------------------------------------------------------- /renderers/video.tsx: -------------------------------------------------------------------------------- 1 | /** VideoOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2020.09.28 5 | * @author - Tomáš Hylský (https://linktr.ee/thylsky) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 10 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 11 | * @version 1.1.2 - 2022.11.26 - Redefine types 12 | */ 13 | 14 | //#region imports 15 | import React from 'react'; 16 | import parse from 'html-react-parser'; 17 | import type { CSSProperties } from 'react'; 18 | //#endregion 19 | 20 | /********************************************** GLOBALS ******************************************/ 21 | 22 | const supportedKeys = ['video', 'figure', 'figcaption']; 23 | 24 | const defaultStyle: {[key: string]: CSSProperties} = { 25 | videoStyle: { 26 | maxWidth: '100%', 27 | }, 28 | figureStyle: { 29 | position: 'relative', 30 | display: 'flex', 31 | flexDirection: 'column', 32 | justifyContent: 'center', 33 | alignItems: 'center', 34 | margin: '20px 0', 35 | width: '100%', 36 | maxWidth: '100%', 37 | overflow: 'hidden', 38 | backgroundColor: 'aliceblue', 39 | border: '1px solid #eee' 40 | }, 41 | figcaptionStyle: { 42 | position: 'absolute', 43 | top: '8px', 44 | right: '8px', 45 | padding: '5px 10px', 46 | fontSize: '12px', 47 | backgroundColor: '#2d333a', 48 | color: 'white', 49 | borderRadius: '2px', 50 | cursor: 'default', 51 | } 52 | }; 53 | 54 | 55 | /********************************************** TYPES ******************************************/ 56 | 57 | type VideoOutputData = { 58 | url?: string 59 | file?: { url: string } 60 | caption?: string 61 | autoPlay?: boolean 62 | muted?: boolean 63 | controls?: boolean 64 | stretched?: boolean 65 | withBorder?: boolean 66 | withBackground?: boolean 67 | } 68 | 69 | type VideoOutputClassNames = { 70 | video?: string 71 | figure?: string 72 | figcaption?: string 73 | } 74 | 75 | type VideoOutputStyles = { 76 | video?: CSSProperties 77 | figure?: CSSProperties 78 | figcaption?: CSSProperties 79 | } 80 | 81 | type VideoOutputProps = { 82 | data: VideoOutputData 83 | style?: VideoOutputStyles 84 | classNames?: VideoOutputClassNames 85 | config?: ErrConfig 86 | } 87 | 88 | 89 | /********************************************** FUNCTIONS ******************************************/ 90 | 91 | const VideoOutput = ({ data, style, classNames, config }: VideoOutputProps): JSX.Element => { 92 | console.log(`dat: ${data}`); 93 | if (!data?.url && !data?.file?.url) { 94 | console.log(data); 95 | return <>; 96 | } 97 | if (!style || typeof style !== 'object') style = {}; 98 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 99 | if (!classNames || typeof classNames !== 'object') classNames = {}; 100 | 101 | supportedKeys.forEach(key => { 102 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 103 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 104 | }); 105 | 106 | const videoStyle = config.disableDefaultStyle ? style.video : { ...defaultStyle.videoStyle, ...style.video }; 107 | videoStyle['width'] = data.stretched ? '100%' : ''; 108 | 109 | const figureStyle = config.disableDefaultStyle ? style.figure : { ...defaultStyle.figureStyle, ...style.figure }; 110 | 111 | if (!data.withBorder) figureStyle['border'] = 'none'; 112 | if (!data.withBackground) figureStyle['backgroundColor'] = 'none'; 113 | 114 | const figcaptionStyle = config.disableDefaultStyle ? style.figcaption : { ...defaultStyle.figcaptionStyle, ...style.figcaption }; 115 | 116 | return ( 117 |
    118 | 122 | { data.caption &&
    { parse(data.caption) }
    } 123 |
    124 | ); 125 | }; 126 | 127 | export default VideoOutput; 128 | -------------------------------------------------------------------------------- /renderers/warning.tsx: -------------------------------------------------------------------------------- 1 | /** WarningOutput 2 | * 3 | * @version 1.0.0 4 | * @created - 2019.08.20 5 | * @author - Adombang Munang Mbomndih (Bomdi) (https://bomdisoft.com) 6 | * 7 | * Version History 8 | * --------------- 9 | * @version 1.0.1 - 2020.02.12 - Covert to React component 10 | * @version 1.0.2 - 2020.07.17 - Add config parameter 11 | * @version 1.1.0 - 2021.04.11 - Add classNames parameter 12 | * @version 1.1.1 - 2021.04.12 - Add validation for config parameter 13 | * @version 1.1.2 - 2022.11.26 - Redefine types 14 | */ 15 | 16 | //#region imports 17 | import React from 'react'; 18 | import parse from 'html-react-parser'; 19 | import type { CSSProperties } from 'react'; 20 | //#endregion 21 | 22 | /********************************************** GLOBALS ******************************************/ 23 | 24 | const supportedKeys = ['container', 'icon', 'title', 'message']; 25 | 26 | const defaultStyle: {[key: string]: CSSProperties} = { 27 | container: { 28 | width: '100%', 29 | margin: '20px 8px', 30 | display: 'flex', 31 | justifyContent: 'flex-start', 32 | alignItems: 'flex-start', 33 | }, 34 | icon: { 35 | width: '30px', 36 | enableBackground: 'new 0 0 50 50', 37 | } as any, 38 | title: { 39 | fontWeight: 400, 40 | textTransform: 'uppercase', 41 | margin: 0, 42 | marginRight: '15px', 43 | marginLeft: '5px', 44 | fontSize: '90%', 45 | }, 46 | message: { 47 | color: 'goldenrod', 48 | textAlign: 'left', 49 | fontSize: '90%', 50 | margin: 0, 51 | }, 52 | circle: { 53 | fill: '#EFCE4A' 54 | }, 55 | line: { 56 | fill: 'none', 57 | stroke: '#FFFFFF', 58 | strokeWidth: 5, 59 | strokeLinecap: 'round', 60 | strokeMiterlimit: 10 61 | } 62 | }; 63 | 64 | 65 | /********************************************** TYPES ******************************************/ 66 | 67 | type WarningOutputData = { 68 | message: string 69 | title?: string 70 | } 71 | 72 | type WarningOutputClassNames = { 73 | container?: string 74 | icon?: string 75 | title?: string 76 | message?: string 77 | } 78 | 79 | type WarningOutputStyles = { 80 | container?: CSSProperties 81 | icon?: CSSProperties 82 | title?: CSSProperties 83 | message?: CSSProperties 84 | } 85 | 86 | type WarningOutputProps = { 87 | data: WarningOutputData 88 | style?: WarningOutputStyles 89 | classNames?: WarningOutputClassNames 90 | config?: ErrConfig 91 | } 92 | 93 | type WarningProps = { 94 | title: string 95 | message: string 96 | style: WarningOutputStyles 97 | classNames: WarningOutputClassNames 98 | config: ErrConfig 99 | } 100 | 101 | 102 | /********************************************** FUNCTIONS ******************************************/ 103 | 104 | const Warning = ({ title, message, classNames, style={}, config }: WarningProps) => { 105 | const containerStyle = config.disableDefaultStyle ? style.container : { ...defaultStyle.container, ...style.container }; 106 | const iconStyle = config.disableDefaultStyle ? style.icon : { ...defaultStyle.icon, ...style.icon }; 107 | const titleStyle = config.disableDefaultStyle ? style.title : { ...defaultStyle.title, ...style.title }; 108 | const messageStyle = config.disableDefaultStyle ? style.message : { ...defaultStyle.message, ...style.message }; 109 | 110 | return ( 111 |
    112 | 114 | 115 | 116 | 117 | 118 | 119 |

    { title }:

    120 |

    { message }

    121 |
    122 | ); 123 | }; 124 | 125 | const WarningOutput = ({ data, style, classNames, config }: WarningOutputProps): JSX.Element => { 126 | if (!data || !data.message || typeof data.message != 'string') return <>; 127 | if (!style || typeof style !== 'object') style = {}; 128 | if (!config || typeof config !== 'object') config = { disableDefaultStyle: false }; 129 | if (!classNames || typeof classNames !== 'object') classNames = {}; 130 | 131 | supportedKeys.forEach(key => { 132 | if (!style[key] || typeof style[key] !== 'object') style[key] = {}; 133 | if (!classNames[key] || typeof classNames[key] !== 'string') classNames[key] = ''; 134 | }); 135 | 136 | return ; 138 | }; 139 | 140 | export default WarningOutput; 141 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "strict": false, 12 | "forceConsistentCasingInFileNames": true, 13 | "noEmit": true, 14 | "esModuleInterop": true, 15 | "module": "CommonJS", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "jsx": "react", 20 | "incremental": true, 21 | "declaration": true, 22 | "removeComments": true, 23 | "outDir": "./dist/" 24 | }, 25 | "include": [ 26 | "**/*.ts", 27 | "**/*.tsx" 28 | ], 29 | "exclude": [ 30 | "node_modules", 31 | "docs", 32 | "dist" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | mode: 'production', 5 | // mode: 'development', 6 | // devtool: 'source-map', 7 | entry: path.normalize(`${__dirname}/index.tsx`), 8 | output: { 9 | path: path.normalize(`${__dirname}/dist`), 10 | filename: 'index.min.js', 11 | libraryTarget: 'umd', 12 | globalObject: 'typeof self !== "undefined" ? self : this' 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.(js|jsx|tsx)$/, 18 | use: [ 19 | { 20 | loader: 'babel-loader', 21 | options: { 22 | presets: ['@babel/preset-env'], 23 | }, 24 | }, 25 | { 26 | loader: 'ts-loader', 27 | options: { 28 | compilerOptions: { 29 | noEmit: false, 30 | }, 31 | }, 32 | } 33 | ] 34 | } 35 | ], 36 | }, 37 | resolve: { 38 | extensions: ['.tsx', '.ts', '.js'], 39 | alias: { 40 | 'react': path.resolve(__dirname, './node_modules/react'), 41 | } 42 | }, 43 | externals: { 44 | react: { 45 | commonjs: 'react', 46 | commonjs2: 'react', 47 | amd: 'React', 48 | root: 'React' 49 | }, 50 | } 51 | }; 52 | --------------------------------------------------------------------------------