For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /guide/customization.md.
  • English
  • Styling and Components

    The library emits stable wtr-* classes and a set of CSS variables. Page structure, labels, heading anchors, and component appearance can all be adjusted without patching the library.

    Styles

    Import the page stylesheet once:

    import "react-wikitext/styles.css";
    • The library sets no global element styles; page typography inherits from the host.
    • The root container is div.wtr-view; library classes start with wtr- and some MediaWiki compatibility classes are preserved.
    • Inline styles keep only whitelisted layout and appearance declarations; unsafe values are dropped whole. Under strict CSP, allow style-src as needed.

    CSS variables

    VariablePurpose
    --wtr-textBody text
    --wtr-mutedSecondary text
    --wtr-borderBorders and dividers
    --wtr-accentLinks and emphasis
    --wtr-accent-softEmphasis background
    --wtr-placeholder-bgPlaceholder background
    --wtr-dangerErrors and blocked content
    --wtr-font-monoMonospace text

    Variables are defined on :root and can be overridden on any ancestor:

    .article-theme {
      --wtr-text: #1f2328;
      --wtr-accent: #0969da;
      --wtr-border: #d0d7de;
    }

    Dark themes can override the same variables through [data-wtr-theme="dark"] or the host's own selector.

    Container props

    <Wikitext
      source={source}
      lang="en"
      dir="ltr"
      className="article"
      containerProps={{ "data-page": "example" }}
    />

    className and containerProps.className merge with wtr-view. The containerProps type excludes dangerouslySetInnerHTML.

    Labels

    All user-visible placeholders and notices come from labels. Prepare options accept Partial<WikitextLabels>; omitted fields keep the default English strings.

    <Wikitext
      source={source}
      prepareOptions={{
        labels: {
          templateNotExpanded: "Template not expanded",
          parserFunctionNotEvaluated: "Parser function not evaluated",
          filePlaceholder: "File",
          reference: "Reference",
          toc: "Contents",
          categories: "Categories",
          unknownNode: "Unsupported node",
          redirectTo: "Redirect to",
          blockedLink: "Blocked link",
          blockedHtml: "Blocked HTML",
          renderFailed: "Render failed",
          nestedTableUnsupported: "Nested table not supported",
        },
      }}
    />
    FieldDefault
    templateNotExpandedTemplate not expanded
    parserFunctionNotEvaluatedParser function not evaluated
    filePlaceholderFile
    referenceReference
    tocContents
    categoriesCategories
    unknownNodeUnsupported node
    redirectToRedirect to
    blockedLinkBlocked link
    blockedHtmlBlocked HTML
    renderFailedRender failed
    nestedTableUnsupportedNested table not supported

    The effective labels are written to WikitextRenderDocument.meta.labels; the view and components read the same strings.

    Heading anchors

    type WikitextHeadingIdStrategy = "instance" | "mediawiki" | "none";
    StrategyBehavior
    instance (default)Preparation generates logical anchors; the view prefixes DOM ids per instance so multiple views do not conflict
    mediawikiWrites bare anchors and adds no prefix; suitable for a single page that matches host conventions
    noneWrites no ids and generates no table-of-contents links
    • Anchors are generated from stripped heading text: whitespace becomes _, duplicate ids get _2 / _3 case-insensitively, and empty headings fall back to section-{n}.
    • Semantic headings and source h1–h6 both participate.
    • idPrefix applies only to instance; without it, the view uses a React useId prefix.
    • The view maps heading id, in-document #fragment links, and table headers attributes.

    Read the final heading list from the render snapshot:

    for (const heading of prepared.headings) {
      console.log(heading.level, heading.text, heading.id);
    }

    Component overrides

    Overrides have the following precedence:

    1. semanticComponents[type] replaces the whole wiki semantic structure.
    2. components[tag] replaces an HTML tag inside the default HAST structure.
    3. Native elements.

    HTML components

    <WikitextView
      document={prepared}
      components={{
        blockquote: ({ children, className }) => (
          <blockquote className={[className, "doc-quote"].filter(Boolean).join(" ")}>
            {children}
          </blockquote>
        ),
      }}
    />

    components maps by HAST tag name such as p, table, img, or a. Components receive sanitized DOM props, the HAST node, the document, and optionally the semantic node and origin. Do not spread non-DOM props onto native elements.

    Semantic components

    import { WikitextFragment, type WikitextTemplateComponentProps } from "react-wikitext/view";
    
    function TemplateCard({ displayName, node }: WikitextTemplateComponentProps) {
      return (
        <aside className="template-card">
          <strong>{displayName}</strong>
          <WikitextFragment nodes={node.children} mode="block" />
        </aside>
      );
    }
    
    <WikitextView document={prepared} semanticComponents={{ template: TemplateCard }} />;

    Available semantic types:

    TypeExtra props
    linktarget, kind, href?, external
    template / parserFunctiondisplayName
    argument—
    filename
    referencenumber
    extensionname, block
    unknownparsedType, block
    table—
    • semanticComponents.extension receives all extension nodes except ref; ref uses reference, and <references> produces no component call.
    • semanticComponents.reference replaces only the <sup>; the endnotes section is still generated by the library.
    • WikitextFragment must run inside the WikitextView context, and nodes must be the same node objects from the current render document. It is intended for children the default renderer does not output, such as template parameters, file captions, and ref content.
    Warning

    components and semanticComponents are trusted code; HTML they emit is not sanitized again. Resolver URLs are validated during preparation, but components should still avoid putting untrusted input into dangerous attributes.

    Read the context

    import { useWikitextIds, useWikitextLabels } from "react-wikitext/view";
    
    function SectionLink() {
      const labels = useWikitextLabels();
      const ids = useWikitextIds();
      return <a href={ids.toHref("#section-1")}>{labels.toc}</a>;
    }
    • useWikitextContext() provides document, indexes, component maps, idPrefix, mapId, mapHref, and onRenderError.
    • useWikitextLabels() reads labels from the current render snapshot.
    • useWikitextIds() provides toDomId and toHref.

    These hooks and WikitextFragment must be used inside <WikitextView>.

    Plugins

    <Wikitext
      source={source}
      prepareOptions={{
        wikitextPlugins: [
          () => (tree, file) => {
            // Runs on the cloned semantic AST
            return tree;
          },
        ],
        rehypePlugins: [
          () => (tree) => {
            for (const child of tree.children) {
              if (child.type === "element" && child.tagName === "p") {
                const classes = child.properties.className;
                child.properties.className = [
                  "doc-paragraph",
                  ...(Array.isArray(classes) ? classes : []),
                ];
              }
            }
            return tree;
          },
        ],
      }}
    />
    • wikitextPlugins run on the cloned semantic tree; rehypePlugins run after HAST conversion and before final sanitization.
    • The plugin signature follows unified's (tree, file), where file is a VFile.
    • The original parse snapshot is not modified; preparation reassigns ids on the working tree.
    • The synchronous entry rejects async plugins; use prepareWikitextAsync for those.
    • Final sanitization always runs after rehype plugins; plugins cannot bypass whitelists or image authorization.

    Plugin lists are structured arrays. Elements can be plugin functions or [plugin, options] tuples and run in order.

    Security policy

    prepareOptions.policy adjusts URL and tag whitelists. Defaults:

    {
      allowRelativeLinks: true,
      allowRelativeImages: false,
      allowPluginImages: false,
      externalLinkTarget: "_blank",
      extraTags: [],
      stripTags: [
        "script", "style", "iframe", "object", "embed", "form", "input",
        "button", "textarea", "select", "option", "svg", "math", "meta", "link",
      ],
    }

    policy is shallow-merged with defaults; array fields are replaced wholesale. class is filtered only by the [A-Za-z0-9_-] safe character set, with no option to widen or narrow it. For tags, attributes, or rich presentation outside the whitelist, prefer /view component overrides; do not loosen sanitization.

    Custom semantic nodes

    Custom nodes require extending WikitextNodeMap and registering a HAST converter in prepareOptions.handlers. A node without a handler produces a diagnostic and degrades to a source card. Handler context, budgets, and conversion details are in the prepare API.