From 0cb523f856588888d35d2be17c51b311939fd841 Mon Sep 17 00:00:00 2001 From: NikPnevmatikos <61566326+NikPnevmatikos@users.noreply.github.com> Date: Fri, 11 Sep 2026 16:23:46 +0300 Subject: [PATCH] docs: add Docusaurus documentation site with GitHub Pages workflow - website/: Docusaurus 3.10 site, kept outside the npm workspaces so its dependencies never mix with the React Native ones. Eight pages moved from the README: getting started, supported HTML, styling and cascade, props, custom rendering, plugins, how it works, limitations. The landing page embeds example/App.tsx in Expo Snack (SDK 56) as a live playground. - .github/workflows/docs.yml: builds the site on pull requests touching website/, builds and deploys to GitHub Pages on push to main. Pages must be enabled once with "Source: GitHub Actions" before the deploy job can succeed. - README (root + core): docs badge linking to https://nikpnevmatikos.github.io/Html-Renderer/ Co-Authored-By: Claude Fable 5.1 --- .github/workflows/docs.yml | 64 + README.md | 1 + packages/core/README.md | 1 + website/.gitignore | 20 + website/README.md | 20 + website/docs/custom-rendering.md | 121 + website/docs/getting-started.md | 60 + website/docs/how-it-works.md | 42 + website/docs/limitations.md | 18 + website/docs/plugins.md | 98 + website/docs/props.md | 42 + website/docs/styling.md | 95 + website/docs/supported-html.md | 49 + website/docusaurus.config.ts | 111 + website/package-lock.json | 19555 ++++++++++++++++++++++++ website/package.json | 49 + website/sidebars.ts | 9 + website/src/components/SnackEmbed.tsx | 93 + website/src/css/custom.css | 27 + website/src/pages/index.module.css | 38 + website/src/pages/index.tsx | 110 + website/static/.nojekyll | 0 website/static/img/favicon.svg | 6 + website/static/img/logo.svg | 6 + website/tsconfig.json | 12 + 25 files changed, 20647 insertions(+) create mode 100644 .github/workflows/docs.yml create mode 100644 website/.gitignore create mode 100644 website/README.md create mode 100644 website/docs/custom-rendering.md create mode 100644 website/docs/getting-started.md create mode 100644 website/docs/how-it-works.md create mode 100644 website/docs/limitations.md create mode 100644 website/docs/plugins.md create mode 100644 website/docs/props.md create mode 100644 website/docs/styling.md create mode 100644 website/docs/supported-html.md create mode 100644 website/docusaurus.config.ts create mode 100644 website/package-lock.json create mode 100644 website/package.json create mode 100644 website/sidebars.ts create mode 100644 website/src/components/SnackEmbed.tsx create mode 100644 website/src/css/custom.css create mode 100644 website/src/pages/index.module.css create mode 100644 website/src/pages/index.tsx create mode 100644 website/static/.nojekyll create mode 100644 website/static/img/favicon.svg create mode 100644 website/static/img/logo.svg create mode 100644 website/tsconfig.json diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..2835606 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,64 @@ +name: Docs + +# Builds the Docusaurus site in website/ and publishes it to GitHub Pages. +# Pages must be enabled once in the repository settings with +# "Source: GitHub Actions" before the deploy job can succeed. + +on: + push: + branches: [main] + paths: + - 'website/**' + - '.github/workflows/docs.yml' + pull_request: + paths: + - 'website/**' + - '.github/workflows/docs.yml' + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + cache-dependency-path: website/package-lock.json + + - name: Install + run: npm ci + working-directory: website + + - name: Build + run: npm run build + working-directory: website + + - name: Upload Pages artifact + if: github.event_name != 'pull_request' + uses: actions/upload-pages-artifact@v3 + with: + path: website/build + + deploy: + if: github.event_name != 'pull_request' + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/README.md b/README.md index 4c89001..60a8b6e 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![CI](https://github.com/NikPnevmatikos/Html-Renderer/actions/workflows/ci.yml/badge.svg)](https://github.com/NikPnevmatikos/Html-Renderer/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE) [![Open in Snack](https://img.shields.io/badge/Open%20in-Snack-4630EB?logo=expo&logoColor=white)](https://snack.expo.dev/?platform=web&sdkVersion=56.0.0&name=html-renderer%20example&dependencies=%40nikpnevmatikos%2Fhtml-renderer%2C%40nikpnevmatikos%2Fhtml-renderer-video%2C%40nikpnevmatikos%2Fhtml-renderer-video%2Fexpo%2Cexpo-video%2Cexpo-status-bar&files=%7B%22App.tsx%22%3A%7B%22type%22%3A%22CODE%22%2C%22url%22%3A%22https%3A%2F%2Fraw.githubusercontent.com%2FNikPnevmatikos%2FHtml-Renderer%2Fmain%2Fexample%2FApp.tsx%22%7D%7D) +[![Docs](https://img.shields.io/badge/docs-nikpnevmatikos.github.io-1a73e8)](https://nikpnevmatikos.github.io/Html-Renderer/) A modern React Native HTML renderer, written in TypeScript with **zero native modules**. Built from scratch as a lightweight alternative to `react-native-render-html` and its successor `@native-html/render`. diff --git a/packages/core/README.md b/packages/core/README.md index ec570e7..d89fd85 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -4,6 +4,7 @@ [![CI](https://github.com/NikPnevmatikos/Html-Renderer/actions/workflows/ci.yml/badge.svg)](https://github.com/NikPnevmatikos/Html-Renderer/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE) [![Open in Snack](https://img.shields.io/badge/Open%20in-Snack-4630EB?logo=expo&logoColor=white)](https://snack.expo.dev/?platform=web&sdkVersion=56.0.0&name=html-renderer%20example&dependencies=%40nikpnevmatikos%2Fhtml-renderer%2C%40nikpnevmatikos%2Fhtml-renderer-video%2C%40nikpnevmatikos%2Fhtml-renderer-video%2Fexpo%2Cexpo-video%2Cexpo-status-bar&files=%7B%22App.tsx%22%3A%7B%22type%22%3A%22CODE%22%2C%22url%22%3A%22https%3A%2F%2Fraw.githubusercontent.com%2FNikPnevmatikos%2FHtml-Renderer%2Fmain%2Fexample%2FApp.tsx%22%7D%7D) +[![Docs](https://img.shields.io/badge/docs-nikpnevmatikos.github.io-1a73e8)](https://nikpnevmatikos.github.io/Html-Renderer/) A modern React Native HTML renderer, written in TypeScript with **zero native modules**. Built from scratch as a lightweight alternative to `react-native-render-html` and its successor `@native-html/render`. diff --git a/website/.gitignore b/website/.gitignore new file mode 100644 index 0000000..b2d6de3 --- /dev/null +++ b/website/.gitignore @@ -0,0 +1,20 @@ +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/website/README.md b/website/README.md new file mode 100644 index 0000000..c9de656 --- /dev/null +++ b/website/README.md @@ -0,0 +1,20 @@ +# Documentation site + +Docusaurus site for `@nikpnevmatikos/html-renderer`, published to +https://nikpnevmatikos.github.io/Html-Renderer/ by `.github/workflows/docs.yml` +on every push to `main` that touches `website/`. + +This folder is **not** an npm workspace member. It has its own `package.json` +and lockfile so Docusaurus dependencies never mix with the React Native ones. + +```bash +cd website +npm install +npm start # dev server with live reload at http://localhost:3000/Html-Renderer/ +npm run build # static build into website/build +``` + +- Pages live in `docs/`. Sidebar order comes from each page's `sidebar_position`. +- The landing page is `src/pages/index.tsx`. It embeds the repository's + `example/App.tsx` in Expo Snack through `src/components/SnackEmbed.tsx`. +- Broken internal links and anchors fail the build on purpose. diff --git a/website/docs/custom-rendering.md b/website/docs/custom-rendering.md new file mode 100644 index 0000000..f259853 --- /dev/null +++ b/website/docs/custom-rendering.md @@ -0,0 +1,121 @@ +--- +sidebar_position: 5 +title: Custom rendering +description: Replace renderers, define your own tags, rewrite the DOM, handle links, size images and configure built-in renderers. +--- + +# Custom rendering + +Every extension point uses the same small API surface. Plugins such as the [video plugin](./plugins.md) are built on exactly these props. + +## Custom renderers + +`customRenderers` replaces or wraps the renderer for a tag. The renderer receives the node and a `defaultRender` function, so wrapping the built-in output is one line: + +```tsx +import { type CustomRenderer } from '@nikpnevmatikos/html-renderer'; + +const customRenderers: Record = { + h1: (node, defaultRender) => ( + + {defaultRender()} + + ), +}; + +; +``` + +Custom renderers are plain function calls, not components. If your renderer needs hooks, return a real component element from it and put the hooks inside that component. + +## Custom HTML element models + +`customHTMLElementModels` defines tags of your own that behave like real HTML: block or inline display, default styles, and void elements that ignore their children. + +```tsx +import { type HTMLElementModel } from '@nikpnevmatikos/html-renderer'; + +const customHTMLElementModels: Record = { + 'my-card': { + display: 'block', + tagDefaultStyle: { backgroundColor: '#eef', padding: 12 }, + }, + 'x-spacer': { + display: 'block', + isVoid: true, + tagDefaultStyle: { height: 20 }, + }, +}; + +; +``` + +## DOM transform hook + +`transformDom` runs after parsing and before the render tree is built. It receives the DOM as an array of nodes and returns the DOM to render. Use it for sanitization, tag rewrites or content substitution: + +```tsx +import { type TransformDom, type DomNode } from '@nikpnevmatikos/html-renderer'; + +const transformDom: TransformDom = (dom) => rewriteText(dom); + +function rewriteText(nodes: DomNode[]): DomNode[] { + return nodes.map((n) => { + if (n.type === 'text') { + return { ...n, data: n.data.replace(/REPLACE_ME/g, 'replaced-by-hook') }; + } + return { ...n, children: rewriteText(n.children) }; + }); +} + +; +``` + +## Link handling + +By default links open with `Linking.openURL`. `onLinkPress` receives the `href` and the element's attributes, so you can route in-app instead: + +```tsx +import { type OnLinkPress } from '@nikpnevmatikos/html-renderer'; + +const onLinkPress: OnLinkPress = (href, attribs) => { + if (attribs.target === '_blank') { + void Linking.openURL(href); + } else { + navigation.navigate('InAppBrowser', { url: href }); + } +}; + +; +``` + +## Auto-fit images + +Pass `contentWidth` and images wider than it scale down proportionally: + +```tsx +import { Dimensions } from 'react-native'; + +const contentWidth = Dimensions.get('window').width - 32; + +; +``` + +## Renderer props + +`renderersProps` passes configuration to individual renderers, built-in or custom: + +```tsx + +``` diff --git a/website/docs/getting-started.md b/website/docs/getting-started.md new file mode 100644 index 0000000..25379f7 --- /dev/null +++ b/website/docs/getting-started.md @@ -0,0 +1,60 @@ +--- +sidebar_position: 1 +title: Getting started +description: Install @nikpnevmatikos/html-renderer and render your first HTML in React Native. +--- + +# Getting started + +`@nikpnevmatikos/html-renderer` renders HTML in React Native. It is written in TypeScript, ships **zero native modules**, and gives you real CSS: a `stylesheet` prop that accepts selectors and resolves them with proper specificity. + +## Why this renderer + +- **Zero native code.** Works on iOS, Android and web (via `react-native-web`), and in Expo Go without a dev build. +- **New Architecture compatible** out of the box. There is nothing native to migrate. +- **Real CSS stylesheets.** Type, class, id, descendant and child selectors, with specificity and source order per the spec. +- **A transient render tree.** HTML is parsed to a DOM, resolved into a styled render tree, and emitted as ``, `` and `` elements. +- **Full style inheritance and cascade**, plus the box-model basics. +- **Extensible.** Custom renderers, custom element models, DOM transform hooks and per-renderer config. Plugin packages use the same API. +- **Entity-encoded input handled.** HTML that arrives as `<p>hello</p>` from a CMS or API, even double-encoded, is detected and rendered as HTML. +- **Typed end-to-end** and covered by 130+ unit tests. + +## Install + +```bash +npm install @nikpnevmatikos/html-renderer +``` + +Peer dependencies: `react >= 18` and `react-native >= 0.73`. + +## Quick start + +```tsx +import { HtmlRenderer } from '@nikpnevmatikos/html-renderer'; + +export default function Screen() { + return ( + Hello

This is bold and a link.

`} + /> + ); +} +``` + +That is the whole integration. Everything else on this site is optional: styling, custom rendering, plugins. + +## Try it without installing + +The repository's example app runs in Expo Snack. Open it, edit the HTML or the stylesheet, and watch the preview update: + +[Open the example in Snack](https://snack.expo.dev/?platform=web&sdkVersion=56.0.0&name=html-renderer%20example&dependencies=%40nikpnevmatikos%2Fhtml-renderer%2C%40nikpnevmatikos%2Fhtml-renderer-video%2C%40nikpnevmatikos%2Fhtml-renderer-video%2Fexpo%2Cexpo-video%2Cexpo-status-bar&files=%7B%22App.tsx%22%3A%7B%22type%22%3A%22CODE%22%2C%22url%22%3A%22https%3A%2F%2Fraw.githubusercontent.com%2FNikPnevmatikos%2FHtml-Renderer%2Fmain%2Fexample%2FApp.tsx%22%7D%7D) + +Snack must be on Expo SDK 56 or newer for the `