diff --git a/crates/weaver-renderer-js/Cargo.toml b/crates/weaver-renderer-js/Cargo.toml
index df9a811..bd32329 100644
--- a/crates/weaver-renderer-js/Cargo.toml
+++ b/crates/weaver-renderer-js/Cargo.toml
@@ -4,10 +4,11 @@ version.workspace = true
edition.workspace = true
license.workspace = true
authors.workspace = true
+repository = "https://tangled.org/nonbinary.computer/weaver"
description = "WASM bindings for weaver-renderer"
[lib]
-crate-type = ["cdylib", "rlib"]
+crate-type = ["cdylib"]
[features]
default = ["syntax-highlighting"]
diff --git a/crates/weaver-renderer-js/LICENSE b/crates/weaver-renderer-js/LICENSE
new file mode 120000
index 0000000..30cff74
--- /dev/null
+++ b/crates/weaver-renderer-js/LICENSE
@@ -0,0 +1 @@
+../../LICENSE
\ No newline at end of file
diff --git a/crates/weaver-renderer-js/build.sh b/crates/weaver-renderer-js/build.sh
new file mode 100755
index 0000000..e028538
--- /dev/null
+++ b/crates/weaver-renderer-js/build.sh
@@ -0,0 +1,266 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+cd "$SCRIPT_DIR"
+
+PKG_NAME="@weaver.sh/renderer"
+PKG_VERSION="0.1.1"
+
+# Targets to build
+TARGETS=(bundler web nodejs deno)
+
+COMMAND="${1:-build}"
+shift || true
+
+# Feature variants
+declare -A VARIANTS=(
+ ["core"]=""
+ ["full"]="syntax-highlighting"
+)
+
+build() {
+ local target="$1"
+ local variant="$2"
+ local features="$3"
+ local out_dir="pkg/${variant}/${target}"
+
+ echo "Building ${variant}/${target}..."
+
+ local feature_args=""
+ if [[ -n "$features" ]]; then
+ feature_args="--features $features"
+ fi
+
+ wasm-pack build \
+ --out-name weaver_renderer \
+ --out-dir "$out_dir" \
+ --target "$target" \
+ --no-default-features \
+ $feature_args
+
+ # Report size
+ local wasm_file="${out_dir}/weaver_renderer_bg.wasm"
+ if [[ -f "$wasm_file" ]]; then
+ local size=$(ls -lh "$wasm_file" | awk '{print $5}')
+ echo " → ${size}"
+ fi
+}
+
+generate_package_json() {
+ local variant="$1"
+ local out_dir="pkg/${variant}"
+ local description="AT Protocol record renderer (${variant})"
+
+ if [[ "$variant" == "full" ]]; then
+ description="AT Protocol record renderer with syntax highlighting"
+ else
+ description="AT Protocol record renderer (lightweight, no syntax highlighting)"
+ fi
+
+ cat > "${out_dir}/package.json" << EOF
+{
+ "name": "${PKG_NAME}-${variant}",
+ "version": "${PKG_VERSION}",
+ "description": "${description}",
+ "license": "MPL-2.0",
+ "repository": {
+ "type": "git",
+ "url": "https://tangled.org/nonbinary.computer/weaver"
+ },
+ "keywords": ["atproto", "bluesky", "markdown", "renderer", "wasm"],
+ "main": "nodejs/weaver_renderer.js",
+ "module": "bundler/weaver_renderer.js",
+ "browser": "web/weaver_renderer.js",
+ "types": "bundler/weaver_renderer.d.ts",
+ "exports": {
+ ".": {
+ "deno": "./deno/weaver_renderer.js",
+ "node": {
+ "import": "./nodejs/weaver_renderer.js",
+ "require": "./nodejs/weaver_renderer.js"
+ },
+ "browser": {
+ "import": "./web/weaver_renderer.js"
+ },
+ "default": "./bundler/weaver_renderer.js"
+ },
+ "./bundler": {
+ "import": "./bundler/weaver_renderer.js",
+ "types": "./bundler/weaver_renderer.d.ts"
+ },
+ "./web": {
+ "import": "./web/weaver_renderer.js",
+ "types": "./web/weaver_renderer.d.ts"
+ },
+ "./nodejs": {
+ "import": "./nodejs/weaver_renderer.js",
+ "require": "./nodejs/weaver_renderer.js",
+ "types": "./nodejs/weaver_renderer.d.ts"
+ },
+ "./deno": {
+ "import": "./deno/weaver_renderer.js",
+ "types": "./deno/weaver_renderer.d.ts"
+ }
+ },
+ "files": [
+ "bundler/",
+ "web/",
+ "nodejs/",
+ "deno/",
+ "README.md"
+ ]
+}
+EOF
+}
+
+generate_readme() {
+ local variant="$1"
+ local out_dir="pkg/${variant}"
+
+ cat > "${out_dir}/README.md" << 'EOF'
+# @weaver.sh/renderer
+
+WASM bindings for rendering AT Protocol records (Bluesky posts, etc.) to HTML.
+
+## Installation
+
+```bash
+npm install @weaver.sh/renderer-full # With syntax highlighting
+npm install @weaver.sh/renderer-core # Light(er) weight
+```
+
+## Usage
+
+### With a bundler (webpack, vite, etc.)
+
+```javascript
+import init, { render_record, render_markdown } from '@weaver.sh/renderer-full';
+
+await init();
+
+const html = render_record(atUri, recordJson);
+```
+
+### Direct browser usage (no bundler)
+
+```html
+
+```
+
+### Node.js
+
+```javascript
+const { render_record } = require('@weaver.sh/renderer-full/nodejs');
+```
+
+## API
+
+- `render_record(at_uri, record_json, fallback_author?, resolved_content?)` - Render an AT Protocol record
+- `render_markdown(markdown, resolved_content?)` - Render markdown to HTML
+- `render_math(latex, display_mode)` - Render LaTeX math to MathML
+- `render_faceted_text(text, facets_json)` - Render rich text with facets
+EOF
+}
+
+do_build() {
+# Clean previous builds
+rm -rf pkg
+
+# Build all combinations
+for variant in "${!VARIANTS[@]}"; do
+ features="${VARIANTS[$variant]}"
+
+ for target in "${TARGETS[@]}"; do
+ build "$target" "$variant" "$features"
+ done
+
+ generate_package_json "$variant"
+ generate_readme "$variant"
+
+ # Clean up wasm-pack artifacts we don't need
+ find "pkg/${variant}" -name ".gitignore" -delete
+ find "pkg/${variant}" -name "package.json" -path "*/bundler/*" -delete
+ find "pkg/${variant}" -name "package.json" -path "*/web/*" -delete
+ find "pkg/${variant}" -name "package.json" -path "*/nodejs/*" -delete
+ find "pkg/${variant}" -name "package.json" -path "*/deno/*" -delete
+done
+
+echo ""
+echo "Build complete!"
+echo ""
+ls -lh pkg/core/web/*.wasm pkg/full/web/*.wasm 2>/dev/null || true
+echo ""
+echo "Packages:"
+echo " pkg/core/ - @weaver.sh/renderer-core (no syntax highlighting)"
+echo " pkg/full/ - @weaver.sh/renderer-full (with syntax highlighting)"
+}
+
+do_pack() {
+ echo "Packing..."
+ for variant in "${!VARIANTS[@]}"; do
+ echo " ${variant}..."
+ (cd "pkg/${variant}" && npm pack)
+ done
+ echo ""
+ echo "Tarballs created:"
+ ls -lh pkg/*/*.tgz 2>/dev/null || true
+}
+
+do_publish() {
+ local tag="${1:-}"
+ local tag_arg=""
+ if [[ -n "$tag" ]]; then
+ tag_arg="--tag $tag"
+ fi
+
+ echo "Publishing..."
+ for variant in "${!VARIANTS[@]}"; do
+ echo " ${variant}..."
+ (cd "pkg/${variant}" && npm publish --access public $tag_arg)
+ done
+ echo ""
+ echo "Published!"
+}
+
+usage() {
+ echo "Usage: $0 [command]"
+ echo ""
+ echo "Commands:"
+ echo " build Build all variants and targets (default)"
+ echo " pack Create npm tarballs"
+ echo " publish Publish to npm registry"
+ echo " all Build, pack, and publish"
+ echo ""
+ echo "Options for publish:"
+ echo " --tag Publish with a specific tag (e.g., 'next', 'beta')"
+}
+
+case "$COMMAND" in
+ build)
+ do_build
+ ;;
+ pack)
+ do_pack
+ ;;
+ publish)
+ do_publish "$@"
+ ;;
+ all)
+ do_build
+ do_pack
+ do_publish "$@"
+ ;;
+ -h|--help|help)
+ usage
+ ;;
+ *)
+ echo "Unknown command: $COMMAND"
+ usage
+ exit 1
+ ;;
+esac
diff --git a/crates/weaver-renderer-js/pkg/core/README.md b/crates/weaver-renderer-js/pkg/core/README.md
new file mode 100644
index 0000000..679c044
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/README.md
@@ -0,0 +1,45 @@
+# @weaver/renderer
+
+WASM bindings for rendering AT Protocol records (Bluesky posts, etc.) to HTML.
+
+## Installation
+
+```bash
+npm install @weaver.sh/renderer-full # With syntax highlighting
+npm install @weaver.sh/renderer-core # Light(er) weight
+```
+
+## Usage
+
+### With a bundler (webpack, vite, etc.)
+
+```javascript
+import init, { render_record, render_markdown } from '@weaver/renderer-full';
+
+await init();
+
+const html = render_record(atUri, recordJson);
+```
+
+### Direct browser usage (no bundler)
+
+```html
+
+```
+
+### Node.js
+
+```javascript
+const { render_record } = require('@weaver/renderer-full/nodejs');
+```
+
+## API
+
+- `render_record(at_uri, record_json, fallback_author?, resolved_content?)` - Render an AT Protocol record
+- `render_markdown(markdown, resolved_content?)` - Render markdown to HTML
+- `render_math(latex, display_mode)` - Render LaTeX math to MathML
+- `render_faceted_text(text, facets_json)` - Render rich text with facets
diff --git a/crates/weaver-renderer-js/pkg/core/bundler/LICENSE b/crates/weaver-renderer-js/pkg/core/bundler/LICENSE
new file mode 100644
index 0000000..a612ad9
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/bundler/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer.d.ts b/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer.d.ts
new file mode 100644
index 0000000..6083277
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer.d.ts
@@ -0,0 +1,84 @@
+/* tslint:disable */
+/* eslint-disable */
+
+export class JsMathResult {
+ private constructor();
+ free(): void;
+ [Symbol.dispose](): void;
+ success: boolean;
+ html: string;
+ get error(): string | undefined;
+ set error(value: string | null | undefined);
+}
+
+export class JsResolvedContent {
+ free(): void;
+ [Symbol.dispose](): void;
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor();
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ */
+ addEmbed(at_uri: string, html: string): void;
+}
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ */
+export function create_resolved_content(): JsResolvedContent;
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init(): void;
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ */
+export function render_faceted_text(text: string, facets_json: any): string;
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_markdown(markdown: string, resolved_content?: JsResolvedContent | null): string;
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ */
+export function render_math(latex: string, display_mode: boolean): JsMathResult;
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_record(at_uri: string, record_json: any, fallback_author?: any | null, resolved_content?: JsResolvedContent | null): string;
diff --git a/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer.js b/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer.js
new file mode 100644
index 0000000..eb312d6
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer.js
@@ -0,0 +1,5 @@
+import * as wasm from "./weaver_renderer_bg.wasm";
+export * from "./weaver_renderer_bg.js";
+import { __wbg_set_wasm } from "./weaver_renderer_bg.js";
+__wbg_set_wasm(wasm);
+wasm.__wbindgen_start();
diff --git a/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer_bg.js b/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer_bg.js
new file mode 100644
index 0000000..b7532e5
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer_bg.js
@@ -0,0 +1,797 @@
+let wasm;
+export function __wbg_set_wasm(val) {
+ wasm = val;
+}
+
+function addHeapObject(obj) {
+ if (heap_next === heap.length) heap.push(heap.length + 1);
+ const idx = heap_next;
+ heap_next = heap[idx];
+
+ heap[idx] = obj;
+ return idx;
+}
+
+function _assertClass(instance, klass) {
+ if (!(instance instanceof klass)) {
+ throw new Error(`expected instance of ${klass.name}`);
+ }
+}
+
+function debugString(val) {
+ // primitive types
+ const type = typeof val;
+ if (type == 'number' || type == 'boolean' || val == null) {
+ return `${val}`;
+ }
+ if (type == 'string') {
+ return `"${val}"`;
+ }
+ if (type == 'symbol') {
+ const description = val.description;
+ if (description == null) {
+ return 'Symbol';
+ } else {
+ return `Symbol(${description})`;
+ }
+ }
+ if (type == 'function') {
+ const name = val.name;
+ if (typeof name == 'string' && name.length > 0) {
+ return `Function(${name})`;
+ } else {
+ return 'Function';
+ }
+ }
+ // objects
+ if (Array.isArray(val)) {
+ const length = val.length;
+ let debug = '[';
+ if (length > 0) {
+ debug += debugString(val[0]);
+ }
+ for(let i = 1; i < length; i++) {
+ debug += ', ' + debugString(val[i]);
+ }
+ debug += ']';
+ return debug;
+ }
+ // Test for built-in
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
+ let className;
+ if (builtInMatches && builtInMatches.length > 1) {
+ className = builtInMatches[1];
+ } else {
+ // Failed to match the standard '[object ClassName]'
+ return toString.call(val);
+ }
+ if (className == 'Object') {
+ // we're a user defined class or Object
+ // JSON.stringify avoids problems with cycles, and is generally much
+ // easier than looping through ownProperties of `val`.
+ try {
+ return 'Object(' + JSON.stringify(val) + ')';
+ } catch (_) {
+ return 'Object';
+ }
+ }
+ // errors
+ if (val instanceof Error) {
+ return `${val.name}: ${val.message}\n${val.stack}`;
+ }
+ // TODO we could test for more things here, like `Set`s and `Map`s.
+ return className;
+}
+
+function dropObject(idx) {
+ if (idx < 132) return;
+ heap[idx] = heap_next;
+ heap_next = idx;
+}
+
+function getArrayU8FromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
+}
+
+let cachedDataViewMemory0 = null;
+function getDataViewMemory0() {
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
+ }
+ return cachedDataViewMemory0;
+}
+
+function getStringFromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return decodeText(ptr, len);
+}
+
+let cachedUint8ArrayMemory0 = null;
+function getUint8ArrayMemory0() {
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
+ }
+ return cachedUint8ArrayMemory0;
+}
+
+function getObject(idx) { return heap[idx]; }
+
+function handleError(f, args) {
+ try {
+ return f.apply(this, args);
+ } catch (e) {
+ wasm.__wbindgen_export3(addHeapObject(e));
+ }
+}
+
+let heap = new Array(128).fill(undefined);
+heap.push(undefined, null, true, false);
+
+let heap_next = heap.length;
+
+function isLikeNone(x) {
+ return x === undefined || x === null;
+}
+
+function passStringToWasm0(arg, malloc, realloc) {
+ if (realloc === undefined) {
+ const buf = cachedTextEncoder.encode(arg);
+ const ptr = malloc(buf.length, 1) >>> 0;
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
+ WASM_VECTOR_LEN = buf.length;
+ return ptr;
+ }
+
+ let len = arg.length;
+ let ptr = malloc(len, 1) >>> 0;
+
+ const mem = getUint8ArrayMemory0();
+
+ let offset = 0;
+
+ for (; offset < len; offset++) {
+ const code = arg.charCodeAt(offset);
+ if (code > 0x7F) break;
+ mem[ptr + offset] = code;
+ }
+ if (offset !== len) {
+ if (offset !== 0) {
+ arg = arg.slice(offset);
+ }
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
+ const ret = cachedTextEncoder.encodeInto(arg, view);
+
+ offset += ret.written;
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
+ }
+
+ WASM_VECTOR_LEN = offset;
+ return ptr;
+}
+
+function takeObject(idx) {
+ const ret = getObject(idx);
+ dropObject(idx);
+ return ret;
+}
+
+let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+cachedTextDecoder.decode();
+const MAX_SAFARI_DECODE_BYTES = 2146435072;
+let numBytesDecoded = 0;
+function decodeText(ptr, len) {
+ numBytesDecoded += len;
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+ cachedTextDecoder.decode();
+ numBytesDecoded = len;
+ }
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
+}
+
+const cachedTextEncoder = new TextEncoder();
+
+if (!('encodeInto' in cachedTextEncoder)) {
+ cachedTextEncoder.encodeInto = function (arg, view) {
+ const buf = cachedTextEncoder.encode(arg);
+ view.set(buf);
+ return {
+ read: arg.length,
+ written: buf.length
+ };
+ }
+}
+
+let WASM_VECTOR_LEN = 0;
+
+const JsMathResultFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsmathresult_free(ptr >>> 0, 1));
+
+const JsResolvedContentFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsresolvedcontent_free(ptr >>> 0, 1));
+
+/**
+ * Result from rendering LaTeX math.
+ */
+export class JsMathResult {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsMathResult.prototype);
+ obj.__wbg_ptr = ptr;
+ JsMathResultFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsMathResultFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsmathresult_free(ptr, 0);
+ }
+ /**
+ * @returns {boolean}
+ */
+ get success() {
+ const ret = wasm.__wbg_get_jsmathresult_success(this.__wbg_ptr);
+ return ret !== 0;
+ }
+ /**
+ * @param {boolean} arg0
+ */
+ set success(arg0) {
+ wasm.__wbg_set_jsmathresult_success(this.__wbg_ptr, arg0);
+ }
+ /**
+ * @returns {string}
+ */
+ get html() {
+ let deferred1_0;
+ let deferred1_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_html(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ deferred1_0 = r0;
+ deferred1_1 = r1;
+ return getStringFromWasm0(r0, r1);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
+ }
+ }
+ /**
+ * @param {string} arg0
+ */
+ set html(arg0) {
+ const ptr0 = passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_html(this.__wbg_ptr, ptr0, len0);
+ }
+ /**
+ * @returns {string | undefined}
+ */
+ get error() {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_error(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ let v1;
+ if (r0 !== 0) {
+ v1 = getStringFromWasm0(r0, r1).slice();
+ wasm.__wbindgen_export4(r0, r1 * 1, 1);
+ }
+ return v1;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+ /**
+ * @param {string | null} [arg0]
+ */
+ set error(arg0) {
+ var ptr0 = isLikeNone(arg0) ? 0 : passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_error(this.__wbg_ptr, ptr0, len0);
+ }
+}
+if (Symbol.dispose) JsMathResult.prototype[Symbol.dispose] = JsMathResult.prototype.free;
+
+/**
+ * Pre-rendered embed content for synchronous rendering.
+ *
+ * Build this by calling `create_resolved_content()` and adding embeds
+ * with `resolved_content_add_embed()`.
+ */
+export class JsResolvedContent {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsResolvedContent.prototype);
+ obj.__wbg_ptr = ptr;
+ JsResolvedContentFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsResolvedContentFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsresolvedcontent_free(ptr, 0);
+ }
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor() {
+ const ret = wasm.create_resolved_content();
+ this.__wbg_ptr = ret >>> 0;
+ JsResolvedContentFinalization.register(this, this.__wbg_ptr, this);
+ return this;
+ }
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ * @param {string} at_uri
+ * @param {string} html
+ */
+ addEmbed(at_uri, html) {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(html, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.jsresolvedcontent_addEmbed(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ if (r1) {
+ throw takeObject(r0);
+ }
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+}
+if (Symbol.dispose) JsResolvedContent.prototype[Symbol.dispose] = JsResolvedContent.prototype.free;
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ * @returns {JsResolvedContent}
+ */
+export function create_resolved_content() {
+ const ret = wasm.create_resolved_content();
+ return JsResolvedContent.__wrap(ret);
+}
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init() {
+ wasm.init();
+}
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ * @param {string} text
+ * @param {any} facets_json
+ * @returns {string}
+ */
+export function render_faceted_text(text, facets_json) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(text, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.render_faceted_text(retptr, ptr0, len0, addHeapObject(facets_json));
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} markdown
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_markdown(markdown, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_markdown(retptr, ptr0, len0, ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ * @param {string} latex
+ * @param {boolean} display_mode
+ * @returns {JsMathResult}
+ */
+export function render_math(latex, display_mode) {
+ const ptr0 = passStringToWasm0(latex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ret = wasm.render_math(ptr0, len0, display_mode);
+ return JsMathResult.__wrap(ret);
+}
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} at_uri
+ * @param {any} record_json
+ * @param {any | null} [fallback_author]
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_record(at_uri, record_json, fallback_author, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_record(retptr, ptr0, len0, addHeapObject(record_json), isLikeNone(fallback_author) ? 0 : addHeapObject(fallback_author), ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+export function __wbg_Error_52673b7de5a0ca89(arg0, arg1) {
+ const ret = Error(getStringFromWasm0(arg0, arg1));
+ return addHeapObject(ret);
+};
+
+export function __wbg_Number_2d1dcfcf4ec51736(arg0) {
+ const ret = Number(getObject(arg0));
+ return ret;
+};
+
+export function __wbg_String_8f0eb39a4a4c2f66(arg0, arg1) {
+ const ret = String(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+export function __wbg___wbindgen_bigint_get_as_i64_6e32f5e6aff02e1d(arg0, arg1) {
+ const v = getObject(arg1);
+ const ret = typeof(v) === 'bigint' ? v : undefined;
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+};
+
+export function __wbg___wbindgen_boolean_get_dea25b33882b895b(arg0) {
+ const v = getObject(arg0);
+ const ret = typeof(v) === 'boolean' ? v : undefined;
+ return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
+};
+
+export function __wbg___wbindgen_debug_string_adfb662ae34724b6(arg0, arg1) {
+ const ret = debugString(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+export function __wbg___wbindgen_in_0d3e1e8f0c669317(arg0, arg1) {
+ const ret = getObject(arg0) in getObject(arg1);
+ return ret;
+};
+
+export function __wbg___wbindgen_is_bigint_0e1a2e3f55cfae27(arg0) {
+ const ret = typeof(getObject(arg0)) === 'bigint';
+ return ret;
+};
+
+export function __wbg___wbindgen_is_function_8d400b8b1af978cd(arg0) {
+ const ret = typeof(getObject(arg0)) === 'function';
+ return ret;
+};
+
+export function __wbg___wbindgen_is_object_ce774f3490692386(arg0) {
+ const val = getObject(arg0);
+ const ret = typeof(val) === 'object' && val !== null;
+ return ret;
+};
+
+export function __wbg___wbindgen_is_undefined_f6b95eab589e0269(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+};
+
+export function __wbg___wbindgen_jsval_eq_b6101cc9cef1fe36(arg0, arg1) {
+ const ret = getObject(arg0) === getObject(arg1);
+ return ret;
+};
+
+export function __wbg___wbindgen_jsval_loose_eq_766057600fdd1b0d(arg0, arg1) {
+ const ret = getObject(arg0) == getObject(arg1);
+ return ret;
+};
+
+export function __wbg___wbindgen_number_get_9619185a74197f95(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'number' ? obj : undefined;
+ getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+};
+
+export function __wbg___wbindgen_string_get_a2a31e16edf96e42(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'string' ? obj : undefined;
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+export function __wbg___wbindgen_throw_dd24417ed36fc46e(arg0, arg1) {
+ throw new Error(getStringFromWasm0(arg0, arg1));
+};
+
+export function __wbg_call_abb4ff46ce38be40() { return handleError(function (arg0, arg1) {
+ const ret = getObject(arg0).call(getObject(arg1));
+ return addHeapObject(ret);
+}, arguments) };
+
+export function __wbg_done_62ea16af4ce34b24(arg0) {
+ const ret = getObject(arg0).done;
+ return ret;
+};
+
+export function __wbg_entries_83c79938054e065f(arg0) {
+ const ret = Object.entries(getObject(arg0));
+ return addHeapObject(ret);
+};
+
+export function __wbg_error_7534b8e9a36f1ab4(arg0, arg1) {
+ let deferred0_0;
+ let deferred0_1;
+ try {
+ deferred0_0 = arg0;
+ deferred0_1 = arg1;
+ console.error(getStringFromWasm0(arg0, arg1));
+ } finally {
+ wasm.__wbindgen_export4(deferred0_0, deferred0_1, 1);
+ }
+};
+
+export function __wbg_get_6b7bd52aca3f9671(arg0, arg1) {
+ const ret = getObject(arg0)[arg1 >>> 0];
+ return addHeapObject(ret);
+};
+
+export function __wbg_get_af9dab7e9603ea93() { return handleError(function (arg0, arg1) {
+ const ret = Reflect.get(getObject(arg0), getObject(arg1));
+ return addHeapObject(ret);
+}, arguments) };
+
+export function __wbg_get_with_ref_key_1dc361bd10053bfe(arg0, arg1) {
+ const ret = getObject(arg0)[getObject(arg1)];
+ return addHeapObject(ret);
+};
+
+export function __wbg_instanceof_ArrayBuffer_f3320d2419cd0355(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof ArrayBuffer;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+export function __wbg_instanceof_Map_084be8da74364158(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Map;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+export function __wbg_instanceof_Uint8Array_da54ccc9d3e09434(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Uint8Array;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+export function __wbg_isArray_51fd9e6422c0a395(arg0) {
+ const ret = Array.isArray(getObject(arg0));
+ return ret;
+};
+
+export function __wbg_isSafeInteger_ae7d3f054d55fa16(arg0) {
+ const ret = Number.isSafeInteger(getObject(arg0));
+ return ret;
+};
+
+export function __wbg_iterator_27b7c8b35ab3e86b() {
+ const ret = Symbol.iterator;
+ return addHeapObject(ret);
+};
+
+export function __wbg_length_22ac23eaec9d8053(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+};
+
+export function __wbg_length_d45040a40c570362(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+};
+
+export function __wbg_new_6421f6084cc5bc5a(arg0) {
+ const ret = new Uint8Array(getObject(arg0));
+ return addHeapObject(ret);
+};
+
+export function __wbg_new_8a6f238a6ece86ea() {
+ const ret = new Error();
+ return addHeapObject(ret);
+};
+
+export function __wbg_next_138a17bbf04e926c(arg0) {
+ const ret = getObject(arg0).next;
+ return addHeapObject(ret);
+};
+
+export function __wbg_next_3cfe5c0fe2a4cc53() { return handleError(function (arg0) {
+ const ret = getObject(arg0).next();
+ return addHeapObject(ret);
+}, arguments) };
+
+export function __wbg_prototypesetcall_dfe9b766cdc1f1fd(arg0, arg1, arg2) {
+ Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
+};
+
+export function __wbg_stack_0ed75d68575b0f3c(arg0, arg1) {
+ const ret = getObject(arg1).stack;
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+export function __wbg_value_57b7b035e117f7ee(arg0) {
+ const ret = getObject(arg0).value;
+ return addHeapObject(ret);
+};
+
+export function __wbindgen_cast_2241b6af4c4b2941(arg0, arg1) {
+ // Cast intrinsic for `Ref(String) -> Externref`.
+ const ret = getStringFromWasm0(arg0, arg1);
+ return addHeapObject(ret);
+};
+
+export function __wbindgen_cast_4625c577ab2ec9ee(arg0) {
+ // Cast intrinsic for `U64 -> Externref`.
+ const ret = BigInt.asUintN(64, arg0);
+ return addHeapObject(ret);
+};
+
+export function __wbindgen_cast_9ae0607507abb057(arg0) {
+ // Cast intrinsic for `I64 -> Externref`.
+ const ret = arg0;
+ return addHeapObject(ret);
+};
+
+export function __wbindgen_object_clone_ref(arg0) {
+ const ret = getObject(arg0);
+ return addHeapObject(ret);
+};
+
+export function __wbindgen_object_drop_ref(arg0) {
+ takeObject(arg0);
+};
+
+export function __wbindgen_object_is_undefined(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+};
diff --git a/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer_bg.wasm.d.ts b/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer_bg.wasm.d.ts
new file mode 100644
index 0000000..16b3955
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/bundler/weaver_renderer_bg.wasm.d.ts
@@ -0,0 +1,25 @@
+/* tslint:disable */
+/* eslint-disable */
+export const memory: WebAssembly.Memory;
+export const __wbg_get_jsmathresult_error: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_html: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_success: (a: number) => number;
+export const __wbg_jsmathresult_free: (a: number, b: number) => void;
+export const __wbg_jsresolvedcontent_free: (a: number, b: number) => void;
+export const __wbg_set_jsmathresult_error: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_html: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_success: (a: number, b: number) => void;
+export const create_resolved_content: () => number;
+export const init: () => void;
+export const jsresolvedcontent_addEmbed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const render_faceted_text: (a: number, b: number, c: number, d: number) => void;
+export const render_markdown: (a: number, b: number, c: number, d: number) => void;
+export const render_math: (a: number, b: number, c: number) => number;
+export const render_record: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const jsresolvedcontent_new: () => number;
+export const __wbindgen_export: (a: number, b: number) => number;
+export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
+export const __wbindgen_export3: (a: number) => void;
+export const __wbindgen_export4: (a: number, b: number, c: number) => void;
+export const __wbindgen_add_to_stack_pointer: (a: number) => number;
+export const __wbindgen_start: () => void;
diff --git a/crates/weaver-renderer-js/pkg/core/deno/LICENSE b/crates/weaver-renderer-js/pkg/core/deno/LICENSE
new file mode 100644
index 0000000..a612ad9
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/deno/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/crates/weaver-renderer-js/pkg/core/deno/weaver_renderer.d.ts b/crates/weaver-renderer-js/pkg/core/deno/weaver_renderer.d.ts
new file mode 100644
index 0000000..6083277
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/deno/weaver_renderer.d.ts
@@ -0,0 +1,84 @@
+/* tslint:disable */
+/* eslint-disable */
+
+export class JsMathResult {
+ private constructor();
+ free(): void;
+ [Symbol.dispose](): void;
+ success: boolean;
+ html: string;
+ get error(): string | undefined;
+ set error(value: string | null | undefined);
+}
+
+export class JsResolvedContent {
+ free(): void;
+ [Symbol.dispose](): void;
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor();
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ */
+ addEmbed(at_uri: string, html: string): void;
+}
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ */
+export function create_resolved_content(): JsResolvedContent;
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init(): void;
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ */
+export function render_faceted_text(text: string, facets_json: any): string;
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_markdown(markdown: string, resolved_content?: JsResolvedContent | null): string;
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ */
+export function render_math(latex: string, display_mode: boolean): JsMathResult;
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_record(at_uri: string, record_json: any, fallback_author?: any | null, resolved_content?: JsResolvedContent | null): string;
diff --git a/crates/weaver-renderer-js/pkg/core/deno/weaver_renderer.js b/crates/weaver-renderer-js/pkg/core/deno/weaver_renderer.js
new file mode 100644
index 0000000..996b119
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/deno/weaver_renderer.js
@@ -0,0 +1,743 @@
+
+
+function addHeapObject(obj) {
+ if (heap_next === heap.length) heap.push(heap.length + 1);
+ const idx = heap_next;
+ heap_next = heap[idx];
+
+ heap[idx] = obj;
+ return idx;
+}
+
+function _assertClass(instance, klass) {
+ if (!(instance instanceof klass)) {
+ throw new Error(`expected instance of ${klass.name}`);
+ }
+}
+
+function debugString(val) {
+ // primitive types
+ const type = typeof val;
+ if (type == 'number' || type == 'boolean' || val == null) {
+ return `${val}`;
+ }
+ if (type == 'string') {
+ return `"${val}"`;
+ }
+ if (type == 'symbol') {
+ const description = val.description;
+ if (description == null) {
+ return 'Symbol';
+ } else {
+ return `Symbol(${description})`;
+ }
+ }
+ if (type == 'function') {
+ const name = val.name;
+ if (typeof name == 'string' && name.length > 0) {
+ return `Function(${name})`;
+ } else {
+ return 'Function';
+ }
+ }
+ // objects
+ if (Array.isArray(val)) {
+ const length = val.length;
+ let debug = '[';
+ if (length > 0) {
+ debug += debugString(val[0]);
+ }
+ for(let i = 1; i < length; i++) {
+ debug += ', ' + debugString(val[i]);
+ }
+ debug += ']';
+ return debug;
+ }
+ // Test for built-in
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
+ let className;
+ if (builtInMatches && builtInMatches.length > 1) {
+ className = builtInMatches[1];
+ } else {
+ // Failed to match the standard '[object ClassName]'
+ return toString.call(val);
+ }
+ if (className == 'Object') {
+ // we're a user defined class or Object
+ // JSON.stringify avoids problems with cycles, and is generally much
+ // easier than looping through ownProperties of `val`.
+ try {
+ return 'Object(' + JSON.stringify(val) + ')';
+ } catch (_) {
+ return 'Object';
+ }
+ }
+ // errors
+ if (val instanceof Error) {
+ return `${val.name}: ${val.message}\n${val.stack}`;
+ }
+ // TODO we could test for more things here, like `Set`s and `Map`s.
+ return className;
+}
+
+function dropObject(idx) {
+ if (idx < 132) return;
+ heap[idx] = heap_next;
+ heap_next = idx;
+}
+
+function getArrayU8FromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
+}
+
+let cachedDataViewMemory0 = null;
+function getDataViewMemory0() {
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
+ }
+ return cachedDataViewMemory0;
+}
+
+function getStringFromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return decodeText(ptr, len);
+}
+
+let cachedUint8ArrayMemory0 = null;
+function getUint8ArrayMemory0() {
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
+ }
+ return cachedUint8ArrayMemory0;
+}
+
+function getObject(idx) { return heap[idx]; }
+
+function handleError(f, args) {
+ try {
+ return f.apply(this, args);
+ } catch (e) {
+ wasm.__wbindgen_export3(addHeapObject(e));
+ }
+}
+
+let heap = new Array(128).fill(undefined);
+heap.push(undefined, null, true, false);
+
+let heap_next = heap.length;
+
+function isLikeNone(x) {
+ return x === undefined || x === null;
+}
+
+function passStringToWasm0(arg, malloc, realloc) {
+ if (realloc === undefined) {
+ const buf = cachedTextEncoder.encode(arg);
+ const ptr = malloc(buf.length, 1) >>> 0;
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
+ WASM_VECTOR_LEN = buf.length;
+ return ptr;
+ }
+
+ let len = arg.length;
+ let ptr = malloc(len, 1) >>> 0;
+
+ const mem = getUint8ArrayMemory0();
+
+ let offset = 0;
+
+ for (; offset < len; offset++) {
+ const code = arg.charCodeAt(offset);
+ if (code > 0x7F) break;
+ mem[ptr + offset] = code;
+ }
+ if (offset !== len) {
+ if (offset !== 0) {
+ arg = arg.slice(offset);
+ }
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
+ const ret = cachedTextEncoder.encodeInto(arg, view);
+
+ offset += ret.written;
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
+ }
+
+ WASM_VECTOR_LEN = offset;
+ return ptr;
+}
+
+function takeObject(idx) {
+ const ret = getObject(idx);
+ dropObject(idx);
+ return ret;
+}
+
+let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+cachedTextDecoder.decode();
+function decodeText(ptr, len) {
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
+}
+
+const cachedTextEncoder = new TextEncoder();
+
+let WASM_VECTOR_LEN = 0;
+
+const JsMathResultFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsmathresult_free(ptr >>> 0, 1));
+
+const JsResolvedContentFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsresolvedcontent_free(ptr >>> 0, 1));
+
+/**
+ * Result from rendering LaTeX math.
+ */
+export class JsMathResult {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsMathResult.prototype);
+ obj.__wbg_ptr = ptr;
+ JsMathResultFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsMathResultFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsmathresult_free(ptr, 0);
+ }
+ /**
+ * @returns {boolean}
+ */
+ get success() {
+ const ret = wasm.__wbg_get_jsmathresult_success(this.__wbg_ptr);
+ return ret !== 0;
+ }
+ /**
+ * @param {boolean} arg0
+ */
+ set success(arg0) {
+ wasm.__wbg_set_jsmathresult_success(this.__wbg_ptr, arg0);
+ }
+ /**
+ * @returns {string}
+ */
+ get html() {
+ let deferred1_0;
+ let deferred1_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_html(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ deferred1_0 = r0;
+ deferred1_1 = r1;
+ return getStringFromWasm0(r0, r1);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
+ }
+ }
+ /**
+ * @param {string} arg0
+ */
+ set html(arg0) {
+ const ptr0 = passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_html(this.__wbg_ptr, ptr0, len0);
+ }
+ /**
+ * @returns {string | undefined}
+ */
+ get error() {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_error(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ let v1;
+ if (r0 !== 0) {
+ v1 = getStringFromWasm0(r0, r1).slice();
+ wasm.__wbindgen_export4(r0, r1 * 1, 1);
+ }
+ return v1;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+ /**
+ * @param {string | null} [arg0]
+ */
+ set error(arg0) {
+ var ptr0 = isLikeNone(arg0) ? 0 : passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_error(this.__wbg_ptr, ptr0, len0);
+ }
+}
+if (Symbol.dispose) JsMathResult.prototype[Symbol.dispose] = JsMathResult.prototype.free;
+
+/**
+ * Pre-rendered embed content for synchronous rendering.
+ *
+ * Build this by calling `create_resolved_content()` and adding embeds
+ * with `resolved_content_add_embed()`.
+ */
+export class JsResolvedContent {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsResolvedContent.prototype);
+ obj.__wbg_ptr = ptr;
+ JsResolvedContentFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsResolvedContentFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsresolvedcontent_free(ptr, 0);
+ }
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor() {
+ const ret = wasm.create_resolved_content();
+ this.__wbg_ptr = ret >>> 0;
+ JsResolvedContentFinalization.register(this, this.__wbg_ptr, this);
+ return this;
+ }
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ * @param {string} at_uri
+ * @param {string} html
+ */
+ addEmbed(at_uri, html) {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(html, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.jsresolvedcontent_addEmbed(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ if (r1) {
+ throw takeObject(r0);
+ }
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+}
+if (Symbol.dispose) JsResolvedContent.prototype[Symbol.dispose] = JsResolvedContent.prototype.free;
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ * @returns {JsResolvedContent}
+ */
+export function create_resolved_content() {
+ const ret = wasm.create_resolved_content();
+ return JsResolvedContent.__wrap(ret);
+}
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init() {
+ wasm.init();
+}
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ * @param {string} text
+ * @param {any} facets_json
+ * @returns {string}
+ */
+export function render_faceted_text(text, facets_json) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(text, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.render_faceted_text(retptr, ptr0, len0, addHeapObject(facets_json));
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} markdown
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_markdown(markdown, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_markdown(retptr, ptr0, len0, ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ * @param {string} latex
+ * @param {boolean} display_mode
+ * @returns {JsMathResult}
+ */
+export function render_math(latex, display_mode) {
+ const ptr0 = passStringToWasm0(latex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ret = wasm.render_math(ptr0, len0, display_mode);
+ return JsMathResult.__wrap(ret);
+}
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} at_uri
+ * @param {any} record_json
+ * @param {any | null} [fallback_author]
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_record(at_uri, record_json, fallback_author, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_record(retptr, ptr0, len0, addHeapObject(record_json), isLikeNone(fallback_author) ? 0 : addHeapObject(fallback_author), ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+const imports = {
+ __wbindgen_placeholder__: {
+ __wbg_Error_52673b7de5a0ca89: function(arg0, arg1) {
+ const ret = Error(getStringFromWasm0(arg0, arg1));
+ return addHeapObject(ret);
+ },
+ __wbg_Number_2d1dcfcf4ec51736: function(arg0) {
+ const ret = Number(getObject(arg0));
+ return ret;
+ },
+ __wbg_String_8f0eb39a4a4c2f66: function(arg0, arg1) {
+ const ret = String(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ },
+ __wbg___wbindgen_bigint_get_as_i64_6e32f5e6aff02e1d: function(arg0, arg1) {
+ const v = getObject(arg1);
+ const ret = typeof(v) === 'bigint' ? v : undefined;
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+ },
+ __wbg___wbindgen_boolean_get_dea25b33882b895b: function(arg0) {
+ const v = getObject(arg0);
+ const ret = typeof(v) === 'boolean' ? v : undefined;
+ return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
+ },
+ __wbg___wbindgen_debug_string_adfb662ae34724b6: function(arg0, arg1) {
+ const ret = debugString(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ },
+ __wbg___wbindgen_in_0d3e1e8f0c669317: function(arg0, arg1) {
+ const ret = getObject(arg0) in getObject(arg1);
+ return ret;
+ },
+ __wbg___wbindgen_is_bigint_0e1a2e3f55cfae27: function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'bigint';
+ return ret;
+ },
+ __wbg___wbindgen_is_function_8d400b8b1af978cd: function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'function';
+ return ret;
+ },
+ __wbg___wbindgen_is_object_ce774f3490692386: function(arg0) {
+ const val = getObject(arg0);
+ const ret = typeof(val) === 'object' && val !== null;
+ return ret;
+ },
+ __wbg___wbindgen_is_undefined_f6b95eab589e0269: function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+ },
+ __wbg___wbindgen_jsval_eq_b6101cc9cef1fe36: function(arg0, arg1) {
+ const ret = getObject(arg0) === getObject(arg1);
+ return ret;
+ },
+ __wbg___wbindgen_jsval_loose_eq_766057600fdd1b0d: function(arg0, arg1) {
+ const ret = getObject(arg0) == getObject(arg1);
+ return ret;
+ },
+ __wbg___wbindgen_number_get_9619185a74197f95: function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'number' ? obj : undefined;
+ getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+ },
+ __wbg___wbindgen_string_get_a2a31e16edf96e42: function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'string' ? obj : undefined;
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ },
+ __wbg___wbindgen_throw_dd24417ed36fc46e: function(arg0, arg1) {
+ throw new Error(getStringFromWasm0(arg0, arg1));
+ },
+ __wbg_call_abb4ff46ce38be40: function() { return handleError(function (arg0, arg1) {
+ const ret = getObject(arg0).call(getObject(arg1));
+ return addHeapObject(ret);
+ }, arguments) },
+ __wbg_done_62ea16af4ce34b24: function(arg0) {
+ const ret = getObject(arg0).done;
+ return ret;
+ },
+ __wbg_entries_83c79938054e065f: function(arg0) {
+ const ret = Object.entries(getObject(arg0));
+ return addHeapObject(ret);
+ },
+ __wbg_error_7534b8e9a36f1ab4: function(arg0, arg1) {
+ let deferred0_0;
+ let deferred0_1;
+ try {
+ deferred0_0 = arg0;
+ deferred0_1 = arg1;
+ console.error(getStringFromWasm0(arg0, arg1));
+ } finally {
+ wasm.__wbindgen_export4(deferred0_0, deferred0_1, 1);
+ }
+ },
+ __wbg_get_6b7bd52aca3f9671: function(arg0, arg1) {
+ const ret = getObject(arg0)[arg1 >>> 0];
+ return addHeapObject(ret);
+ },
+ __wbg_get_af9dab7e9603ea93: function() { return handleError(function (arg0, arg1) {
+ const ret = Reflect.get(getObject(arg0), getObject(arg1));
+ return addHeapObject(ret);
+ }, arguments) },
+ __wbg_get_with_ref_key_1dc361bd10053bfe: function(arg0, arg1) {
+ const ret = getObject(arg0)[getObject(arg1)];
+ return addHeapObject(ret);
+ },
+ __wbg_instanceof_ArrayBuffer_f3320d2419cd0355: function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof ArrayBuffer;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ },
+ __wbg_instanceof_Map_084be8da74364158: function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Map;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ },
+ __wbg_instanceof_Uint8Array_da54ccc9d3e09434: function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Uint8Array;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ },
+ __wbg_isArray_51fd9e6422c0a395: function(arg0) {
+ const ret = Array.isArray(getObject(arg0));
+ return ret;
+ },
+ __wbg_isSafeInteger_ae7d3f054d55fa16: function(arg0) {
+ const ret = Number.isSafeInteger(getObject(arg0));
+ return ret;
+ },
+ __wbg_iterator_27b7c8b35ab3e86b: function() {
+ const ret = Symbol.iterator;
+ return addHeapObject(ret);
+ },
+ __wbg_length_22ac23eaec9d8053: function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+ },
+ __wbg_length_d45040a40c570362: function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+ },
+ __wbg_new_6421f6084cc5bc5a: function(arg0) {
+ const ret = new Uint8Array(getObject(arg0));
+ return addHeapObject(ret);
+ },
+ __wbg_new_8a6f238a6ece86ea: function() {
+ const ret = new Error();
+ return addHeapObject(ret);
+ },
+ __wbg_next_138a17bbf04e926c: function(arg0) {
+ const ret = getObject(arg0).next;
+ return addHeapObject(ret);
+ },
+ __wbg_next_3cfe5c0fe2a4cc53: function() { return handleError(function (arg0) {
+ const ret = getObject(arg0).next();
+ return addHeapObject(ret);
+ }, arguments) },
+ __wbg_prototypesetcall_dfe9b766cdc1f1fd: function(arg0, arg1, arg2) {
+ Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
+ },
+ __wbg_stack_0ed75d68575b0f3c: function(arg0, arg1) {
+ const ret = getObject(arg1).stack;
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ },
+ __wbg_value_57b7b035e117f7ee: function(arg0) {
+ const ret = getObject(arg0).value;
+ return addHeapObject(ret);
+ },
+ __wbindgen_cast_2241b6af4c4b2941: function(arg0, arg1) {
+ // Cast intrinsic for `Ref(String) -> Externref`.
+ const ret = getStringFromWasm0(arg0, arg1);
+ return addHeapObject(ret);
+ },
+ __wbindgen_cast_4625c577ab2ec9ee: function(arg0) {
+ // Cast intrinsic for `U64 -> Externref`.
+ const ret = BigInt.asUintN(64, arg0);
+ return addHeapObject(ret);
+ },
+ __wbindgen_cast_9ae0607507abb057: function(arg0) {
+ // Cast intrinsic for `I64 -> Externref`.
+ const ret = arg0;
+ return addHeapObject(ret);
+ },
+ __wbindgen_object_clone_ref: function(arg0) {
+ const ret = getObject(arg0);
+ return addHeapObject(ret);
+ },
+ __wbindgen_object_drop_ref: function(arg0) {
+ takeObject(arg0);
+ },
+ __wbindgen_object_is_undefined: function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+ },
+ },
+
+};
+
+const wasmUrl = new URL('weaver_renderer_bg.wasm', import.meta.url);
+const wasm = (await WebAssembly.instantiateStreaming(fetch(wasmUrl), imports)).instance.exports;
+export { wasm as __wasm };
+
+wasm.__wbindgen_start();
diff --git a/crates/weaver-renderer-js/pkg/core/deno/weaver_renderer_bg.wasm.d.ts b/crates/weaver-renderer-js/pkg/core/deno/weaver_renderer_bg.wasm.d.ts
new file mode 100644
index 0000000..16b3955
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/deno/weaver_renderer_bg.wasm.d.ts
@@ -0,0 +1,25 @@
+/* tslint:disable */
+/* eslint-disable */
+export const memory: WebAssembly.Memory;
+export const __wbg_get_jsmathresult_error: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_html: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_success: (a: number) => number;
+export const __wbg_jsmathresult_free: (a: number, b: number) => void;
+export const __wbg_jsresolvedcontent_free: (a: number, b: number) => void;
+export const __wbg_set_jsmathresult_error: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_html: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_success: (a: number, b: number) => void;
+export const create_resolved_content: () => number;
+export const init: () => void;
+export const jsresolvedcontent_addEmbed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const render_faceted_text: (a: number, b: number, c: number, d: number) => void;
+export const render_markdown: (a: number, b: number, c: number, d: number) => void;
+export const render_math: (a: number, b: number, c: number) => number;
+export const render_record: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const jsresolvedcontent_new: () => number;
+export const __wbindgen_export: (a: number, b: number) => number;
+export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
+export const __wbindgen_export3: (a: number) => void;
+export const __wbindgen_export4: (a: number, b: number, c: number) => void;
+export const __wbindgen_add_to_stack_pointer: (a: number) => number;
+export const __wbindgen_start: () => void;
diff --git a/crates/weaver-renderer-js/pkg/core/nodejs/LICENSE b/crates/weaver-renderer-js/pkg/core/nodejs/LICENSE
new file mode 100644
index 0000000..a612ad9
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/nodejs/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/crates/weaver-renderer-js/pkg/core/nodejs/weaver_renderer.d.ts b/crates/weaver-renderer-js/pkg/core/nodejs/weaver_renderer.d.ts
new file mode 100644
index 0000000..6083277
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/nodejs/weaver_renderer.d.ts
@@ -0,0 +1,84 @@
+/* tslint:disable */
+/* eslint-disable */
+
+export class JsMathResult {
+ private constructor();
+ free(): void;
+ [Symbol.dispose](): void;
+ success: boolean;
+ html: string;
+ get error(): string | undefined;
+ set error(value: string | null | undefined);
+}
+
+export class JsResolvedContent {
+ free(): void;
+ [Symbol.dispose](): void;
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor();
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ */
+ addEmbed(at_uri: string, html: string): void;
+}
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ */
+export function create_resolved_content(): JsResolvedContent;
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init(): void;
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ */
+export function render_faceted_text(text: string, facets_json: any): string;
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_markdown(markdown: string, resolved_content?: JsResolvedContent | null): string;
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ */
+export function render_math(latex: string, display_mode: boolean): JsMathResult;
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_record(at_uri: string, record_json: any, fallback_author?: any | null, resolved_content?: JsResolvedContent | null): string;
diff --git a/crates/weaver-renderer-js/pkg/core/nodejs/weaver_renderer.js b/crates/weaver-renderer-js/pkg/core/nodejs/weaver_renderer.js
new file mode 100644
index 0000000..86f6508
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/nodejs/weaver_renderer.js
@@ -0,0 +1,803 @@
+
+let imports = {};
+imports['__wbindgen_placeholder__'] = module.exports;
+
+function addHeapObject(obj) {
+ if (heap_next === heap.length) heap.push(heap.length + 1);
+ const idx = heap_next;
+ heap_next = heap[idx];
+
+ heap[idx] = obj;
+ return idx;
+}
+
+function _assertClass(instance, klass) {
+ if (!(instance instanceof klass)) {
+ throw new Error(`expected instance of ${klass.name}`);
+ }
+}
+
+function debugString(val) {
+ // primitive types
+ const type = typeof val;
+ if (type == 'number' || type == 'boolean' || val == null) {
+ return `${val}`;
+ }
+ if (type == 'string') {
+ return `"${val}"`;
+ }
+ if (type == 'symbol') {
+ const description = val.description;
+ if (description == null) {
+ return 'Symbol';
+ } else {
+ return `Symbol(${description})`;
+ }
+ }
+ if (type == 'function') {
+ const name = val.name;
+ if (typeof name == 'string' && name.length > 0) {
+ return `Function(${name})`;
+ } else {
+ return 'Function';
+ }
+ }
+ // objects
+ if (Array.isArray(val)) {
+ const length = val.length;
+ let debug = '[';
+ if (length > 0) {
+ debug += debugString(val[0]);
+ }
+ for(let i = 1; i < length; i++) {
+ debug += ', ' + debugString(val[i]);
+ }
+ debug += ']';
+ return debug;
+ }
+ // Test for built-in
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
+ let className;
+ if (builtInMatches && builtInMatches.length > 1) {
+ className = builtInMatches[1];
+ } else {
+ // Failed to match the standard '[object ClassName]'
+ return toString.call(val);
+ }
+ if (className == 'Object') {
+ // we're a user defined class or Object
+ // JSON.stringify avoids problems with cycles, and is generally much
+ // easier than looping through ownProperties of `val`.
+ try {
+ return 'Object(' + JSON.stringify(val) + ')';
+ } catch (_) {
+ return 'Object';
+ }
+ }
+ // errors
+ if (val instanceof Error) {
+ return `${val.name}: ${val.message}\n${val.stack}`;
+ }
+ // TODO we could test for more things here, like `Set`s and `Map`s.
+ return className;
+}
+
+function dropObject(idx) {
+ if (idx < 132) return;
+ heap[idx] = heap_next;
+ heap_next = idx;
+}
+
+function getArrayU8FromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
+}
+
+let cachedDataViewMemory0 = null;
+function getDataViewMemory0() {
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
+ }
+ return cachedDataViewMemory0;
+}
+
+function getStringFromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return decodeText(ptr, len);
+}
+
+let cachedUint8ArrayMemory0 = null;
+function getUint8ArrayMemory0() {
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
+ }
+ return cachedUint8ArrayMemory0;
+}
+
+function getObject(idx) { return heap[idx]; }
+
+function handleError(f, args) {
+ try {
+ return f.apply(this, args);
+ } catch (e) {
+ wasm.__wbindgen_export3(addHeapObject(e));
+ }
+}
+
+let heap = new Array(128).fill(undefined);
+heap.push(undefined, null, true, false);
+
+let heap_next = heap.length;
+
+function isLikeNone(x) {
+ return x === undefined || x === null;
+}
+
+function passStringToWasm0(arg, malloc, realloc) {
+ if (realloc === undefined) {
+ const buf = cachedTextEncoder.encode(arg);
+ const ptr = malloc(buf.length, 1) >>> 0;
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
+ WASM_VECTOR_LEN = buf.length;
+ return ptr;
+ }
+
+ let len = arg.length;
+ let ptr = malloc(len, 1) >>> 0;
+
+ const mem = getUint8ArrayMemory0();
+
+ let offset = 0;
+
+ for (; offset < len; offset++) {
+ const code = arg.charCodeAt(offset);
+ if (code > 0x7F) break;
+ mem[ptr + offset] = code;
+ }
+ if (offset !== len) {
+ if (offset !== 0) {
+ arg = arg.slice(offset);
+ }
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
+ const ret = cachedTextEncoder.encodeInto(arg, view);
+
+ offset += ret.written;
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
+ }
+
+ WASM_VECTOR_LEN = offset;
+ return ptr;
+}
+
+function takeObject(idx) {
+ const ret = getObject(idx);
+ dropObject(idx);
+ return ret;
+}
+
+let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+cachedTextDecoder.decode();
+function decodeText(ptr, len) {
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
+}
+
+const cachedTextEncoder = new TextEncoder();
+
+if (!('encodeInto' in cachedTextEncoder)) {
+ cachedTextEncoder.encodeInto = function (arg, view) {
+ const buf = cachedTextEncoder.encode(arg);
+ view.set(buf);
+ return {
+ read: arg.length,
+ written: buf.length
+ };
+ }
+}
+
+let WASM_VECTOR_LEN = 0;
+
+const JsMathResultFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsmathresult_free(ptr >>> 0, 1));
+
+const JsResolvedContentFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsresolvedcontent_free(ptr >>> 0, 1));
+
+/**
+ * Result from rendering LaTeX math.
+ */
+class JsMathResult {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsMathResult.prototype);
+ obj.__wbg_ptr = ptr;
+ JsMathResultFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsMathResultFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsmathresult_free(ptr, 0);
+ }
+ /**
+ * @returns {boolean}
+ */
+ get success() {
+ const ret = wasm.__wbg_get_jsmathresult_success(this.__wbg_ptr);
+ return ret !== 0;
+ }
+ /**
+ * @param {boolean} arg0
+ */
+ set success(arg0) {
+ wasm.__wbg_set_jsmathresult_success(this.__wbg_ptr, arg0);
+ }
+ /**
+ * @returns {string}
+ */
+ get html() {
+ let deferred1_0;
+ let deferred1_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_html(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ deferred1_0 = r0;
+ deferred1_1 = r1;
+ return getStringFromWasm0(r0, r1);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
+ }
+ }
+ /**
+ * @param {string} arg0
+ */
+ set html(arg0) {
+ const ptr0 = passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_html(this.__wbg_ptr, ptr0, len0);
+ }
+ /**
+ * @returns {string | undefined}
+ */
+ get error() {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_error(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ let v1;
+ if (r0 !== 0) {
+ v1 = getStringFromWasm0(r0, r1).slice();
+ wasm.__wbindgen_export4(r0, r1 * 1, 1);
+ }
+ return v1;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+ /**
+ * @param {string | null} [arg0]
+ */
+ set error(arg0) {
+ var ptr0 = isLikeNone(arg0) ? 0 : passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_error(this.__wbg_ptr, ptr0, len0);
+ }
+}
+if (Symbol.dispose) JsMathResult.prototype[Symbol.dispose] = JsMathResult.prototype.free;
+exports.JsMathResult = JsMathResult;
+
+/**
+ * Pre-rendered embed content for synchronous rendering.
+ *
+ * Build this by calling `create_resolved_content()` and adding embeds
+ * with `resolved_content_add_embed()`.
+ */
+class JsResolvedContent {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsResolvedContent.prototype);
+ obj.__wbg_ptr = ptr;
+ JsResolvedContentFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsResolvedContentFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsresolvedcontent_free(ptr, 0);
+ }
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor() {
+ const ret = wasm.create_resolved_content();
+ this.__wbg_ptr = ret >>> 0;
+ JsResolvedContentFinalization.register(this, this.__wbg_ptr, this);
+ return this;
+ }
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ * @param {string} at_uri
+ * @param {string} html
+ */
+ addEmbed(at_uri, html) {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(html, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.jsresolvedcontent_addEmbed(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ if (r1) {
+ throw takeObject(r0);
+ }
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+}
+if (Symbol.dispose) JsResolvedContent.prototype[Symbol.dispose] = JsResolvedContent.prototype.free;
+exports.JsResolvedContent = JsResolvedContent;
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ * @returns {JsResolvedContent}
+ */
+function create_resolved_content() {
+ const ret = wasm.create_resolved_content();
+ return JsResolvedContent.__wrap(ret);
+}
+exports.create_resolved_content = create_resolved_content;
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+function init() {
+ wasm.init();
+}
+exports.init = init;
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ * @param {string} text
+ * @param {any} facets_json
+ * @returns {string}
+ */
+function render_faceted_text(text, facets_json) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(text, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.render_faceted_text(retptr, ptr0, len0, addHeapObject(facets_json));
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
+ }
+}
+exports.render_faceted_text = render_faceted_text;
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} markdown
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+function render_markdown(markdown, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_markdown(retptr, ptr0, len0, ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+exports.render_markdown = render_markdown;
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ * @param {string} latex
+ * @param {boolean} display_mode
+ * @returns {JsMathResult}
+ */
+function render_math(latex, display_mode) {
+ const ptr0 = passStringToWasm0(latex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ret = wasm.render_math(ptr0, len0, display_mode);
+ return JsMathResult.__wrap(ret);
+}
+exports.render_math = render_math;
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} at_uri
+ * @param {any} record_json
+ * @param {any | null} [fallback_author]
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+function render_record(at_uri, record_json, fallback_author, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_record(retptr, ptr0, len0, addHeapObject(record_json), isLikeNone(fallback_author) ? 0 : addHeapObject(fallback_author), ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+exports.render_record = render_record;
+
+exports.__wbg_Error_52673b7de5a0ca89 = function(arg0, arg1) {
+ const ret = Error(getStringFromWasm0(arg0, arg1));
+ return addHeapObject(ret);
+};
+
+exports.__wbg_Number_2d1dcfcf4ec51736 = function(arg0) {
+ const ret = Number(getObject(arg0));
+ return ret;
+};
+
+exports.__wbg_String_8f0eb39a4a4c2f66 = function(arg0, arg1) {
+ const ret = String(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+exports.__wbg___wbindgen_bigint_get_as_i64_6e32f5e6aff02e1d = function(arg0, arg1) {
+ const v = getObject(arg1);
+ const ret = typeof(v) === 'bigint' ? v : undefined;
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+};
+
+exports.__wbg___wbindgen_boolean_get_dea25b33882b895b = function(arg0) {
+ const v = getObject(arg0);
+ const ret = typeof(v) === 'boolean' ? v : undefined;
+ return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
+};
+
+exports.__wbg___wbindgen_debug_string_adfb662ae34724b6 = function(arg0, arg1) {
+ const ret = debugString(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+exports.__wbg___wbindgen_in_0d3e1e8f0c669317 = function(arg0, arg1) {
+ const ret = getObject(arg0) in getObject(arg1);
+ return ret;
+};
+
+exports.__wbg___wbindgen_is_bigint_0e1a2e3f55cfae27 = function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'bigint';
+ return ret;
+};
+
+exports.__wbg___wbindgen_is_function_8d400b8b1af978cd = function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'function';
+ return ret;
+};
+
+exports.__wbg___wbindgen_is_object_ce774f3490692386 = function(arg0) {
+ const val = getObject(arg0);
+ const ret = typeof(val) === 'object' && val !== null;
+ return ret;
+};
+
+exports.__wbg___wbindgen_is_undefined_f6b95eab589e0269 = function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+};
+
+exports.__wbg___wbindgen_jsval_eq_b6101cc9cef1fe36 = function(arg0, arg1) {
+ const ret = getObject(arg0) === getObject(arg1);
+ return ret;
+};
+
+exports.__wbg___wbindgen_jsval_loose_eq_766057600fdd1b0d = function(arg0, arg1) {
+ const ret = getObject(arg0) == getObject(arg1);
+ return ret;
+};
+
+exports.__wbg___wbindgen_number_get_9619185a74197f95 = function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'number' ? obj : undefined;
+ getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+};
+
+exports.__wbg___wbindgen_string_get_a2a31e16edf96e42 = function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'string' ? obj : undefined;
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+exports.__wbg___wbindgen_throw_dd24417ed36fc46e = function(arg0, arg1) {
+ throw new Error(getStringFromWasm0(arg0, arg1));
+};
+
+exports.__wbg_call_abb4ff46ce38be40 = function() { return handleError(function (arg0, arg1) {
+ const ret = getObject(arg0).call(getObject(arg1));
+ return addHeapObject(ret);
+}, arguments) };
+
+exports.__wbg_done_62ea16af4ce34b24 = function(arg0) {
+ const ret = getObject(arg0).done;
+ return ret;
+};
+
+exports.__wbg_entries_83c79938054e065f = function(arg0) {
+ const ret = Object.entries(getObject(arg0));
+ return addHeapObject(ret);
+};
+
+exports.__wbg_error_7534b8e9a36f1ab4 = function(arg0, arg1) {
+ let deferred0_0;
+ let deferred0_1;
+ try {
+ deferred0_0 = arg0;
+ deferred0_1 = arg1;
+ console.error(getStringFromWasm0(arg0, arg1));
+ } finally {
+ wasm.__wbindgen_export4(deferred0_0, deferred0_1, 1);
+ }
+};
+
+exports.__wbg_get_6b7bd52aca3f9671 = function(arg0, arg1) {
+ const ret = getObject(arg0)[arg1 >>> 0];
+ return addHeapObject(ret);
+};
+
+exports.__wbg_get_af9dab7e9603ea93 = function() { return handleError(function (arg0, arg1) {
+ const ret = Reflect.get(getObject(arg0), getObject(arg1));
+ return addHeapObject(ret);
+}, arguments) };
+
+exports.__wbg_get_with_ref_key_1dc361bd10053bfe = function(arg0, arg1) {
+ const ret = getObject(arg0)[getObject(arg1)];
+ return addHeapObject(ret);
+};
+
+exports.__wbg_instanceof_ArrayBuffer_f3320d2419cd0355 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof ArrayBuffer;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+exports.__wbg_instanceof_Map_084be8da74364158 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Map;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+exports.__wbg_instanceof_Uint8Array_da54ccc9d3e09434 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Uint8Array;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+exports.__wbg_isArray_51fd9e6422c0a395 = function(arg0) {
+ const ret = Array.isArray(getObject(arg0));
+ return ret;
+};
+
+exports.__wbg_isSafeInteger_ae7d3f054d55fa16 = function(arg0) {
+ const ret = Number.isSafeInteger(getObject(arg0));
+ return ret;
+};
+
+exports.__wbg_iterator_27b7c8b35ab3e86b = function() {
+ const ret = Symbol.iterator;
+ return addHeapObject(ret);
+};
+
+exports.__wbg_length_22ac23eaec9d8053 = function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+};
+
+exports.__wbg_length_d45040a40c570362 = function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+};
+
+exports.__wbg_new_6421f6084cc5bc5a = function(arg0) {
+ const ret = new Uint8Array(getObject(arg0));
+ return addHeapObject(ret);
+};
+
+exports.__wbg_new_8a6f238a6ece86ea = function() {
+ const ret = new Error();
+ return addHeapObject(ret);
+};
+
+exports.__wbg_next_138a17bbf04e926c = function(arg0) {
+ const ret = getObject(arg0).next;
+ return addHeapObject(ret);
+};
+
+exports.__wbg_next_3cfe5c0fe2a4cc53 = function() { return handleError(function (arg0) {
+ const ret = getObject(arg0).next();
+ return addHeapObject(ret);
+}, arguments) };
+
+exports.__wbg_prototypesetcall_dfe9b766cdc1f1fd = function(arg0, arg1, arg2) {
+ Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
+};
+
+exports.__wbg_stack_0ed75d68575b0f3c = function(arg0, arg1) {
+ const ret = getObject(arg1).stack;
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+exports.__wbg_value_57b7b035e117f7ee = function(arg0) {
+ const ret = getObject(arg0).value;
+ return addHeapObject(ret);
+};
+
+exports.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
+ // Cast intrinsic for `Ref(String) -> Externref`.
+ const ret = getStringFromWasm0(arg0, arg1);
+ return addHeapObject(ret);
+};
+
+exports.__wbindgen_cast_4625c577ab2ec9ee = function(arg0) {
+ // Cast intrinsic for `U64 -> Externref`.
+ const ret = BigInt.asUintN(64, arg0);
+ return addHeapObject(ret);
+};
+
+exports.__wbindgen_cast_9ae0607507abb057 = function(arg0) {
+ // Cast intrinsic for `I64 -> Externref`.
+ const ret = arg0;
+ return addHeapObject(ret);
+};
+
+exports.__wbindgen_object_clone_ref = function(arg0) {
+ const ret = getObject(arg0);
+ return addHeapObject(ret);
+};
+
+exports.__wbindgen_object_drop_ref = function(arg0) {
+ takeObject(arg0);
+};
+
+exports.__wbindgen_object_is_undefined = function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+};
+
+const wasmPath = `${__dirname}/weaver_renderer_bg.wasm`;
+const wasmBytes = require('fs').readFileSync(wasmPath);
+const wasmModule = new WebAssembly.Module(wasmBytes);
+const wasm = exports.__wasm = new WebAssembly.Instance(wasmModule, imports).exports;
+
+wasm.__wbindgen_start();
diff --git a/crates/weaver-renderer-js/pkg/core/nodejs/weaver_renderer_bg.wasm.d.ts b/crates/weaver-renderer-js/pkg/core/nodejs/weaver_renderer_bg.wasm.d.ts
new file mode 100644
index 0000000..16b3955
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/nodejs/weaver_renderer_bg.wasm.d.ts
@@ -0,0 +1,25 @@
+/* tslint:disable */
+/* eslint-disable */
+export const memory: WebAssembly.Memory;
+export const __wbg_get_jsmathresult_error: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_html: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_success: (a: number) => number;
+export const __wbg_jsmathresult_free: (a: number, b: number) => void;
+export const __wbg_jsresolvedcontent_free: (a: number, b: number) => void;
+export const __wbg_set_jsmathresult_error: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_html: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_success: (a: number, b: number) => void;
+export const create_resolved_content: () => number;
+export const init: () => void;
+export const jsresolvedcontent_addEmbed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const render_faceted_text: (a: number, b: number, c: number, d: number) => void;
+export const render_markdown: (a: number, b: number, c: number, d: number) => void;
+export const render_math: (a: number, b: number, c: number) => number;
+export const render_record: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const jsresolvedcontent_new: () => number;
+export const __wbindgen_export: (a: number, b: number) => number;
+export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
+export const __wbindgen_export3: (a: number) => void;
+export const __wbindgen_export4: (a: number, b: number, c: number) => void;
+export const __wbindgen_add_to_stack_pointer: (a: number) => number;
+export const __wbindgen_start: () => void;
diff --git a/crates/weaver-renderer-js/pkg/core/package.json b/crates/weaver-renderer-js/pkg/core/package.json
new file mode 100644
index 0000000..1458016
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "@weaver.sh/renderer-core",
+ "version": "0.1.1",
+ "description": "AT Protocol record renderer (lightweight, no syntax highlighting)",
+ "license": "MPL-2.0",
+ "repository": {
+ "type": "git",
+ "url": "https://tangled.org/nonbinary.computer/weaver"
+ },
+ "keywords": ["atproto", "bluesky", "markdown", "renderer", "wasm"],
+ "main": "nodejs/weaver_renderer.js",
+ "module": "bundler/weaver_renderer.js",
+ "browser": "web/weaver_renderer.js",
+ "types": "bundler/weaver_renderer.d.ts",
+ "exports": {
+ ".": {
+ "deno": "./deno/weaver_renderer.js",
+ "node": {
+ "import": "./nodejs/weaver_renderer.js",
+ "require": "./nodejs/weaver_renderer.js"
+ },
+ "browser": {
+ "import": "./web/weaver_renderer.js"
+ },
+ "default": "./bundler/weaver_renderer.js"
+ },
+ "./bundler": {
+ "import": "./bundler/weaver_renderer.js",
+ "types": "./bundler/weaver_renderer.d.ts"
+ },
+ "./web": {
+ "import": "./web/weaver_renderer.js",
+ "types": "./web/weaver_renderer.d.ts"
+ },
+ "./nodejs": {
+ "import": "./nodejs/weaver_renderer.js",
+ "require": "./nodejs/weaver_renderer.js",
+ "types": "./nodejs/weaver_renderer.d.ts"
+ },
+ "./deno": {
+ "import": "./deno/weaver_renderer.js",
+ "types": "./deno/weaver_renderer.d.ts"
+ }
+ },
+ "files": [
+ "bundler/",
+ "web/",
+ "nodejs/",
+ "deno/",
+ "README.md"
+ ]
+}
diff --git a/crates/weaver-renderer-js/pkg/core/web/LICENSE b/crates/weaver-renderer-js/pkg/core/web/LICENSE
new file mode 100644
index 0000000..a612ad9
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/web/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/crates/weaver-renderer-js/pkg/core/web/weaver_renderer.d.ts b/crates/weaver-renderer-js/pkg/core/web/weaver_renderer.d.ts
new file mode 100644
index 0000000..d564d73
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/web/weaver_renderer.d.ts
@@ -0,0 +1,134 @@
+/* tslint:disable */
+/* eslint-disable */
+
+export class JsMathResult {
+ private constructor();
+ free(): void;
+ [Symbol.dispose](): void;
+ success: boolean;
+ html: string;
+ get error(): string | undefined;
+ set error(value: string | null | undefined);
+}
+
+export class JsResolvedContent {
+ free(): void;
+ [Symbol.dispose](): void;
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor();
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ */
+ addEmbed(at_uri: string, html: string): void;
+}
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ */
+export function create_resolved_content(): JsResolvedContent;
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init(): void;
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ */
+export function render_faceted_text(text: string, facets_json: any): string;
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_markdown(markdown: string, resolved_content?: JsResolvedContent | null): string;
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ */
+export function render_math(latex: string, display_mode: boolean): JsMathResult;
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_record(at_uri: string, record_json: any, fallback_author?: any | null, resolved_content?: JsResolvedContent | null): string;
+
+export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
+
+export interface InitOutput {
+ readonly memory: WebAssembly.Memory;
+ readonly __wbg_get_jsmathresult_error: (a: number, b: number) => void;
+ readonly __wbg_get_jsmathresult_html: (a: number, b: number) => void;
+ readonly __wbg_get_jsmathresult_success: (a: number) => number;
+ readonly __wbg_jsmathresult_free: (a: number, b: number) => void;
+ readonly __wbg_jsresolvedcontent_free: (a: number, b: number) => void;
+ readonly __wbg_set_jsmathresult_error: (a: number, b: number, c: number) => void;
+ readonly __wbg_set_jsmathresult_html: (a: number, b: number, c: number) => void;
+ readonly __wbg_set_jsmathresult_success: (a: number, b: number) => void;
+ readonly create_resolved_content: () => number;
+ readonly init: () => void;
+ readonly jsresolvedcontent_addEmbed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+ readonly render_faceted_text: (a: number, b: number, c: number, d: number) => void;
+ readonly render_markdown: (a: number, b: number, c: number, d: number) => void;
+ readonly render_math: (a: number, b: number, c: number) => number;
+ readonly render_record: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+ readonly jsresolvedcontent_new: () => number;
+ readonly __wbindgen_export: (a: number, b: number) => number;
+ readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
+ readonly __wbindgen_export3: (a: number) => void;
+ readonly __wbindgen_export4: (a: number, b: number, c: number) => void;
+ readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
+ readonly __wbindgen_start: () => void;
+}
+
+export type SyncInitInput = BufferSource | WebAssembly.Module;
+
+/**
+* Instantiates the given `module`, which can either be bytes or
+* a precompiled `WebAssembly.Module`.
+*
+* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
+*
+* @returns {InitOutput}
+*/
+export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
+
+/**
+* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
+* for everything else, calls `WebAssembly.instantiate` directly.
+*
+* @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated.
+*
+* @returns {Promise}
+*/
+export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise;
diff --git a/crates/weaver-renderer-js/pkg/core/web/weaver_renderer.js b/crates/weaver-renderer-js/pkg/core/web/weaver_renderer.js
new file mode 100644
index 0000000..a2bfbff
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/web/weaver_renderer.js
@@ -0,0 +1,849 @@
+let wasm;
+
+function addHeapObject(obj) {
+ if (heap_next === heap.length) heap.push(heap.length + 1);
+ const idx = heap_next;
+ heap_next = heap[idx];
+
+ heap[idx] = obj;
+ return idx;
+}
+
+function _assertClass(instance, klass) {
+ if (!(instance instanceof klass)) {
+ throw new Error(`expected instance of ${klass.name}`);
+ }
+}
+
+function debugString(val) {
+ // primitive types
+ const type = typeof val;
+ if (type == 'number' || type == 'boolean' || val == null) {
+ return `${val}`;
+ }
+ if (type == 'string') {
+ return `"${val}"`;
+ }
+ if (type == 'symbol') {
+ const description = val.description;
+ if (description == null) {
+ return 'Symbol';
+ } else {
+ return `Symbol(${description})`;
+ }
+ }
+ if (type == 'function') {
+ const name = val.name;
+ if (typeof name == 'string' && name.length > 0) {
+ return `Function(${name})`;
+ } else {
+ return 'Function';
+ }
+ }
+ // objects
+ if (Array.isArray(val)) {
+ const length = val.length;
+ let debug = '[';
+ if (length > 0) {
+ debug += debugString(val[0]);
+ }
+ for(let i = 1; i < length; i++) {
+ debug += ', ' + debugString(val[i]);
+ }
+ debug += ']';
+ return debug;
+ }
+ // Test for built-in
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
+ let className;
+ if (builtInMatches && builtInMatches.length > 1) {
+ className = builtInMatches[1];
+ } else {
+ // Failed to match the standard '[object ClassName]'
+ return toString.call(val);
+ }
+ if (className == 'Object') {
+ // we're a user defined class or Object
+ // JSON.stringify avoids problems with cycles, and is generally much
+ // easier than looping through ownProperties of `val`.
+ try {
+ return 'Object(' + JSON.stringify(val) + ')';
+ } catch (_) {
+ return 'Object';
+ }
+ }
+ // errors
+ if (val instanceof Error) {
+ return `${val.name}: ${val.message}\n${val.stack}`;
+ }
+ // TODO we could test for more things here, like `Set`s and `Map`s.
+ return className;
+}
+
+function dropObject(idx) {
+ if (idx < 132) return;
+ heap[idx] = heap_next;
+ heap_next = idx;
+}
+
+function getArrayU8FromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
+}
+
+let cachedDataViewMemory0 = null;
+function getDataViewMemory0() {
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
+ }
+ return cachedDataViewMemory0;
+}
+
+function getStringFromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return decodeText(ptr, len);
+}
+
+let cachedUint8ArrayMemory0 = null;
+function getUint8ArrayMemory0() {
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
+ }
+ return cachedUint8ArrayMemory0;
+}
+
+function getObject(idx) { return heap[idx]; }
+
+function handleError(f, args) {
+ try {
+ return f.apply(this, args);
+ } catch (e) {
+ wasm.__wbindgen_export3(addHeapObject(e));
+ }
+}
+
+let heap = new Array(128).fill(undefined);
+heap.push(undefined, null, true, false);
+
+let heap_next = heap.length;
+
+function isLikeNone(x) {
+ return x === undefined || x === null;
+}
+
+function passStringToWasm0(arg, malloc, realloc) {
+ if (realloc === undefined) {
+ const buf = cachedTextEncoder.encode(arg);
+ const ptr = malloc(buf.length, 1) >>> 0;
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
+ WASM_VECTOR_LEN = buf.length;
+ return ptr;
+ }
+
+ let len = arg.length;
+ let ptr = malloc(len, 1) >>> 0;
+
+ const mem = getUint8ArrayMemory0();
+
+ let offset = 0;
+
+ for (; offset < len; offset++) {
+ const code = arg.charCodeAt(offset);
+ if (code > 0x7F) break;
+ mem[ptr + offset] = code;
+ }
+ if (offset !== len) {
+ if (offset !== 0) {
+ arg = arg.slice(offset);
+ }
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
+ const ret = cachedTextEncoder.encodeInto(arg, view);
+
+ offset += ret.written;
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
+ }
+
+ WASM_VECTOR_LEN = offset;
+ return ptr;
+}
+
+function takeObject(idx) {
+ const ret = getObject(idx);
+ dropObject(idx);
+ return ret;
+}
+
+let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+cachedTextDecoder.decode();
+const MAX_SAFARI_DECODE_BYTES = 2146435072;
+let numBytesDecoded = 0;
+function decodeText(ptr, len) {
+ numBytesDecoded += len;
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+ cachedTextDecoder.decode();
+ numBytesDecoded = len;
+ }
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
+}
+
+const cachedTextEncoder = new TextEncoder();
+
+if (!('encodeInto' in cachedTextEncoder)) {
+ cachedTextEncoder.encodeInto = function (arg, view) {
+ const buf = cachedTextEncoder.encode(arg);
+ view.set(buf);
+ return {
+ read: arg.length,
+ written: buf.length
+ };
+ }
+}
+
+let WASM_VECTOR_LEN = 0;
+
+const JsMathResultFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsmathresult_free(ptr >>> 0, 1));
+
+const JsResolvedContentFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsresolvedcontent_free(ptr >>> 0, 1));
+
+/**
+ * Result from rendering LaTeX math.
+ */
+export class JsMathResult {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsMathResult.prototype);
+ obj.__wbg_ptr = ptr;
+ JsMathResultFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsMathResultFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsmathresult_free(ptr, 0);
+ }
+ /**
+ * @returns {boolean}
+ */
+ get success() {
+ const ret = wasm.__wbg_get_jsmathresult_success(this.__wbg_ptr);
+ return ret !== 0;
+ }
+ /**
+ * @param {boolean} arg0
+ */
+ set success(arg0) {
+ wasm.__wbg_set_jsmathresult_success(this.__wbg_ptr, arg0);
+ }
+ /**
+ * @returns {string}
+ */
+ get html() {
+ let deferred1_0;
+ let deferred1_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_html(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ deferred1_0 = r0;
+ deferred1_1 = r1;
+ return getStringFromWasm0(r0, r1);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
+ }
+ }
+ /**
+ * @param {string} arg0
+ */
+ set html(arg0) {
+ const ptr0 = passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_html(this.__wbg_ptr, ptr0, len0);
+ }
+ /**
+ * @returns {string | undefined}
+ */
+ get error() {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_error(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ let v1;
+ if (r0 !== 0) {
+ v1 = getStringFromWasm0(r0, r1).slice();
+ wasm.__wbindgen_export4(r0, r1 * 1, 1);
+ }
+ return v1;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+ /**
+ * @param {string | null} [arg0]
+ */
+ set error(arg0) {
+ var ptr0 = isLikeNone(arg0) ? 0 : passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_error(this.__wbg_ptr, ptr0, len0);
+ }
+}
+if (Symbol.dispose) JsMathResult.prototype[Symbol.dispose] = JsMathResult.prototype.free;
+
+/**
+ * Pre-rendered embed content for synchronous rendering.
+ *
+ * Build this by calling `create_resolved_content()` and adding embeds
+ * with `resolved_content_add_embed()`.
+ */
+export class JsResolvedContent {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsResolvedContent.prototype);
+ obj.__wbg_ptr = ptr;
+ JsResolvedContentFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsResolvedContentFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsresolvedcontent_free(ptr, 0);
+ }
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor() {
+ const ret = wasm.create_resolved_content();
+ this.__wbg_ptr = ret >>> 0;
+ JsResolvedContentFinalization.register(this, this.__wbg_ptr, this);
+ return this;
+ }
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ * @param {string} at_uri
+ * @param {string} html
+ */
+ addEmbed(at_uri, html) {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(html, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.jsresolvedcontent_addEmbed(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ if (r1) {
+ throw takeObject(r0);
+ }
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+}
+if (Symbol.dispose) JsResolvedContent.prototype[Symbol.dispose] = JsResolvedContent.prototype.free;
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ * @returns {JsResolvedContent}
+ */
+export function create_resolved_content() {
+ const ret = wasm.create_resolved_content();
+ return JsResolvedContent.__wrap(ret);
+}
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init() {
+ wasm.init();
+}
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ * @param {string} text
+ * @param {any} facets_json
+ * @returns {string}
+ */
+export function render_faceted_text(text, facets_json) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(text, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.render_faceted_text(retptr, ptr0, len0, addHeapObject(facets_json));
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} markdown
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_markdown(markdown, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_markdown(retptr, ptr0, len0, ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ * @param {string} latex
+ * @param {boolean} display_mode
+ * @returns {JsMathResult}
+ */
+export function render_math(latex, display_mode) {
+ const ptr0 = passStringToWasm0(latex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ret = wasm.render_math(ptr0, len0, display_mode);
+ return JsMathResult.__wrap(ret);
+}
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} at_uri
+ * @param {any} record_json
+ * @param {any | null} [fallback_author]
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_record(at_uri, record_json, fallback_author, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_record(retptr, ptr0, len0, addHeapObject(record_json), isLikeNone(fallback_author) ? 0 : addHeapObject(fallback_author), ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+const EXPECTED_RESPONSE_TYPES = new Set(['basic', 'cors', 'default']);
+
+async function __wbg_load(module, imports) {
+ if (typeof Response === 'function' && module instanceof Response) {
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
+ try {
+ return await WebAssembly.instantiateStreaming(module, imports);
+ } catch (e) {
+ const validResponse = module.ok && EXPECTED_RESPONSE_TYPES.has(module.type);
+
+ if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
+
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ const bytes = await module.arrayBuffer();
+ return await WebAssembly.instantiate(bytes, imports);
+ } else {
+ const instance = await WebAssembly.instantiate(module, imports);
+
+ if (instance instanceof WebAssembly.Instance) {
+ return { instance, module };
+ } else {
+ return instance;
+ }
+ }
+}
+
+function __wbg_get_imports() {
+ const imports = {};
+ imports.wbg = {};
+ imports.wbg.__wbg_Error_52673b7de5a0ca89 = function(arg0, arg1) {
+ const ret = Error(getStringFromWasm0(arg0, arg1));
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_Number_2d1dcfcf4ec51736 = function(arg0) {
+ const ret = Number(getObject(arg0));
+ return ret;
+ };
+ imports.wbg.__wbg_String_8f0eb39a4a4c2f66 = function(arg0, arg1) {
+ const ret = String(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ };
+ imports.wbg.__wbg___wbindgen_bigint_get_as_i64_6e32f5e6aff02e1d = function(arg0, arg1) {
+ const v = getObject(arg1);
+ const ret = typeof(v) === 'bigint' ? v : undefined;
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+ };
+ imports.wbg.__wbg___wbindgen_boolean_get_dea25b33882b895b = function(arg0) {
+ const v = getObject(arg0);
+ const ret = typeof(v) === 'boolean' ? v : undefined;
+ return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
+ };
+ imports.wbg.__wbg___wbindgen_debug_string_adfb662ae34724b6 = function(arg0, arg1) {
+ const ret = debugString(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ };
+ imports.wbg.__wbg___wbindgen_in_0d3e1e8f0c669317 = function(arg0, arg1) {
+ const ret = getObject(arg0) in getObject(arg1);
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_is_bigint_0e1a2e3f55cfae27 = function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'bigint';
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_is_function_8d400b8b1af978cd = function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'function';
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_is_object_ce774f3490692386 = function(arg0) {
+ const val = getObject(arg0);
+ const ret = typeof(val) === 'object' && val !== null;
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_is_undefined_f6b95eab589e0269 = function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_jsval_eq_b6101cc9cef1fe36 = function(arg0, arg1) {
+ const ret = getObject(arg0) === getObject(arg1);
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_jsval_loose_eq_766057600fdd1b0d = function(arg0, arg1) {
+ const ret = getObject(arg0) == getObject(arg1);
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_number_get_9619185a74197f95 = function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'number' ? obj : undefined;
+ getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+ };
+ imports.wbg.__wbg___wbindgen_string_get_a2a31e16edf96e42 = function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'string' ? obj : undefined;
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ };
+ imports.wbg.__wbg___wbindgen_throw_dd24417ed36fc46e = function(arg0, arg1) {
+ throw new Error(getStringFromWasm0(arg0, arg1));
+ };
+ imports.wbg.__wbg_call_abb4ff46ce38be40 = function() { return handleError(function (arg0, arg1) {
+ const ret = getObject(arg0).call(getObject(arg1));
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbg_done_62ea16af4ce34b24 = function(arg0) {
+ const ret = getObject(arg0).done;
+ return ret;
+ };
+ imports.wbg.__wbg_entries_83c79938054e065f = function(arg0) {
+ const ret = Object.entries(getObject(arg0));
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_error_7534b8e9a36f1ab4 = function(arg0, arg1) {
+ let deferred0_0;
+ let deferred0_1;
+ try {
+ deferred0_0 = arg0;
+ deferred0_1 = arg1;
+ console.error(getStringFromWasm0(arg0, arg1));
+ } finally {
+ wasm.__wbindgen_export4(deferred0_0, deferred0_1, 1);
+ }
+ };
+ imports.wbg.__wbg_get_6b7bd52aca3f9671 = function(arg0, arg1) {
+ const ret = getObject(arg0)[arg1 >>> 0];
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_get_af9dab7e9603ea93 = function() { return handleError(function (arg0, arg1) {
+ const ret = Reflect.get(getObject(arg0), getObject(arg1));
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbg_get_with_ref_key_1dc361bd10053bfe = function(arg0, arg1) {
+ const ret = getObject(arg0)[getObject(arg1)];
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_instanceof_ArrayBuffer_f3320d2419cd0355 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof ArrayBuffer;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ };
+ imports.wbg.__wbg_instanceof_Map_084be8da74364158 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Map;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ };
+ imports.wbg.__wbg_instanceof_Uint8Array_da54ccc9d3e09434 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Uint8Array;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ };
+ imports.wbg.__wbg_isArray_51fd9e6422c0a395 = function(arg0) {
+ const ret = Array.isArray(getObject(arg0));
+ return ret;
+ };
+ imports.wbg.__wbg_isSafeInteger_ae7d3f054d55fa16 = function(arg0) {
+ const ret = Number.isSafeInteger(getObject(arg0));
+ return ret;
+ };
+ imports.wbg.__wbg_iterator_27b7c8b35ab3e86b = function() {
+ const ret = Symbol.iterator;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_length_22ac23eaec9d8053 = function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+ };
+ imports.wbg.__wbg_length_d45040a40c570362 = function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+ };
+ imports.wbg.__wbg_new_6421f6084cc5bc5a = function(arg0) {
+ const ret = new Uint8Array(getObject(arg0));
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_new_8a6f238a6ece86ea = function() {
+ const ret = new Error();
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_next_138a17bbf04e926c = function(arg0) {
+ const ret = getObject(arg0).next;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_next_3cfe5c0fe2a4cc53 = function() { return handleError(function (arg0) {
+ const ret = getObject(arg0).next();
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbg_prototypesetcall_dfe9b766cdc1f1fd = function(arg0, arg1, arg2) {
+ Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
+ };
+ imports.wbg.__wbg_stack_0ed75d68575b0f3c = function(arg0, arg1) {
+ const ret = getObject(arg1).stack;
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ };
+ imports.wbg.__wbg_value_57b7b035e117f7ee = function(arg0) {
+ const ret = getObject(arg0).value;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
+ // Cast intrinsic for `Ref(String) -> Externref`.
+ const ret = getStringFromWasm0(arg0, arg1);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_cast_4625c577ab2ec9ee = function(arg0) {
+ // Cast intrinsic for `U64 -> Externref`.
+ const ret = BigInt.asUintN(64, arg0);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_cast_9ae0607507abb057 = function(arg0) {
+ // Cast intrinsic for `I64 -> Externref`.
+ const ret = arg0;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
+ const ret = getObject(arg0);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
+ takeObject(arg0);
+ };
+ imports.wbg.__wbindgen_object_is_undefined = function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+ };
+
+ return imports;
+}
+
+function __wbg_finalize_init(instance, module) {
+ wasm = instance.exports;
+ __wbg_init.__wbindgen_wasm_module = module;
+ cachedDataViewMemory0 = null;
+ cachedUint8ArrayMemory0 = null;
+
+
+ wasm.__wbindgen_start();
+ return wasm;
+}
+
+function initSync(module) {
+ if (wasm !== undefined) return wasm;
+
+
+ if (typeof module !== 'undefined') {
+ if (Object.getPrototypeOf(module) === Object.prototype) {
+ ({module} = module)
+ } else {
+ console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
+ }
+ }
+
+ const imports = __wbg_get_imports();
+ if (!(module instanceof WebAssembly.Module)) {
+ module = new WebAssembly.Module(module);
+ }
+ const instance = new WebAssembly.Instance(module, imports);
+ return __wbg_finalize_init(instance, module);
+}
+
+async function __wbg_init(module_or_path) {
+ if (wasm !== undefined) return wasm;
+
+
+ if (typeof module_or_path !== 'undefined') {
+ if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
+ ({module_or_path} = module_or_path)
+ } else {
+ console.warn('using deprecated parameters for the initialization function; pass a single object instead')
+ }
+ }
+
+ if (typeof module_or_path === 'undefined') {
+ module_or_path = new URL('weaver_renderer_bg.wasm', import.meta.url);
+ }
+ const imports = __wbg_get_imports();
+
+ if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
+ module_or_path = fetch(module_or_path);
+ }
+
+ const { instance, module } = await __wbg_load(await module_or_path, imports);
+
+ return __wbg_finalize_init(instance, module);
+}
+
+export { initSync };
+export default __wbg_init;
diff --git a/crates/weaver-renderer-js/pkg/core/web/weaver_renderer_bg.wasm.d.ts b/crates/weaver-renderer-js/pkg/core/web/weaver_renderer_bg.wasm.d.ts
new file mode 100644
index 0000000..16b3955
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/core/web/weaver_renderer_bg.wasm.d.ts
@@ -0,0 +1,25 @@
+/* tslint:disable */
+/* eslint-disable */
+export const memory: WebAssembly.Memory;
+export const __wbg_get_jsmathresult_error: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_html: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_success: (a: number) => number;
+export const __wbg_jsmathresult_free: (a: number, b: number) => void;
+export const __wbg_jsresolvedcontent_free: (a: number, b: number) => void;
+export const __wbg_set_jsmathresult_error: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_html: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_success: (a: number, b: number) => void;
+export const create_resolved_content: () => number;
+export const init: () => void;
+export const jsresolvedcontent_addEmbed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const render_faceted_text: (a: number, b: number, c: number, d: number) => void;
+export const render_markdown: (a: number, b: number, c: number, d: number) => void;
+export const render_math: (a: number, b: number, c: number) => number;
+export const render_record: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const jsresolvedcontent_new: () => number;
+export const __wbindgen_export: (a: number, b: number) => number;
+export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
+export const __wbindgen_export3: (a: number) => void;
+export const __wbindgen_export4: (a: number, b: number, c: number) => void;
+export const __wbindgen_add_to_stack_pointer: (a: number) => number;
+export const __wbindgen_start: () => void;
diff --git a/crates/weaver-renderer-js/pkg/full/README.md b/crates/weaver-renderer-js/pkg/full/README.md
new file mode 100644
index 0000000..679c044
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/README.md
@@ -0,0 +1,45 @@
+# @weaver/renderer
+
+WASM bindings for rendering AT Protocol records (Bluesky posts, etc.) to HTML.
+
+## Installation
+
+```bash
+npm install @weaver.sh/renderer-full # With syntax highlighting
+npm install @weaver.sh/renderer-core # Light(er) weight
+```
+
+## Usage
+
+### With a bundler (webpack, vite, etc.)
+
+```javascript
+import init, { render_record, render_markdown } from '@weaver/renderer-full';
+
+await init();
+
+const html = render_record(atUri, recordJson);
+```
+
+### Direct browser usage (no bundler)
+
+```html
+
+```
+
+### Node.js
+
+```javascript
+const { render_record } = require('@weaver/renderer-full/nodejs');
+```
+
+## API
+
+- `render_record(at_uri, record_json, fallback_author?, resolved_content?)` - Render an AT Protocol record
+- `render_markdown(markdown, resolved_content?)` - Render markdown to HTML
+- `render_math(latex, display_mode)` - Render LaTeX math to MathML
+- `render_faceted_text(text, facets_json)` - Render rich text with facets
diff --git a/crates/weaver-renderer-js/pkg/full/bundler/LICENSE b/crates/weaver-renderer-js/pkg/full/bundler/LICENSE
new file mode 100644
index 0000000..a612ad9
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/bundler/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer.d.ts b/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer.d.ts
new file mode 100644
index 0000000..6083277
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer.d.ts
@@ -0,0 +1,84 @@
+/* tslint:disable */
+/* eslint-disable */
+
+export class JsMathResult {
+ private constructor();
+ free(): void;
+ [Symbol.dispose](): void;
+ success: boolean;
+ html: string;
+ get error(): string | undefined;
+ set error(value: string | null | undefined);
+}
+
+export class JsResolvedContent {
+ free(): void;
+ [Symbol.dispose](): void;
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor();
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ */
+ addEmbed(at_uri: string, html: string): void;
+}
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ */
+export function create_resolved_content(): JsResolvedContent;
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init(): void;
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ */
+export function render_faceted_text(text: string, facets_json: any): string;
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_markdown(markdown: string, resolved_content?: JsResolvedContent | null): string;
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ */
+export function render_math(latex: string, display_mode: boolean): JsMathResult;
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_record(at_uri: string, record_json: any, fallback_author?: any | null, resolved_content?: JsResolvedContent | null): string;
diff --git a/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer.js b/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer.js
new file mode 100644
index 0000000..eb312d6
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer.js
@@ -0,0 +1,5 @@
+import * as wasm from "./weaver_renderer_bg.wasm";
+export * from "./weaver_renderer_bg.js";
+import { __wbg_set_wasm } from "./weaver_renderer_bg.js";
+__wbg_set_wasm(wasm);
+wasm.__wbindgen_start();
diff --git a/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer_bg.js b/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer_bg.js
new file mode 100644
index 0000000..b7532e5
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer_bg.js
@@ -0,0 +1,797 @@
+let wasm;
+export function __wbg_set_wasm(val) {
+ wasm = val;
+}
+
+function addHeapObject(obj) {
+ if (heap_next === heap.length) heap.push(heap.length + 1);
+ const idx = heap_next;
+ heap_next = heap[idx];
+
+ heap[idx] = obj;
+ return idx;
+}
+
+function _assertClass(instance, klass) {
+ if (!(instance instanceof klass)) {
+ throw new Error(`expected instance of ${klass.name}`);
+ }
+}
+
+function debugString(val) {
+ // primitive types
+ const type = typeof val;
+ if (type == 'number' || type == 'boolean' || val == null) {
+ return `${val}`;
+ }
+ if (type == 'string') {
+ return `"${val}"`;
+ }
+ if (type == 'symbol') {
+ const description = val.description;
+ if (description == null) {
+ return 'Symbol';
+ } else {
+ return `Symbol(${description})`;
+ }
+ }
+ if (type == 'function') {
+ const name = val.name;
+ if (typeof name == 'string' && name.length > 0) {
+ return `Function(${name})`;
+ } else {
+ return 'Function';
+ }
+ }
+ // objects
+ if (Array.isArray(val)) {
+ const length = val.length;
+ let debug = '[';
+ if (length > 0) {
+ debug += debugString(val[0]);
+ }
+ for(let i = 1; i < length; i++) {
+ debug += ', ' + debugString(val[i]);
+ }
+ debug += ']';
+ return debug;
+ }
+ // Test for built-in
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
+ let className;
+ if (builtInMatches && builtInMatches.length > 1) {
+ className = builtInMatches[1];
+ } else {
+ // Failed to match the standard '[object ClassName]'
+ return toString.call(val);
+ }
+ if (className == 'Object') {
+ // we're a user defined class or Object
+ // JSON.stringify avoids problems with cycles, and is generally much
+ // easier than looping through ownProperties of `val`.
+ try {
+ return 'Object(' + JSON.stringify(val) + ')';
+ } catch (_) {
+ return 'Object';
+ }
+ }
+ // errors
+ if (val instanceof Error) {
+ return `${val.name}: ${val.message}\n${val.stack}`;
+ }
+ // TODO we could test for more things here, like `Set`s and `Map`s.
+ return className;
+}
+
+function dropObject(idx) {
+ if (idx < 132) return;
+ heap[idx] = heap_next;
+ heap_next = idx;
+}
+
+function getArrayU8FromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
+}
+
+let cachedDataViewMemory0 = null;
+function getDataViewMemory0() {
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
+ }
+ return cachedDataViewMemory0;
+}
+
+function getStringFromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return decodeText(ptr, len);
+}
+
+let cachedUint8ArrayMemory0 = null;
+function getUint8ArrayMemory0() {
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
+ }
+ return cachedUint8ArrayMemory0;
+}
+
+function getObject(idx) { return heap[idx]; }
+
+function handleError(f, args) {
+ try {
+ return f.apply(this, args);
+ } catch (e) {
+ wasm.__wbindgen_export3(addHeapObject(e));
+ }
+}
+
+let heap = new Array(128).fill(undefined);
+heap.push(undefined, null, true, false);
+
+let heap_next = heap.length;
+
+function isLikeNone(x) {
+ return x === undefined || x === null;
+}
+
+function passStringToWasm0(arg, malloc, realloc) {
+ if (realloc === undefined) {
+ const buf = cachedTextEncoder.encode(arg);
+ const ptr = malloc(buf.length, 1) >>> 0;
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
+ WASM_VECTOR_LEN = buf.length;
+ return ptr;
+ }
+
+ let len = arg.length;
+ let ptr = malloc(len, 1) >>> 0;
+
+ const mem = getUint8ArrayMemory0();
+
+ let offset = 0;
+
+ for (; offset < len; offset++) {
+ const code = arg.charCodeAt(offset);
+ if (code > 0x7F) break;
+ mem[ptr + offset] = code;
+ }
+ if (offset !== len) {
+ if (offset !== 0) {
+ arg = arg.slice(offset);
+ }
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
+ const ret = cachedTextEncoder.encodeInto(arg, view);
+
+ offset += ret.written;
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
+ }
+
+ WASM_VECTOR_LEN = offset;
+ return ptr;
+}
+
+function takeObject(idx) {
+ const ret = getObject(idx);
+ dropObject(idx);
+ return ret;
+}
+
+let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+cachedTextDecoder.decode();
+const MAX_SAFARI_DECODE_BYTES = 2146435072;
+let numBytesDecoded = 0;
+function decodeText(ptr, len) {
+ numBytesDecoded += len;
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+ cachedTextDecoder.decode();
+ numBytesDecoded = len;
+ }
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
+}
+
+const cachedTextEncoder = new TextEncoder();
+
+if (!('encodeInto' in cachedTextEncoder)) {
+ cachedTextEncoder.encodeInto = function (arg, view) {
+ const buf = cachedTextEncoder.encode(arg);
+ view.set(buf);
+ return {
+ read: arg.length,
+ written: buf.length
+ };
+ }
+}
+
+let WASM_VECTOR_LEN = 0;
+
+const JsMathResultFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsmathresult_free(ptr >>> 0, 1));
+
+const JsResolvedContentFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsresolvedcontent_free(ptr >>> 0, 1));
+
+/**
+ * Result from rendering LaTeX math.
+ */
+export class JsMathResult {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsMathResult.prototype);
+ obj.__wbg_ptr = ptr;
+ JsMathResultFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsMathResultFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsmathresult_free(ptr, 0);
+ }
+ /**
+ * @returns {boolean}
+ */
+ get success() {
+ const ret = wasm.__wbg_get_jsmathresult_success(this.__wbg_ptr);
+ return ret !== 0;
+ }
+ /**
+ * @param {boolean} arg0
+ */
+ set success(arg0) {
+ wasm.__wbg_set_jsmathresult_success(this.__wbg_ptr, arg0);
+ }
+ /**
+ * @returns {string}
+ */
+ get html() {
+ let deferred1_0;
+ let deferred1_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_html(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ deferred1_0 = r0;
+ deferred1_1 = r1;
+ return getStringFromWasm0(r0, r1);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
+ }
+ }
+ /**
+ * @param {string} arg0
+ */
+ set html(arg0) {
+ const ptr0 = passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_html(this.__wbg_ptr, ptr0, len0);
+ }
+ /**
+ * @returns {string | undefined}
+ */
+ get error() {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_error(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ let v1;
+ if (r0 !== 0) {
+ v1 = getStringFromWasm0(r0, r1).slice();
+ wasm.__wbindgen_export4(r0, r1 * 1, 1);
+ }
+ return v1;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+ /**
+ * @param {string | null} [arg0]
+ */
+ set error(arg0) {
+ var ptr0 = isLikeNone(arg0) ? 0 : passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_error(this.__wbg_ptr, ptr0, len0);
+ }
+}
+if (Symbol.dispose) JsMathResult.prototype[Symbol.dispose] = JsMathResult.prototype.free;
+
+/**
+ * Pre-rendered embed content for synchronous rendering.
+ *
+ * Build this by calling `create_resolved_content()` and adding embeds
+ * with `resolved_content_add_embed()`.
+ */
+export class JsResolvedContent {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsResolvedContent.prototype);
+ obj.__wbg_ptr = ptr;
+ JsResolvedContentFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsResolvedContentFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsresolvedcontent_free(ptr, 0);
+ }
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor() {
+ const ret = wasm.create_resolved_content();
+ this.__wbg_ptr = ret >>> 0;
+ JsResolvedContentFinalization.register(this, this.__wbg_ptr, this);
+ return this;
+ }
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ * @param {string} at_uri
+ * @param {string} html
+ */
+ addEmbed(at_uri, html) {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(html, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.jsresolvedcontent_addEmbed(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ if (r1) {
+ throw takeObject(r0);
+ }
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+}
+if (Symbol.dispose) JsResolvedContent.prototype[Symbol.dispose] = JsResolvedContent.prototype.free;
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ * @returns {JsResolvedContent}
+ */
+export function create_resolved_content() {
+ const ret = wasm.create_resolved_content();
+ return JsResolvedContent.__wrap(ret);
+}
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init() {
+ wasm.init();
+}
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ * @param {string} text
+ * @param {any} facets_json
+ * @returns {string}
+ */
+export function render_faceted_text(text, facets_json) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(text, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.render_faceted_text(retptr, ptr0, len0, addHeapObject(facets_json));
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} markdown
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_markdown(markdown, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_markdown(retptr, ptr0, len0, ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ * @param {string} latex
+ * @param {boolean} display_mode
+ * @returns {JsMathResult}
+ */
+export function render_math(latex, display_mode) {
+ const ptr0 = passStringToWasm0(latex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ret = wasm.render_math(ptr0, len0, display_mode);
+ return JsMathResult.__wrap(ret);
+}
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} at_uri
+ * @param {any} record_json
+ * @param {any | null} [fallback_author]
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_record(at_uri, record_json, fallback_author, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_record(retptr, ptr0, len0, addHeapObject(record_json), isLikeNone(fallback_author) ? 0 : addHeapObject(fallback_author), ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+export function __wbg_Error_52673b7de5a0ca89(arg0, arg1) {
+ const ret = Error(getStringFromWasm0(arg0, arg1));
+ return addHeapObject(ret);
+};
+
+export function __wbg_Number_2d1dcfcf4ec51736(arg0) {
+ const ret = Number(getObject(arg0));
+ return ret;
+};
+
+export function __wbg_String_8f0eb39a4a4c2f66(arg0, arg1) {
+ const ret = String(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+export function __wbg___wbindgen_bigint_get_as_i64_6e32f5e6aff02e1d(arg0, arg1) {
+ const v = getObject(arg1);
+ const ret = typeof(v) === 'bigint' ? v : undefined;
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+};
+
+export function __wbg___wbindgen_boolean_get_dea25b33882b895b(arg0) {
+ const v = getObject(arg0);
+ const ret = typeof(v) === 'boolean' ? v : undefined;
+ return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
+};
+
+export function __wbg___wbindgen_debug_string_adfb662ae34724b6(arg0, arg1) {
+ const ret = debugString(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+export function __wbg___wbindgen_in_0d3e1e8f0c669317(arg0, arg1) {
+ const ret = getObject(arg0) in getObject(arg1);
+ return ret;
+};
+
+export function __wbg___wbindgen_is_bigint_0e1a2e3f55cfae27(arg0) {
+ const ret = typeof(getObject(arg0)) === 'bigint';
+ return ret;
+};
+
+export function __wbg___wbindgen_is_function_8d400b8b1af978cd(arg0) {
+ const ret = typeof(getObject(arg0)) === 'function';
+ return ret;
+};
+
+export function __wbg___wbindgen_is_object_ce774f3490692386(arg0) {
+ const val = getObject(arg0);
+ const ret = typeof(val) === 'object' && val !== null;
+ return ret;
+};
+
+export function __wbg___wbindgen_is_undefined_f6b95eab589e0269(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+};
+
+export function __wbg___wbindgen_jsval_eq_b6101cc9cef1fe36(arg0, arg1) {
+ const ret = getObject(arg0) === getObject(arg1);
+ return ret;
+};
+
+export function __wbg___wbindgen_jsval_loose_eq_766057600fdd1b0d(arg0, arg1) {
+ const ret = getObject(arg0) == getObject(arg1);
+ return ret;
+};
+
+export function __wbg___wbindgen_number_get_9619185a74197f95(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'number' ? obj : undefined;
+ getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+};
+
+export function __wbg___wbindgen_string_get_a2a31e16edf96e42(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'string' ? obj : undefined;
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+export function __wbg___wbindgen_throw_dd24417ed36fc46e(arg0, arg1) {
+ throw new Error(getStringFromWasm0(arg0, arg1));
+};
+
+export function __wbg_call_abb4ff46ce38be40() { return handleError(function (arg0, arg1) {
+ const ret = getObject(arg0).call(getObject(arg1));
+ return addHeapObject(ret);
+}, arguments) };
+
+export function __wbg_done_62ea16af4ce34b24(arg0) {
+ const ret = getObject(arg0).done;
+ return ret;
+};
+
+export function __wbg_entries_83c79938054e065f(arg0) {
+ const ret = Object.entries(getObject(arg0));
+ return addHeapObject(ret);
+};
+
+export function __wbg_error_7534b8e9a36f1ab4(arg0, arg1) {
+ let deferred0_0;
+ let deferred0_1;
+ try {
+ deferred0_0 = arg0;
+ deferred0_1 = arg1;
+ console.error(getStringFromWasm0(arg0, arg1));
+ } finally {
+ wasm.__wbindgen_export4(deferred0_0, deferred0_1, 1);
+ }
+};
+
+export function __wbg_get_6b7bd52aca3f9671(arg0, arg1) {
+ const ret = getObject(arg0)[arg1 >>> 0];
+ return addHeapObject(ret);
+};
+
+export function __wbg_get_af9dab7e9603ea93() { return handleError(function (arg0, arg1) {
+ const ret = Reflect.get(getObject(arg0), getObject(arg1));
+ return addHeapObject(ret);
+}, arguments) };
+
+export function __wbg_get_with_ref_key_1dc361bd10053bfe(arg0, arg1) {
+ const ret = getObject(arg0)[getObject(arg1)];
+ return addHeapObject(ret);
+};
+
+export function __wbg_instanceof_ArrayBuffer_f3320d2419cd0355(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof ArrayBuffer;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+export function __wbg_instanceof_Map_084be8da74364158(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Map;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+export function __wbg_instanceof_Uint8Array_da54ccc9d3e09434(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Uint8Array;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+export function __wbg_isArray_51fd9e6422c0a395(arg0) {
+ const ret = Array.isArray(getObject(arg0));
+ return ret;
+};
+
+export function __wbg_isSafeInteger_ae7d3f054d55fa16(arg0) {
+ const ret = Number.isSafeInteger(getObject(arg0));
+ return ret;
+};
+
+export function __wbg_iterator_27b7c8b35ab3e86b() {
+ const ret = Symbol.iterator;
+ return addHeapObject(ret);
+};
+
+export function __wbg_length_22ac23eaec9d8053(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+};
+
+export function __wbg_length_d45040a40c570362(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+};
+
+export function __wbg_new_6421f6084cc5bc5a(arg0) {
+ const ret = new Uint8Array(getObject(arg0));
+ return addHeapObject(ret);
+};
+
+export function __wbg_new_8a6f238a6ece86ea() {
+ const ret = new Error();
+ return addHeapObject(ret);
+};
+
+export function __wbg_next_138a17bbf04e926c(arg0) {
+ const ret = getObject(arg0).next;
+ return addHeapObject(ret);
+};
+
+export function __wbg_next_3cfe5c0fe2a4cc53() { return handleError(function (arg0) {
+ const ret = getObject(arg0).next();
+ return addHeapObject(ret);
+}, arguments) };
+
+export function __wbg_prototypesetcall_dfe9b766cdc1f1fd(arg0, arg1, arg2) {
+ Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
+};
+
+export function __wbg_stack_0ed75d68575b0f3c(arg0, arg1) {
+ const ret = getObject(arg1).stack;
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+export function __wbg_value_57b7b035e117f7ee(arg0) {
+ const ret = getObject(arg0).value;
+ return addHeapObject(ret);
+};
+
+export function __wbindgen_cast_2241b6af4c4b2941(arg0, arg1) {
+ // Cast intrinsic for `Ref(String) -> Externref`.
+ const ret = getStringFromWasm0(arg0, arg1);
+ return addHeapObject(ret);
+};
+
+export function __wbindgen_cast_4625c577ab2ec9ee(arg0) {
+ // Cast intrinsic for `U64 -> Externref`.
+ const ret = BigInt.asUintN(64, arg0);
+ return addHeapObject(ret);
+};
+
+export function __wbindgen_cast_9ae0607507abb057(arg0) {
+ // Cast intrinsic for `I64 -> Externref`.
+ const ret = arg0;
+ return addHeapObject(ret);
+};
+
+export function __wbindgen_object_clone_ref(arg0) {
+ const ret = getObject(arg0);
+ return addHeapObject(ret);
+};
+
+export function __wbindgen_object_drop_ref(arg0) {
+ takeObject(arg0);
+};
+
+export function __wbindgen_object_is_undefined(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+};
diff --git a/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer_bg.wasm.d.ts b/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer_bg.wasm.d.ts
new file mode 100644
index 0000000..16b3955
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/bundler/weaver_renderer_bg.wasm.d.ts
@@ -0,0 +1,25 @@
+/* tslint:disable */
+/* eslint-disable */
+export const memory: WebAssembly.Memory;
+export const __wbg_get_jsmathresult_error: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_html: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_success: (a: number) => number;
+export const __wbg_jsmathresult_free: (a: number, b: number) => void;
+export const __wbg_jsresolvedcontent_free: (a: number, b: number) => void;
+export const __wbg_set_jsmathresult_error: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_html: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_success: (a: number, b: number) => void;
+export const create_resolved_content: () => number;
+export const init: () => void;
+export const jsresolvedcontent_addEmbed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const render_faceted_text: (a: number, b: number, c: number, d: number) => void;
+export const render_markdown: (a: number, b: number, c: number, d: number) => void;
+export const render_math: (a: number, b: number, c: number) => number;
+export const render_record: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const jsresolvedcontent_new: () => number;
+export const __wbindgen_export: (a: number, b: number) => number;
+export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
+export const __wbindgen_export3: (a: number) => void;
+export const __wbindgen_export4: (a: number, b: number, c: number) => void;
+export const __wbindgen_add_to_stack_pointer: (a: number) => number;
+export const __wbindgen_start: () => void;
diff --git a/crates/weaver-renderer-js/pkg/full/deno/LICENSE b/crates/weaver-renderer-js/pkg/full/deno/LICENSE
new file mode 100644
index 0000000..a612ad9
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/deno/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/crates/weaver-renderer-js/pkg/full/deno/weaver_renderer.d.ts b/crates/weaver-renderer-js/pkg/full/deno/weaver_renderer.d.ts
new file mode 100644
index 0000000..6083277
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/deno/weaver_renderer.d.ts
@@ -0,0 +1,84 @@
+/* tslint:disable */
+/* eslint-disable */
+
+export class JsMathResult {
+ private constructor();
+ free(): void;
+ [Symbol.dispose](): void;
+ success: boolean;
+ html: string;
+ get error(): string | undefined;
+ set error(value: string | null | undefined);
+}
+
+export class JsResolvedContent {
+ free(): void;
+ [Symbol.dispose](): void;
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor();
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ */
+ addEmbed(at_uri: string, html: string): void;
+}
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ */
+export function create_resolved_content(): JsResolvedContent;
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init(): void;
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ */
+export function render_faceted_text(text: string, facets_json: any): string;
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_markdown(markdown: string, resolved_content?: JsResolvedContent | null): string;
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ */
+export function render_math(latex: string, display_mode: boolean): JsMathResult;
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_record(at_uri: string, record_json: any, fallback_author?: any | null, resolved_content?: JsResolvedContent | null): string;
diff --git a/crates/weaver-renderer-js/pkg/full/deno/weaver_renderer.js b/crates/weaver-renderer-js/pkg/full/deno/weaver_renderer.js
new file mode 100644
index 0000000..996b119
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/deno/weaver_renderer.js
@@ -0,0 +1,743 @@
+
+
+function addHeapObject(obj) {
+ if (heap_next === heap.length) heap.push(heap.length + 1);
+ const idx = heap_next;
+ heap_next = heap[idx];
+
+ heap[idx] = obj;
+ return idx;
+}
+
+function _assertClass(instance, klass) {
+ if (!(instance instanceof klass)) {
+ throw new Error(`expected instance of ${klass.name}`);
+ }
+}
+
+function debugString(val) {
+ // primitive types
+ const type = typeof val;
+ if (type == 'number' || type == 'boolean' || val == null) {
+ return `${val}`;
+ }
+ if (type == 'string') {
+ return `"${val}"`;
+ }
+ if (type == 'symbol') {
+ const description = val.description;
+ if (description == null) {
+ return 'Symbol';
+ } else {
+ return `Symbol(${description})`;
+ }
+ }
+ if (type == 'function') {
+ const name = val.name;
+ if (typeof name == 'string' && name.length > 0) {
+ return `Function(${name})`;
+ } else {
+ return 'Function';
+ }
+ }
+ // objects
+ if (Array.isArray(val)) {
+ const length = val.length;
+ let debug = '[';
+ if (length > 0) {
+ debug += debugString(val[0]);
+ }
+ for(let i = 1; i < length; i++) {
+ debug += ', ' + debugString(val[i]);
+ }
+ debug += ']';
+ return debug;
+ }
+ // Test for built-in
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
+ let className;
+ if (builtInMatches && builtInMatches.length > 1) {
+ className = builtInMatches[1];
+ } else {
+ // Failed to match the standard '[object ClassName]'
+ return toString.call(val);
+ }
+ if (className == 'Object') {
+ // we're a user defined class or Object
+ // JSON.stringify avoids problems with cycles, and is generally much
+ // easier than looping through ownProperties of `val`.
+ try {
+ return 'Object(' + JSON.stringify(val) + ')';
+ } catch (_) {
+ return 'Object';
+ }
+ }
+ // errors
+ if (val instanceof Error) {
+ return `${val.name}: ${val.message}\n${val.stack}`;
+ }
+ // TODO we could test for more things here, like `Set`s and `Map`s.
+ return className;
+}
+
+function dropObject(idx) {
+ if (idx < 132) return;
+ heap[idx] = heap_next;
+ heap_next = idx;
+}
+
+function getArrayU8FromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
+}
+
+let cachedDataViewMemory0 = null;
+function getDataViewMemory0() {
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
+ }
+ return cachedDataViewMemory0;
+}
+
+function getStringFromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return decodeText(ptr, len);
+}
+
+let cachedUint8ArrayMemory0 = null;
+function getUint8ArrayMemory0() {
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
+ }
+ return cachedUint8ArrayMemory0;
+}
+
+function getObject(idx) { return heap[idx]; }
+
+function handleError(f, args) {
+ try {
+ return f.apply(this, args);
+ } catch (e) {
+ wasm.__wbindgen_export3(addHeapObject(e));
+ }
+}
+
+let heap = new Array(128).fill(undefined);
+heap.push(undefined, null, true, false);
+
+let heap_next = heap.length;
+
+function isLikeNone(x) {
+ return x === undefined || x === null;
+}
+
+function passStringToWasm0(arg, malloc, realloc) {
+ if (realloc === undefined) {
+ const buf = cachedTextEncoder.encode(arg);
+ const ptr = malloc(buf.length, 1) >>> 0;
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
+ WASM_VECTOR_LEN = buf.length;
+ return ptr;
+ }
+
+ let len = arg.length;
+ let ptr = malloc(len, 1) >>> 0;
+
+ const mem = getUint8ArrayMemory0();
+
+ let offset = 0;
+
+ for (; offset < len; offset++) {
+ const code = arg.charCodeAt(offset);
+ if (code > 0x7F) break;
+ mem[ptr + offset] = code;
+ }
+ if (offset !== len) {
+ if (offset !== 0) {
+ arg = arg.slice(offset);
+ }
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
+ const ret = cachedTextEncoder.encodeInto(arg, view);
+
+ offset += ret.written;
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
+ }
+
+ WASM_VECTOR_LEN = offset;
+ return ptr;
+}
+
+function takeObject(idx) {
+ const ret = getObject(idx);
+ dropObject(idx);
+ return ret;
+}
+
+let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+cachedTextDecoder.decode();
+function decodeText(ptr, len) {
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
+}
+
+const cachedTextEncoder = new TextEncoder();
+
+let WASM_VECTOR_LEN = 0;
+
+const JsMathResultFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsmathresult_free(ptr >>> 0, 1));
+
+const JsResolvedContentFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsresolvedcontent_free(ptr >>> 0, 1));
+
+/**
+ * Result from rendering LaTeX math.
+ */
+export class JsMathResult {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsMathResult.prototype);
+ obj.__wbg_ptr = ptr;
+ JsMathResultFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsMathResultFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsmathresult_free(ptr, 0);
+ }
+ /**
+ * @returns {boolean}
+ */
+ get success() {
+ const ret = wasm.__wbg_get_jsmathresult_success(this.__wbg_ptr);
+ return ret !== 0;
+ }
+ /**
+ * @param {boolean} arg0
+ */
+ set success(arg0) {
+ wasm.__wbg_set_jsmathresult_success(this.__wbg_ptr, arg0);
+ }
+ /**
+ * @returns {string}
+ */
+ get html() {
+ let deferred1_0;
+ let deferred1_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_html(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ deferred1_0 = r0;
+ deferred1_1 = r1;
+ return getStringFromWasm0(r0, r1);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
+ }
+ }
+ /**
+ * @param {string} arg0
+ */
+ set html(arg0) {
+ const ptr0 = passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_html(this.__wbg_ptr, ptr0, len0);
+ }
+ /**
+ * @returns {string | undefined}
+ */
+ get error() {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_error(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ let v1;
+ if (r0 !== 0) {
+ v1 = getStringFromWasm0(r0, r1).slice();
+ wasm.__wbindgen_export4(r0, r1 * 1, 1);
+ }
+ return v1;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+ /**
+ * @param {string | null} [arg0]
+ */
+ set error(arg0) {
+ var ptr0 = isLikeNone(arg0) ? 0 : passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_error(this.__wbg_ptr, ptr0, len0);
+ }
+}
+if (Symbol.dispose) JsMathResult.prototype[Symbol.dispose] = JsMathResult.prototype.free;
+
+/**
+ * Pre-rendered embed content for synchronous rendering.
+ *
+ * Build this by calling `create_resolved_content()` and adding embeds
+ * with `resolved_content_add_embed()`.
+ */
+export class JsResolvedContent {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsResolvedContent.prototype);
+ obj.__wbg_ptr = ptr;
+ JsResolvedContentFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsResolvedContentFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsresolvedcontent_free(ptr, 0);
+ }
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor() {
+ const ret = wasm.create_resolved_content();
+ this.__wbg_ptr = ret >>> 0;
+ JsResolvedContentFinalization.register(this, this.__wbg_ptr, this);
+ return this;
+ }
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ * @param {string} at_uri
+ * @param {string} html
+ */
+ addEmbed(at_uri, html) {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(html, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.jsresolvedcontent_addEmbed(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ if (r1) {
+ throw takeObject(r0);
+ }
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+}
+if (Symbol.dispose) JsResolvedContent.prototype[Symbol.dispose] = JsResolvedContent.prototype.free;
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ * @returns {JsResolvedContent}
+ */
+export function create_resolved_content() {
+ const ret = wasm.create_resolved_content();
+ return JsResolvedContent.__wrap(ret);
+}
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init() {
+ wasm.init();
+}
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ * @param {string} text
+ * @param {any} facets_json
+ * @returns {string}
+ */
+export function render_faceted_text(text, facets_json) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(text, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.render_faceted_text(retptr, ptr0, len0, addHeapObject(facets_json));
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} markdown
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_markdown(markdown, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_markdown(retptr, ptr0, len0, ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ * @param {string} latex
+ * @param {boolean} display_mode
+ * @returns {JsMathResult}
+ */
+export function render_math(latex, display_mode) {
+ const ptr0 = passStringToWasm0(latex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ret = wasm.render_math(ptr0, len0, display_mode);
+ return JsMathResult.__wrap(ret);
+}
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} at_uri
+ * @param {any} record_json
+ * @param {any | null} [fallback_author]
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_record(at_uri, record_json, fallback_author, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_record(retptr, ptr0, len0, addHeapObject(record_json), isLikeNone(fallback_author) ? 0 : addHeapObject(fallback_author), ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+const imports = {
+ __wbindgen_placeholder__: {
+ __wbg_Error_52673b7de5a0ca89: function(arg0, arg1) {
+ const ret = Error(getStringFromWasm0(arg0, arg1));
+ return addHeapObject(ret);
+ },
+ __wbg_Number_2d1dcfcf4ec51736: function(arg0) {
+ const ret = Number(getObject(arg0));
+ return ret;
+ },
+ __wbg_String_8f0eb39a4a4c2f66: function(arg0, arg1) {
+ const ret = String(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ },
+ __wbg___wbindgen_bigint_get_as_i64_6e32f5e6aff02e1d: function(arg0, arg1) {
+ const v = getObject(arg1);
+ const ret = typeof(v) === 'bigint' ? v : undefined;
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+ },
+ __wbg___wbindgen_boolean_get_dea25b33882b895b: function(arg0) {
+ const v = getObject(arg0);
+ const ret = typeof(v) === 'boolean' ? v : undefined;
+ return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
+ },
+ __wbg___wbindgen_debug_string_adfb662ae34724b6: function(arg0, arg1) {
+ const ret = debugString(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ },
+ __wbg___wbindgen_in_0d3e1e8f0c669317: function(arg0, arg1) {
+ const ret = getObject(arg0) in getObject(arg1);
+ return ret;
+ },
+ __wbg___wbindgen_is_bigint_0e1a2e3f55cfae27: function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'bigint';
+ return ret;
+ },
+ __wbg___wbindgen_is_function_8d400b8b1af978cd: function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'function';
+ return ret;
+ },
+ __wbg___wbindgen_is_object_ce774f3490692386: function(arg0) {
+ const val = getObject(arg0);
+ const ret = typeof(val) === 'object' && val !== null;
+ return ret;
+ },
+ __wbg___wbindgen_is_undefined_f6b95eab589e0269: function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+ },
+ __wbg___wbindgen_jsval_eq_b6101cc9cef1fe36: function(arg0, arg1) {
+ const ret = getObject(arg0) === getObject(arg1);
+ return ret;
+ },
+ __wbg___wbindgen_jsval_loose_eq_766057600fdd1b0d: function(arg0, arg1) {
+ const ret = getObject(arg0) == getObject(arg1);
+ return ret;
+ },
+ __wbg___wbindgen_number_get_9619185a74197f95: function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'number' ? obj : undefined;
+ getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+ },
+ __wbg___wbindgen_string_get_a2a31e16edf96e42: function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'string' ? obj : undefined;
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ },
+ __wbg___wbindgen_throw_dd24417ed36fc46e: function(arg0, arg1) {
+ throw new Error(getStringFromWasm0(arg0, arg1));
+ },
+ __wbg_call_abb4ff46ce38be40: function() { return handleError(function (arg0, arg1) {
+ const ret = getObject(arg0).call(getObject(arg1));
+ return addHeapObject(ret);
+ }, arguments) },
+ __wbg_done_62ea16af4ce34b24: function(arg0) {
+ const ret = getObject(arg0).done;
+ return ret;
+ },
+ __wbg_entries_83c79938054e065f: function(arg0) {
+ const ret = Object.entries(getObject(arg0));
+ return addHeapObject(ret);
+ },
+ __wbg_error_7534b8e9a36f1ab4: function(arg0, arg1) {
+ let deferred0_0;
+ let deferred0_1;
+ try {
+ deferred0_0 = arg0;
+ deferred0_1 = arg1;
+ console.error(getStringFromWasm0(arg0, arg1));
+ } finally {
+ wasm.__wbindgen_export4(deferred0_0, deferred0_1, 1);
+ }
+ },
+ __wbg_get_6b7bd52aca3f9671: function(arg0, arg1) {
+ const ret = getObject(arg0)[arg1 >>> 0];
+ return addHeapObject(ret);
+ },
+ __wbg_get_af9dab7e9603ea93: function() { return handleError(function (arg0, arg1) {
+ const ret = Reflect.get(getObject(arg0), getObject(arg1));
+ return addHeapObject(ret);
+ }, arguments) },
+ __wbg_get_with_ref_key_1dc361bd10053bfe: function(arg0, arg1) {
+ const ret = getObject(arg0)[getObject(arg1)];
+ return addHeapObject(ret);
+ },
+ __wbg_instanceof_ArrayBuffer_f3320d2419cd0355: function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof ArrayBuffer;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ },
+ __wbg_instanceof_Map_084be8da74364158: function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Map;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ },
+ __wbg_instanceof_Uint8Array_da54ccc9d3e09434: function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Uint8Array;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ },
+ __wbg_isArray_51fd9e6422c0a395: function(arg0) {
+ const ret = Array.isArray(getObject(arg0));
+ return ret;
+ },
+ __wbg_isSafeInteger_ae7d3f054d55fa16: function(arg0) {
+ const ret = Number.isSafeInteger(getObject(arg0));
+ return ret;
+ },
+ __wbg_iterator_27b7c8b35ab3e86b: function() {
+ const ret = Symbol.iterator;
+ return addHeapObject(ret);
+ },
+ __wbg_length_22ac23eaec9d8053: function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+ },
+ __wbg_length_d45040a40c570362: function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+ },
+ __wbg_new_6421f6084cc5bc5a: function(arg0) {
+ const ret = new Uint8Array(getObject(arg0));
+ return addHeapObject(ret);
+ },
+ __wbg_new_8a6f238a6ece86ea: function() {
+ const ret = new Error();
+ return addHeapObject(ret);
+ },
+ __wbg_next_138a17bbf04e926c: function(arg0) {
+ const ret = getObject(arg0).next;
+ return addHeapObject(ret);
+ },
+ __wbg_next_3cfe5c0fe2a4cc53: function() { return handleError(function (arg0) {
+ const ret = getObject(arg0).next();
+ return addHeapObject(ret);
+ }, arguments) },
+ __wbg_prototypesetcall_dfe9b766cdc1f1fd: function(arg0, arg1, arg2) {
+ Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
+ },
+ __wbg_stack_0ed75d68575b0f3c: function(arg0, arg1) {
+ const ret = getObject(arg1).stack;
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ },
+ __wbg_value_57b7b035e117f7ee: function(arg0) {
+ const ret = getObject(arg0).value;
+ return addHeapObject(ret);
+ },
+ __wbindgen_cast_2241b6af4c4b2941: function(arg0, arg1) {
+ // Cast intrinsic for `Ref(String) -> Externref`.
+ const ret = getStringFromWasm0(arg0, arg1);
+ return addHeapObject(ret);
+ },
+ __wbindgen_cast_4625c577ab2ec9ee: function(arg0) {
+ // Cast intrinsic for `U64 -> Externref`.
+ const ret = BigInt.asUintN(64, arg0);
+ return addHeapObject(ret);
+ },
+ __wbindgen_cast_9ae0607507abb057: function(arg0) {
+ // Cast intrinsic for `I64 -> Externref`.
+ const ret = arg0;
+ return addHeapObject(ret);
+ },
+ __wbindgen_object_clone_ref: function(arg0) {
+ const ret = getObject(arg0);
+ return addHeapObject(ret);
+ },
+ __wbindgen_object_drop_ref: function(arg0) {
+ takeObject(arg0);
+ },
+ __wbindgen_object_is_undefined: function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+ },
+ },
+
+};
+
+const wasmUrl = new URL('weaver_renderer_bg.wasm', import.meta.url);
+const wasm = (await WebAssembly.instantiateStreaming(fetch(wasmUrl), imports)).instance.exports;
+export { wasm as __wasm };
+
+wasm.__wbindgen_start();
diff --git a/crates/weaver-renderer-js/pkg/full/deno/weaver_renderer_bg.wasm.d.ts b/crates/weaver-renderer-js/pkg/full/deno/weaver_renderer_bg.wasm.d.ts
new file mode 100644
index 0000000..16b3955
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/deno/weaver_renderer_bg.wasm.d.ts
@@ -0,0 +1,25 @@
+/* tslint:disable */
+/* eslint-disable */
+export const memory: WebAssembly.Memory;
+export const __wbg_get_jsmathresult_error: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_html: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_success: (a: number) => number;
+export const __wbg_jsmathresult_free: (a: number, b: number) => void;
+export const __wbg_jsresolvedcontent_free: (a: number, b: number) => void;
+export const __wbg_set_jsmathresult_error: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_html: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_success: (a: number, b: number) => void;
+export const create_resolved_content: () => number;
+export const init: () => void;
+export const jsresolvedcontent_addEmbed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const render_faceted_text: (a: number, b: number, c: number, d: number) => void;
+export const render_markdown: (a: number, b: number, c: number, d: number) => void;
+export const render_math: (a: number, b: number, c: number) => number;
+export const render_record: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const jsresolvedcontent_new: () => number;
+export const __wbindgen_export: (a: number, b: number) => number;
+export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
+export const __wbindgen_export3: (a: number) => void;
+export const __wbindgen_export4: (a: number, b: number, c: number) => void;
+export const __wbindgen_add_to_stack_pointer: (a: number) => number;
+export const __wbindgen_start: () => void;
diff --git a/crates/weaver-renderer-js/pkg/full/nodejs/LICENSE b/crates/weaver-renderer-js/pkg/full/nodejs/LICENSE
new file mode 100644
index 0000000..a612ad9
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/nodejs/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/crates/weaver-renderer-js/pkg/full/nodejs/weaver_renderer.d.ts b/crates/weaver-renderer-js/pkg/full/nodejs/weaver_renderer.d.ts
new file mode 100644
index 0000000..6083277
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/nodejs/weaver_renderer.d.ts
@@ -0,0 +1,84 @@
+/* tslint:disable */
+/* eslint-disable */
+
+export class JsMathResult {
+ private constructor();
+ free(): void;
+ [Symbol.dispose](): void;
+ success: boolean;
+ html: string;
+ get error(): string | undefined;
+ set error(value: string | null | undefined);
+}
+
+export class JsResolvedContent {
+ free(): void;
+ [Symbol.dispose](): void;
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor();
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ */
+ addEmbed(at_uri: string, html: string): void;
+}
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ */
+export function create_resolved_content(): JsResolvedContent;
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init(): void;
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ */
+export function render_faceted_text(text: string, facets_json: any): string;
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_markdown(markdown: string, resolved_content?: JsResolvedContent | null): string;
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ */
+export function render_math(latex: string, display_mode: boolean): JsMathResult;
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_record(at_uri: string, record_json: any, fallback_author?: any | null, resolved_content?: JsResolvedContent | null): string;
diff --git a/crates/weaver-renderer-js/pkg/full/nodejs/weaver_renderer.js b/crates/weaver-renderer-js/pkg/full/nodejs/weaver_renderer.js
new file mode 100644
index 0000000..86f6508
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/nodejs/weaver_renderer.js
@@ -0,0 +1,803 @@
+
+let imports = {};
+imports['__wbindgen_placeholder__'] = module.exports;
+
+function addHeapObject(obj) {
+ if (heap_next === heap.length) heap.push(heap.length + 1);
+ const idx = heap_next;
+ heap_next = heap[idx];
+
+ heap[idx] = obj;
+ return idx;
+}
+
+function _assertClass(instance, klass) {
+ if (!(instance instanceof klass)) {
+ throw new Error(`expected instance of ${klass.name}`);
+ }
+}
+
+function debugString(val) {
+ // primitive types
+ const type = typeof val;
+ if (type == 'number' || type == 'boolean' || val == null) {
+ return `${val}`;
+ }
+ if (type == 'string') {
+ return `"${val}"`;
+ }
+ if (type == 'symbol') {
+ const description = val.description;
+ if (description == null) {
+ return 'Symbol';
+ } else {
+ return `Symbol(${description})`;
+ }
+ }
+ if (type == 'function') {
+ const name = val.name;
+ if (typeof name == 'string' && name.length > 0) {
+ return `Function(${name})`;
+ } else {
+ return 'Function';
+ }
+ }
+ // objects
+ if (Array.isArray(val)) {
+ const length = val.length;
+ let debug = '[';
+ if (length > 0) {
+ debug += debugString(val[0]);
+ }
+ for(let i = 1; i < length; i++) {
+ debug += ', ' + debugString(val[i]);
+ }
+ debug += ']';
+ return debug;
+ }
+ // Test for built-in
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
+ let className;
+ if (builtInMatches && builtInMatches.length > 1) {
+ className = builtInMatches[1];
+ } else {
+ // Failed to match the standard '[object ClassName]'
+ return toString.call(val);
+ }
+ if (className == 'Object') {
+ // we're a user defined class or Object
+ // JSON.stringify avoids problems with cycles, and is generally much
+ // easier than looping through ownProperties of `val`.
+ try {
+ return 'Object(' + JSON.stringify(val) + ')';
+ } catch (_) {
+ return 'Object';
+ }
+ }
+ // errors
+ if (val instanceof Error) {
+ return `${val.name}: ${val.message}\n${val.stack}`;
+ }
+ // TODO we could test for more things here, like `Set`s and `Map`s.
+ return className;
+}
+
+function dropObject(idx) {
+ if (idx < 132) return;
+ heap[idx] = heap_next;
+ heap_next = idx;
+}
+
+function getArrayU8FromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
+}
+
+let cachedDataViewMemory0 = null;
+function getDataViewMemory0() {
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
+ }
+ return cachedDataViewMemory0;
+}
+
+function getStringFromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return decodeText(ptr, len);
+}
+
+let cachedUint8ArrayMemory0 = null;
+function getUint8ArrayMemory0() {
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
+ }
+ return cachedUint8ArrayMemory0;
+}
+
+function getObject(idx) { return heap[idx]; }
+
+function handleError(f, args) {
+ try {
+ return f.apply(this, args);
+ } catch (e) {
+ wasm.__wbindgen_export3(addHeapObject(e));
+ }
+}
+
+let heap = new Array(128).fill(undefined);
+heap.push(undefined, null, true, false);
+
+let heap_next = heap.length;
+
+function isLikeNone(x) {
+ return x === undefined || x === null;
+}
+
+function passStringToWasm0(arg, malloc, realloc) {
+ if (realloc === undefined) {
+ const buf = cachedTextEncoder.encode(arg);
+ const ptr = malloc(buf.length, 1) >>> 0;
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
+ WASM_VECTOR_LEN = buf.length;
+ return ptr;
+ }
+
+ let len = arg.length;
+ let ptr = malloc(len, 1) >>> 0;
+
+ const mem = getUint8ArrayMemory0();
+
+ let offset = 0;
+
+ for (; offset < len; offset++) {
+ const code = arg.charCodeAt(offset);
+ if (code > 0x7F) break;
+ mem[ptr + offset] = code;
+ }
+ if (offset !== len) {
+ if (offset !== 0) {
+ arg = arg.slice(offset);
+ }
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
+ const ret = cachedTextEncoder.encodeInto(arg, view);
+
+ offset += ret.written;
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
+ }
+
+ WASM_VECTOR_LEN = offset;
+ return ptr;
+}
+
+function takeObject(idx) {
+ const ret = getObject(idx);
+ dropObject(idx);
+ return ret;
+}
+
+let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+cachedTextDecoder.decode();
+function decodeText(ptr, len) {
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
+}
+
+const cachedTextEncoder = new TextEncoder();
+
+if (!('encodeInto' in cachedTextEncoder)) {
+ cachedTextEncoder.encodeInto = function (arg, view) {
+ const buf = cachedTextEncoder.encode(arg);
+ view.set(buf);
+ return {
+ read: arg.length,
+ written: buf.length
+ };
+ }
+}
+
+let WASM_VECTOR_LEN = 0;
+
+const JsMathResultFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsmathresult_free(ptr >>> 0, 1));
+
+const JsResolvedContentFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsresolvedcontent_free(ptr >>> 0, 1));
+
+/**
+ * Result from rendering LaTeX math.
+ */
+class JsMathResult {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsMathResult.prototype);
+ obj.__wbg_ptr = ptr;
+ JsMathResultFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsMathResultFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsmathresult_free(ptr, 0);
+ }
+ /**
+ * @returns {boolean}
+ */
+ get success() {
+ const ret = wasm.__wbg_get_jsmathresult_success(this.__wbg_ptr);
+ return ret !== 0;
+ }
+ /**
+ * @param {boolean} arg0
+ */
+ set success(arg0) {
+ wasm.__wbg_set_jsmathresult_success(this.__wbg_ptr, arg0);
+ }
+ /**
+ * @returns {string}
+ */
+ get html() {
+ let deferred1_0;
+ let deferred1_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_html(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ deferred1_0 = r0;
+ deferred1_1 = r1;
+ return getStringFromWasm0(r0, r1);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
+ }
+ }
+ /**
+ * @param {string} arg0
+ */
+ set html(arg0) {
+ const ptr0 = passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_html(this.__wbg_ptr, ptr0, len0);
+ }
+ /**
+ * @returns {string | undefined}
+ */
+ get error() {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_error(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ let v1;
+ if (r0 !== 0) {
+ v1 = getStringFromWasm0(r0, r1).slice();
+ wasm.__wbindgen_export4(r0, r1 * 1, 1);
+ }
+ return v1;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+ /**
+ * @param {string | null} [arg0]
+ */
+ set error(arg0) {
+ var ptr0 = isLikeNone(arg0) ? 0 : passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_error(this.__wbg_ptr, ptr0, len0);
+ }
+}
+if (Symbol.dispose) JsMathResult.prototype[Symbol.dispose] = JsMathResult.prototype.free;
+exports.JsMathResult = JsMathResult;
+
+/**
+ * Pre-rendered embed content for synchronous rendering.
+ *
+ * Build this by calling `create_resolved_content()` and adding embeds
+ * with `resolved_content_add_embed()`.
+ */
+class JsResolvedContent {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsResolvedContent.prototype);
+ obj.__wbg_ptr = ptr;
+ JsResolvedContentFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsResolvedContentFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsresolvedcontent_free(ptr, 0);
+ }
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor() {
+ const ret = wasm.create_resolved_content();
+ this.__wbg_ptr = ret >>> 0;
+ JsResolvedContentFinalization.register(this, this.__wbg_ptr, this);
+ return this;
+ }
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ * @param {string} at_uri
+ * @param {string} html
+ */
+ addEmbed(at_uri, html) {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(html, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.jsresolvedcontent_addEmbed(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ if (r1) {
+ throw takeObject(r0);
+ }
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+}
+if (Symbol.dispose) JsResolvedContent.prototype[Symbol.dispose] = JsResolvedContent.prototype.free;
+exports.JsResolvedContent = JsResolvedContent;
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ * @returns {JsResolvedContent}
+ */
+function create_resolved_content() {
+ const ret = wasm.create_resolved_content();
+ return JsResolvedContent.__wrap(ret);
+}
+exports.create_resolved_content = create_resolved_content;
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+function init() {
+ wasm.init();
+}
+exports.init = init;
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ * @param {string} text
+ * @param {any} facets_json
+ * @returns {string}
+ */
+function render_faceted_text(text, facets_json) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(text, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.render_faceted_text(retptr, ptr0, len0, addHeapObject(facets_json));
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
+ }
+}
+exports.render_faceted_text = render_faceted_text;
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} markdown
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+function render_markdown(markdown, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_markdown(retptr, ptr0, len0, ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+exports.render_markdown = render_markdown;
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ * @param {string} latex
+ * @param {boolean} display_mode
+ * @returns {JsMathResult}
+ */
+function render_math(latex, display_mode) {
+ const ptr0 = passStringToWasm0(latex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ret = wasm.render_math(ptr0, len0, display_mode);
+ return JsMathResult.__wrap(ret);
+}
+exports.render_math = render_math;
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} at_uri
+ * @param {any} record_json
+ * @param {any | null} [fallback_author]
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+function render_record(at_uri, record_json, fallback_author, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_record(retptr, ptr0, len0, addHeapObject(record_json), isLikeNone(fallback_author) ? 0 : addHeapObject(fallback_author), ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+exports.render_record = render_record;
+
+exports.__wbg_Error_52673b7de5a0ca89 = function(arg0, arg1) {
+ const ret = Error(getStringFromWasm0(arg0, arg1));
+ return addHeapObject(ret);
+};
+
+exports.__wbg_Number_2d1dcfcf4ec51736 = function(arg0) {
+ const ret = Number(getObject(arg0));
+ return ret;
+};
+
+exports.__wbg_String_8f0eb39a4a4c2f66 = function(arg0, arg1) {
+ const ret = String(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+exports.__wbg___wbindgen_bigint_get_as_i64_6e32f5e6aff02e1d = function(arg0, arg1) {
+ const v = getObject(arg1);
+ const ret = typeof(v) === 'bigint' ? v : undefined;
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+};
+
+exports.__wbg___wbindgen_boolean_get_dea25b33882b895b = function(arg0) {
+ const v = getObject(arg0);
+ const ret = typeof(v) === 'boolean' ? v : undefined;
+ return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
+};
+
+exports.__wbg___wbindgen_debug_string_adfb662ae34724b6 = function(arg0, arg1) {
+ const ret = debugString(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+exports.__wbg___wbindgen_in_0d3e1e8f0c669317 = function(arg0, arg1) {
+ const ret = getObject(arg0) in getObject(arg1);
+ return ret;
+};
+
+exports.__wbg___wbindgen_is_bigint_0e1a2e3f55cfae27 = function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'bigint';
+ return ret;
+};
+
+exports.__wbg___wbindgen_is_function_8d400b8b1af978cd = function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'function';
+ return ret;
+};
+
+exports.__wbg___wbindgen_is_object_ce774f3490692386 = function(arg0) {
+ const val = getObject(arg0);
+ const ret = typeof(val) === 'object' && val !== null;
+ return ret;
+};
+
+exports.__wbg___wbindgen_is_undefined_f6b95eab589e0269 = function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+};
+
+exports.__wbg___wbindgen_jsval_eq_b6101cc9cef1fe36 = function(arg0, arg1) {
+ const ret = getObject(arg0) === getObject(arg1);
+ return ret;
+};
+
+exports.__wbg___wbindgen_jsval_loose_eq_766057600fdd1b0d = function(arg0, arg1) {
+ const ret = getObject(arg0) == getObject(arg1);
+ return ret;
+};
+
+exports.__wbg___wbindgen_number_get_9619185a74197f95 = function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'number' ? obj : undefined;
+ getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+};
+
+exports.__wbg___wbindgen_string_get_a2a31e16edf96e42 = function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'string' ? obj : undefined;
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+exports.__wbg___wbindgen_throw_dd24417ed36fc46e = function(arg0, arg1) {
+ throw new Error(getStringFromWasm0(arg0, arg1));
+};
+
+exports.__wbg_call_abb4ff46ce38be40 = function() { return handleError(function (arg0, arg1) {
+ const ret = getObject(arg0).call(getObject(arg1));
+ return addHeapObject(ret);
+}, arguments) };
+
+exports.__wbg_done_62ea16af4ce34b24 = function(arg0) {
+ const ret = getObject(arg0).done;
+ return ret;
+};
+
+exports.__wbg_entries_83c79938054e065f = function(arg0) {
+ const ret = Object.entries(getObject(arg0));
+ return addHeapObject(ret);
+};
+
+exports.__wbg_error_7534b8e9a36f1ab4 = function(arg0, arg1) {
+ let deferred0_0;
+ let deferred0_1;
+ try {
+ deferred0_0 = arg0;
+ deferred0_1 = arg1;
+ console.error(getStringFromWasm0(arg0, arg1));
+ } finally {
+ wasm.__wbindgen_export4(deferred0_0, deferred0_1, 1);
+ }
+};
+
+exports.__wbg_get_6b7bd52aca3f9671 = function(arg0, arg1) {
+ const ret = getObject(arg0)[arg1 >>> 0];
+ return addHeapObject(ret);
+};
+
+exports.__wbg_get_af9dab7e9603ea93 = function() { return handleError(function (arg0, arg1) {
+ const ret = Reflect.get(getObject(arg0), getObject(arg1));
+ return addHeapObject(ret);
+}, arguments) };
+
+exports.__wbg_get_with_ref_key_1dc361bd10053bfe = function(arg0, arg1) {
+ const ret = getObject(arg0)[getObject(arg1)];
+ return addHeapObject(ret);
+};
+
+exports.__wbg_instanceof_ArrayBuffer_f3320d2419cd0355 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof ArrayBuffer;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+exports.__wbg_instanceof_Map_084be8da74364158 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Map;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+exports.__wbg_instanceof_Uint8Array_da54ccc9d3e09434 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Uint8Array;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+};
+
+exports.__wbg_isArray_51fd9e6422c0a395 = function(arg0) {
+ const ret = Array.isArray(getObject(arg0));
+ return ret;
+};
+
+exports.__wbg_isSafeInteger_ae7d3f054d55fa16 = function(arg0) {
+ const ret = Number.isSafeInteger(getObject(arg0));
+ return ret;
+};
+
+exports.__wbg_iterator_27b7c8b35ab3e86b = function() {
+ const ret = Symbol.iterator;
+ return addHeapObject(ret);
+};
+
+exports.__wbg_length_22ac23eaec9d8053 = function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+};
+
+exports.__wbg_length_d45040a40c570362 = function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+};
+
+exports.__wbg_new_6421f6084cc5bc5a = function(arg0) {
+ const ret = new Uint8Array(getObject(arg0));
+ return addHeapObject(ret);
+};
+
+exports.__wbg_new_8a6f238a6ece86ea = function() {
+ const ret = new Error();
+ return addHeapObject(ret);
+};
+
+exports.__wbg_next_138a17bbf04e926c = function(arg0) {
+ const ret = getObject(arg0).next;
+ return addHeapObject(ret);
+};
+
+exports.__wbg_next_3cfe5c0fe2a4cc53 = function() { return handleError(function (arg0) {
+ const ret = getObject(arg0).next();
+ return addHeapObject(ret);
+}, arguments) };
+
+exports.__wbg_prototypesetcall_dfe9b766cdc1f1fd = function(arg0, arg1, arg2) {
+ Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
+};
+
+exports.__wbg_stack_0ed75d68575b0f3c = function(arg0, arg1) {
+ const ret = getObject(arg1).stack;
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+};
+
+exports.__wbg_value_57b7b035e117f7ee = function(arg0) {
+ const ret = getObject(arg0).value;
+ return addHeapObject(ret);
+};
+
+exports.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
+ // Cast intrinsic for `Ref(String) -> Externref`.
+ const ret = getStringFromWasm0(arg0, arg1);
+ return addHeapObject(ret);
+};
+
+exports.__wbindgen_cast_4625c577ab2ec9ee = function(arg0) {
+ // Cast intrinsic for `U64 -> Externref`.
+ const ret = BigInt.asUintN(64, arg0);
+ return addHeapObject(ret);
+};
+
+exports.__wbindgen_cast_9ae0607507abb057 = function(arg0) {
+ // Cast intrinsic for `I64 -> Externref`.
+ const ret = arg0;
+ return addHeapObject(ret);
+};
+
+exports.__wbindgen_object_clone_ref = function(arg0) {
+ const ret = getObject(arg0);
+ return addHeapObject(ret);
+};
+
+exports.__wbindgen_object_drop_ref = function(arg0) {
+ takeObject(arg0);
+};
+
+exports.__wbindgen_object_is_undefined = function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+};
+
+const wasmPath = `${__dirname}/weaver_renderer_bg.wasm`;
+const wasmBytes = require('fs').readFileSync(wasmPath);
+const wasmModule = new WebAssembly.Module(wasmBytes);
+const wasm = exports.__wasm = new WebAssembly.Instance(wasmModule, imports).exports;
+
+wasm.__wbindgen_start();
diff --git a/crates/weaver-renderer-js/pkg/full/nodejs/weaver_renderer_bg.wasm.d.ts b/crates/weaver-renderer-js/pkg/full/nodejs/weaver_renderer_bg.wasm.d.ts
new file mode 100644
index 0000000..16b3955
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/nodejs/weaver_renderer_bg.wasm.d.ts
@@ -0,0 +1,25 @@
+/* tslint:disable */
+/* eslint-disable */
+export const memory: WebAssembly.Memory;
+export const __wbg_get_jsmathresult_error: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_html: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_success: (a: number) => number;
+export const __wbg_jsmathresult_free: (a: number, b: number) => void;
+export const __wbg_jsresolvedcontent_free: (a: number, b: number) => void;
+export const __wbg_set_jsmathresult_error: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_html: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_success: (a: number, b: number) => void;
+export const create_resolved_content: () => number;
+export const init: () => void;
+export const jsresolvedcontent_addEmbed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const render_faceted_text: (a: number, b: number, c: number, d: number) => void;
+export const render_markdown: (a: number, b: number, c: number, d: number) => void;
+export const render_math: (a: number, b: number, c: number) => number;
+export const render_record: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const jsresolvedcontent_new: () => number;
+export const __wbindgen_export: (a: number, b: number) => number;
+export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
+export const __wbindgen_export3: (a: number) => void;
+export const __wbindgen_export4: (a: number, b: number, c: number) => void;
+export const __wbindgen_add_to_stack_pointer: (a: number) => number;
+export const __wbindgen_start: () => void;
diff --git a/crates/weaver-renderer-js/pkg/full/package.json b/crates/weaver-renderer-js/pkg/full/package.json
new file mode 100644
index 0000000..7eddcc1
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "@weaver.sh/renderer-full",
+ "version": "0.1.1",
+ "description": "AT Protocol record renderer with syntax highlighting",
+ "license": "MPL-2.0",
+ "repository": {
+ "type": "git",
+ "url": "https://tangled.org/nonbinary.computer/weaver"
+ },
+ "keywords": ["atproto", "bluesky", "markdown", "renderer", "wasm"],
+ "main": "nodejs/weaver_renderer.js",
+ "module": "bundler/weaver_renderer.js",
+ "browser": "web/weaver_renderer.js",
+ "types": "bundler/weaver_renderer.d.ts",
+ "exports": {
+ ".": {
+ "deno": "./deno/weaver_renderer.js",
+ "node": {
+ "import": "./nodejs/weaver_renderer.js",
+ "require": "./nodejs/weaver_renderer.js"
+ },
+ "browser": {
+ "import": "./web/weaver_renderer.js"
+ },
+ "default": "./bundler/weaver_renderer.js"
+ },
+ "./bundler": {
+ "import": "./bundler/weaver_renderer.js",
+ "types": "./bundler/weaver_renderer.d.ts"
+ },
+ "./web": {
+ "import": "./web/weaver_renderer.js",
+ "types": "./web/weaver_renderer.d.ts"
+ },
+ "./nodejs": {
+ "import": "./nodejs/weaver_renderer.js",
+ "require": "./nodejs/weaver_renderer.js",
+ "types": "./nodejs/weaver_renderer.d.ts"
+ },
+ "./deno": {
+ "import": "./deno/weaver_renderer.js",
+ "types": "./deno/weaver_renderer.d.ts"
+ }
+ },
+ "files": [
+ "bundler/",
+ "web/",
+ "nodejs/",
+ "deno/",
+ "README.md"
+ ]
+}
diff --git a/crates/weaver-renderer-js/pkg/full/web/LICENSE b/crates/weaver-renderer-js/pkg/full/web/LICENSE
new file mode 100644
index 0000000..a612ad9
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/web/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/crates/weaver-renderer-js/pkg/full/web/weaver_renderer.d.ts b/crates/weaver-renderer-js/pkg/full/web/weaver_renderer.d.ts
new file mode 100644
index 0000000..d564d73
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/web/weaver_renderer.d.ts
@@ -0,0 +1,134 @@
+/* tslint:disable */
+/* eslint-disable */
+
+export class JsMathResult {
+ private constructor();
+ free(): void;
+ [Symbol.dispose](): void;
+ success: boolean;
+ html: string;
+ get error(): string | undefined;
+ set error(value: string | null | undefined);
+}
+
+export class JsResolvedContent {
+ free(): void;
+ [Symbol.dispose](): void;
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor();
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ */
+ addEmbed(at_uri: string, html: string): void;
+}
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ */
+export function create_resolved_content(): JsResolvedContent;
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init(): void;
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ */
+export function render_faceted_text(text: string, facets_json: any): string;
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_markdown(markdown: string, resolved_content?: JsResolvedContent | null): string;
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ */
+export function render_math(latex: string, display_mode: boolean): JsMathResult;
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ */
+export function render_record(at_uri: string, record_json: any, fallback_author?: any | null, resolved_content?: JsResolvedContent | null): string;
+
+export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
+
+export interface InitOutput {
+ readonly memory: WebAssembly.Memory;
+ readonly __wbg_get_jsmathresult_error: (a: number, b: number) => void;
+ readonly __wbg_get_jsmathresult_html: (a: number, b: number) => void;
+ readonly __wbg_get_jsmathresult_success: (a: number) => number;
+ readonly __wbg_jsmathresult_free: (a: number, b: number) => void;
+ readonly __wbg_jsresolvedcontent_free: (a: number, b: number) => void;
+ readonly __wbg_set_jsmathresult_error: (a: number, b: number, c: number) => void;
+ readonly __wbg_set_jsmathresult_html: (a: number, b: number, c: number) => void;
+ readonly __wbg_set_jsmathresult_success: (a: number, b: number) => void;
+ readonly create_resolved_content: () => number;
+ readonly init: () => void;
+ readonly jsresolvedcontent_addEmbed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+ readonly render_faceted_text: (a: number, b: number, c: number, d: number) => void;
+ readonly render_markdown: (a: number, b: number, c: number, d: number) => void;
+ readonly render_math: (a: number, b: number, c: number) => number;
+ readonly render_record: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+ readonly jsresolvedcontent_new: () => number;
+ readonly __wbindgen_export: (a: number, b: number) => number;
+ readonly __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
+ readonly __wbindgen_export3: (a: number) => void;
+ readonly __wbindgen_export4: (a: number, b: number, c: number) => void;
+ readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
+ readonly __wbindgen_start: () => void;
+}
+
+export type SyncInitInput = BufferSource | WebAssembly.Module;
+
+/**
+* Instantiates the given `module`, which can either be bytes or
+* a precompiled `WebAssembly.Module`.
+*
+* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
+*
+* @returns {InitOutput}
+*/
+export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
+
+/**
+* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
+* for everything else, calls `WebAssembly.instantiate` directly.
+*
+* @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated.
+*
+* @returns {Promise}
+*/
+export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise;
diff --git a/crates/weaver-renderer-js/pkg/full/web/weaver_renderer.js b/crates/weaver-renderer-js/pkg/full/web/weaver_renderer.js
new file mode 100644
index 0000000..a2bfbff
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/web/weaver_renderer.js
@@ -0,0 +1,849 @@
+let wasm;
+
+function addHeapObject(obj) {
+ if (heap_next === heap.length) heap.push(heap.length + 1);
+ const idx = heap_next;
+ heap_next = heap[idx];
+
+ heap[idx] = obj;
+ return idx;
+}
+
+function _assertClass(instance, klass) {
+ if (!(instance instanceof klass)) {
+ throw new Error(`expected instance of ${klass.name}`);
+ }
+}
+
+function debugString(val) {
+ // primitive types
+ const type = typeof val;
+ if (type == 'number' || type == 'boolean' || val == null) {
+ return `${val}`;
+ }
+ if (type == 'string') {
+ return `"${val}"`;
+ }
+ if (type == 'symbol') {
+ const description = val.description;
+ if (description == null) {
+ return 'Symbol';
+ } else {
+ return `Symbol(${description})`;
+ }
+ }
+ if (type == 'function') {
+ const name = val.name;
+ if (typeof name == 'string' && name.length > 0) {
+ return `Function(${name})`;
+ } else {
+ return 'Function';
+ }
+ }
+ // objects
+ if (Array.isArray(val)) {
+ const length = val.length;
+ let debug = '[';
+ if (length > 0) {
+ debug += debugString(val[0]);
+ }
+ for(let i = 1; i < length; i++) {
+ debug += ', ' + debugString(val[i]);
+ }
+ debug += ']';
+ return debug;
+ }
+ // Test for built-in
+ const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
+ let className;
+ if (builtInMatches && builtInMatches.length > 1) {
+ className = builtInMatches[1];
+ } else {
+ // Failed to match the standard '[object ClassName]'
+ return toString.call(val);
+ }
+ if (className == 'Object') {
+ // we're a user defined class or Object
+ // JSON.stringify avoids problems with cycles, and is generally much
+ // easier than looping through ownProperties of `val`.
+ try {
+ return 'Object(' + JSON.stringify(val) + ')';
+ } catch (_) {
+ return 'Object';
+ }
+ }
+ // errors
+ if (val instanceof Error) {
+ return `${val.name}: ${val.message}\n${val.stack}`;
+ }
+ // TODO we could test for more things here, like `Set`s and `Map`s.
+ return className;
+}
+
+function dropObject(idx) {
+ if (idx < 132) return;
+ heap[idx] = heap_next;
+ heap_next = idx;
+}
+
+function getArrayU8FromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
+}
+
+let cachedDataViewMemory0 = null;
+function getDataViewMemory0() {
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
+ }
+ return cachedDataViewMemory0;
+}
+
+function getStringFromWasm0(ptr, len) {
+ ptr = ptr >>> 0;
+ return decodeText(ptr, len);
+}
+
+let cachedUint8ArrayMemory0 = null;
+function getUint8ArrayMemory0() {
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
+ }
+ return cachedUint8ArrayMemory0;
+}
+
+function getObject(idx) { return heap[idx]; }
+
+function handleError(f, args) {
+ try {
+ return f.apply(this, args);
+ } catch (e) {
+ wasm.__wbindgen_export3(addHeapObject(e));
+ }
+}
+
+let heap = new Array(128).fill(undefined);
+heap.push(undefined, null, true, false);
+
+let heap_next = heap.length;
+
+function isLikeNone(x) {
+ return x === undefined || x === null;
+}
+
+function passStringToWasm0(arg, malloc, realloc) {
+ if (realloc === undefined) {
+ const buf = cachedTextEncoder.encode(arg);
+ const ptr = malloc(buf.length, 1) >>> 0;
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
+ WASM_VECTOR_LEN = buf.length;
+ return ptr;
+ }
+
+ let len = arg.length;
+ let ptr = malloc(len, 1) >>> 0;
+
+ const mem = getUint8ArrayMemory0();
+
+ let offset = 0;
+
+ for (; offset < len; offset++) {
+ const code = arg.charCodeAt(offset);
+ if (code > 0x7F) break;
+ mem[ptr + offset] = code;
+ }
+ if (offset !== len) {
+ if (offset !== 0) {
+ arg = arg.slice(offset);
+ }
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
+ const ret = cachedTextEncoder.encodeInto(arg, view);
+
+ offset += ret.written;
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
+ }
+
+ WASM_VECTOR_LEN = offset;
+ return ptr;
+}
+
+function takeObject(idx) {
+ const ret = getObject(idx);
+ dropObject(idx);
+ return ret;
+}
+
+let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+cachedTextDecoder.decode();
+const MAX_SAFARI_DECODE_BYTES = 2146435072;
+let numBytesDecoded = 0;
+function decodeText(ptr, len) {
+ numBytesDecoded += len;
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+ cachedTextDecoder.decode();
+ numBytesDecoded = len;
+ }
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
+}
+
+const cachedTextEncoder = new TextEncoder();
+
+if (!('encodeInto' in cachedTextEncoder)) {
+ cachedTextEncoder.encodeInto = function (arg, view) {
+ const buf = cachedTextEncoder.encode(arg);
+ view.set(buf);
+ return {
+ read: arg.length,
+ written: buf.length
+ };
+ }
+}
+
+let WASM_VECTOR_LEN = 0;
+
+const JsMathResultFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsmathresult_free(ptr >>> 0, 1));
+
+const JsResolvedContentFinalization = (typeof FinalizationRegistry === 'undefined')
+ ? { register: () => {}, unregister: () => {} }
+ : new FinalizationRegistry(ptr => wasm.__wbg_jsresolvedcontent_free(ptr >>> 0, 1));
+
+/**
+ * Result from rendering LaTeX math.
+ */
+export class JsMathResult {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsMathResult.prototype);
+ obj.__wbg_ptr = ptr;
+ JsMathResultFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsMathResultFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsmathresult_free(ptr, 0);
+ }
+ /**
+ * @returns {boolean}
+ */
+ get success() {
+ const ret = wasm.__wbg_get_jsmathresult_success(this.__wbg_ptr);
+ return ret !== 0;
+ }
+ /**
+ * @param {boolean} arg0
+ */
+ set success(arg0) {
+ wasm.__wbg_set_jsmathresult_success(this.__wbg_ptr, arg0);
+ }
+ /**
+ * @returns {string}
+ */
+ get html() {
+ let deferred1_0;
+ let deferred1_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_html(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ deferred1_0 = r0;
+ deferred1_1 = r1;
+ return getStringFromWasm0(r0, r1);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred1_0, deferred1_1, 1);
+ }
+ }
+ /**
+ * @param {string} arg0
+ */
+ set html(arg0) {
+ const ptr0 = passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_html(this.__wbg_ptr, ptr0, len0);
+ }
+ /**
+ * @returns {string | undefined}
+ */
+ get error() {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ wasm.__wbg_get_jsmathresult_error(retptr, this.__wbg_ptr);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ let v1;
+ if (r0 !== 0) {
+ v1 = getStringFromWasm0(r0, r1).slice();
+ wasm.__wbindgen_export4(r0, r1 * 1, 1);
+ }
+ return v1;
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+ /**
+ * @param {string | null} [arg0]
+ */
+ set error(arg0) {
+ var ptr0 = isLikeNone(arg0) ? 0 : passStringToWasm0(arg0, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len0 = WASM_VECTOR_LEN;
+ wasm.__wbg_set_jsmathresult_error(this.__wbg_ptr, ptr0, len0);
+ }
+}
+if (Symbol.dispose) JsMathResult.prototype[Symbol.dispose] = JsMathResult.prototype.free;
+
+/**
+ * Pre-rendered embed content for synchronous rendering.
+ *
+ * Build this by calling `create_resolved_content()` and adding embeds
+ * with `resolved_content_add_embed()`.
+ */
+export class JsResolvedContent {
+ static __wrap(ptr) {
+ ptr = ptr >>> 0;
+ const obj = Object.create(JsResolvedContent.prototype);
+ obj.__wbg_ptr = ptr;
+ JsResolvedContentFinalization.register(obj, obj.__wbg_ptr, obj);
+ return obj;
+ }
+ __destroy_into_raw() {
+ const ptr = this.__wbg_ptr;
+ this.__wbg_ptr = 0;
+ JsResolvedContentFinalization.unregister(this);
+ return ptr;
+ }
+ free() {
+ const ptr = this.__destroy_into_raw();
+ wasm.__wbg_jsresolvedcontent_free(ptr, 0);
+ }
+ /**
+ * Create an empty resolved content container.
+ */
+ constructor() {
+ const ret = wasm.create_resolved_content();
+ this.__wbg_ptr = ret >>> 0;
+ JsResolvedContentFinalization.register(this, this.__wbg_ptr, this);
+ return this;
+ }
+ /**
+ * Add pre-rendered embed HTML for an AT URI.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `html` - The pre-rendered HTML for this embed
+ * @param {string} at_uri
+ * @param {string} html
+ */
+ addEmbed(at_uri, html) {
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ptr1 = passStringToWasm0(html, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ wasm.jsresolvedcontent_addEmbed(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ if (r1) {
+ throw takeObject(r0);
+ }
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ }
+ }
+}
+if (Symbol.dispose) JsResolvedContent.prototype[Symbol.dispose] = JsResolvedContent.prototype.free;
+
+/**
+ * Create an empty resolved content container.
+ *
+ * Use this to pre-render embeds before calling render functions.
+ * @returns {JsResolvedContent}
+ */
+export function create_resolved_content() {
+ const ret = wasm.create_resolved_content();
+ return JsResolvedContent.__wrap(ret);
+}
+
+/**
+ * Initialize panic hook for better error messages in console.
+ */
+export function init() {
+ wasm.init();
+}
+
+/**
+ * Render faceted text (rich text with mentions, links, etc.) to HTML.
+ *
+ * Accepts facets from several AT Protocol lexicons (app.bsky, pub.leaflet, blog.pckt).
+ *
+ * # Arguments
+ * * `text` - The plain text content
+ * * `facets_json` - Array of facets with `index` (byteStart/byteEnd) and `features` array
+ * @param {string} text
+ * @param {any} facets_json
+ * @returns {string}
+ */
+export function render_faceted_text(text, facets_json) {
+ let deferred3_0;
+ let deferred3_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(text, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ wasm.render_faceted_text(retptr, ptr0, len0, addHeapObject(facets_json));
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr2 = r0;
+ var len2 = r1;
+ if (r3) {
+ ptr2 = 0; len2 = 0;
+ throw takeObject(r2);
+ }
+ deferred3_0 = ptr2;
+ deferred3_1 = len2;
+ return getStringFromWasm0(ptr2, len2);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred3_0, deferred3_1, 1);
+ }
+}
+
+/**
+ * Render markdown to HTML.
+ *
+ * # Arguments
+ * * `markdown` - The markdown source text
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} markdown
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_markdown(markdown, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(markdown, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_markdown(retptr, ptr0, len0, ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+/**
+ * Render LaTeX math to MathML.
+ *
+ * # Arguments
+ * * `latex` - The LaTeX math expression
+ * * `display_mode` - true for display math (block), false for inline math
+ * @param {string} latex
+ * @param {boolean} display_mode
+ * @returns {JsMathResult}
+ */
+export function render_math(latex, display_mode) {
+ const ptr0 = passStringToWasm0(latex, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ const ret = wasm.render_math(ptr0, len0, display_mode);
+ return JsMathResult.__wrap(ret);
+}
+
+/**
+ * Render an AT Protocol record as HTML.
+ *
+ * Takes a record URI and the record data (typically fetched from an appview).
+ * Returns the rendered HTML string.
+ *
+ * # Arguments
+ * * `at_uri` - The AT Protocol URI (e.g., "at://did:plc:.../app.bsky.feed.post/...")
+ * * `record_json` - The record data as JSON
+ * * `fallback_author` - Optional author profile for records that don't include author info
+ * * `resolved_content` - Optional pre-rendered embed content
+ * @param {string} at_uri
+ * @param {any} record_json
+ * @param {any | null} [fallback_author]
+ * @param {JsResolvedContent | null} [resolved_content]
+ * @returns {string}
+ */
+export function render_record(at_uri, record_json, fallback_author, resolved_content) {
+ let deferred4_0;
+ let deferred4_1;
+ try {
+ const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
+ const ptr0 = passStringToWasm0(at_uri, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len0 = WASM_VECTOR_LEN;
+ let ptr1 = 0;
+ if (!isLikeNone(resolved_content)) {
+ _assertClass(resolved_content, JsResolvedContent);
+ ptr1 = resolved_content.__destroy_into_raw();
+ }
+ wasm.render_record(retptr, ptr0, len0, addHeapObject(record_json), isLikeNone(fallback_author) ? 0 : addHeapObject(fallback_author), ptr1);
+ var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
+ var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
+ var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
+ var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
+ var ptr3 = r0;
+ var len3 = r1;
+ if (r3) {
+ ptr3 = 0; len3 = 0;
+ throw takeObject(r2);
+ }
+ deferred4_0 = ptr3;
+ deferred4_1 = len3;
+ return getStringFromWasm0(ptr3, len3);
+ } finally {
+ wasm.__wbindgen_add_to_stack_pointer(16);
+ wasm.__wbindgen_export4(deferred4_0, deferred4_1, 1);
+ }
+}
+
+const EXPECTED_RESPONSE_TYPES = new Set(['basic', 'cors', 'default']);
+
+async function __wbg_load(module, imports) {
+ if (typeof Response === 'function' && module instanceof Response) {
+ if (typeof WebAssembly.instantiateStreaming === 'function') {
+ try {
+ return await WebAssembly.instantiateStreaming(module, imports);
+ } catch (e) {
+ const validResponse = module.ok && EXPECTED_RESPONSE_TYPES.has(module.type);
+
+ if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
+ console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
+
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ const bytes = await module.arrayBuffer();
+ return await WebAssembly.instantiate(bytes, imports);
+ } else {
+ const instance = await WebAssembly.instantiate(module, imports);
+
+ if (instance instanceof WebAssembly.Instance) {
+ return { instance, module };
+ } else {
+ return instance;
+ }
+ }
+}
+
+function __wbg_get_imports() {
+ const imports = {};
+ imports.wbg = {};
+ imports.wbg.__wbg_Error_52673b7de5a0ca89 = function(arg0, arg1) {
+ const ret = Error(getStringFromWasm0(arg0, arg1));
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_Number_2d1dcfcf4ec51736 = function(arg0) {
+ const ret = Number(getObject(arg0));
+ return ret;
+ };
+ imports.wbg.__wbg_String_8f0eb39a4a4c2f66 = function(arg0, arg1) {
+ const ret = String(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ };
+ imports.wbg.__wbg___wbindgen_bigint_get_as_i64_6e32f5e6aff02e1d = function(arg0, arg1) {
+ const v = getObject(arg1);
+ const ret = typeof(v) === 'bigint' ? v : undefined;
+ getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+ };
+ imports.wbg.__wbg___wbindgen_boolean_get_dea25b33882b895b = function(arg0) {
+ const v = getObject(arg0);
+ const ret = typeof(v) === 'boolean' ? v : undefined;
+ return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
+ };
+ imports.wbg.__wbg___wbindgen_debug_string_adfb662ae34724b6 = function(arg0, arg1) {
+ const ret = debugString(getObject(arg1));
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ };
+ imports.wbg.__wbg___wbindgen_in_0d3e1e8f0c669317 = function(arg0, arg1) {
+ const ret = getObject(arg0) in getObject(arg1);
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_is_bigint_0e1a2e3f55cfae27 = function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'bigint';
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_is_function_8d400b8b1af978cd = function(arg0) {
+ const ret = typeof(getObject(arg0)) === 'function';
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_is_object_ce774f3490692386 = function(arg0) {
+ const val = getObject(arg0);
+ const ret = typeof(val) === 'object' && val !== null;
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_is_undefined_f6b95eab589e0269 = function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_jsval_eq_b6101cc9cef1fe36 = function(arg0, arg1) {
+ const ret = getObject(arg0) === getObject(arg1);
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_jsval_loose_eq_766057600fdd1b0d = function(arg0, arg1) {
+ const ret = getObject(arg0) == getObject(arg1);
+ return ret;
+ };
+ imports.wbg.__wbg___wbindgen_number_get_9619185a74197f95 = function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'number' ? obj : undefined;
+ getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
+ };
+ imports.wbg.__wbg___wbindgen_string_get_a2a31e16edf96e42 = function(arg0, arg1) {
+ const obj = getObject(arg1);
+ const ret = typeof(obj) === 'string' ? obj : undefined;
+ var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ var len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ };
+ imports.wbg.__wbg___wbindgen_throw_dd24417ed36fc46e = function(arg0, arg1) {
+ throw new Error(getStringFromWasm0(arg0, arg1));
+ };
+ imports.wbg.__wbg_call_abb4ff46ce38be40 = function() { return handleError(function (arg0, arg1) {
+ const ret = getObject(arg0).call(getObject(arg1));
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbg_done_62ea16af4ce34b24 = function(arg0) {
+ const ret = getObject(arg0).done;
+ return ret;
+ };
+ imports.wbg.__wbg_entries_83c79938054e065f = function(arg0) {
+ const ret = Object.entries(getObject(arg0));
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_error_7534b8e9a36f1ab4 = function(arg0, arg1) {
+ let deferred0_0;
+ let deferred0_1;
+ try {
+ deferred0_0 = arg0;
+ deferred0_1 = arg1;
+ console.error(getStringFromWasm0(arg0, arg1));
+ } finally {
+ wasm.__wbindgen_export4(deferred0_0, deferred0_1, 1);
+ }
+ };
+ imports.wbg.__wbg_get_6b7bd52aca3f9671 = function(arg0, arg1) {
+ const ret = getObject(arg0)[arg1 >>> 0];
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_get_af9dab7e9603ea93 = function() { return handleError(function (arg0, arg1) {
+ const ret = Reflect.get(getObject(arg0), getObject(arg1));
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbg_get_with_ref_key_1dc361bd10053bfe = function(arg0, arg1) {
+ const ret = getObject(arg0)[getObject(arg1)];
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_instanceof_ArrayBuffer_f3320d2419cd0355 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof ArrayBuffer;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ };
+ imports.wbg.__wbg_instanceof_Map_084be8da74364158 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Map;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ };
+ imports.wbg.__wbg_instanceof_Uint8Array_da54ccc9d3e09434 = function(arg0) {
+ let result;
+ try {
+ result = getObject(arg0) instanceof Uint8Array;
+ } catch (_) {
+ result = false;
+ }
+ const ret = result;
+ return ret;
+ };
+ imports.wbg.__wbg_isArray_51fd9e6422c0a395 = function(arg0) {
+ const ret = Array.isArray(getObject(arg0));
+ return ret;
+ };
+ imports.wbg.__wbg_isSafeInteger_ae7d3f054d55fa16 = function(arg0) {
+ const ret = Number.isSafeInteger(getObject(arg0));
+ return ret;
+ };
+ imports.wbg.__wbg_iterator_27b7c8b35ab3e86b = function() {
+ const ret = Symbol.iterator;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_length_22ac23eaec9d8053 = function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+ };
+ imports.wbg.__wbg_length_d45040a40c570362 = function(arg0) {
+ const ret = getObject(arg0).length;
+ return ret;
+ };
+ imports.wbg.__wbg_new_6421f6084cc5bc5a = function(arg0) {
+ const ret = new Uint8Array(getObject(arg0));
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_new_8a6f238a6ece86ea = function() {
+ const ret = new Error();
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_next_138a17bbf04e926c = function(arg0) {
+ const ret = getObject(arg0).next;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbg_next_3cfe5c0fe2a4cc53 = function() { return handleError(function (arg0) {
+ const ret = getObject(arg0).next();
+ return addHeapObject(ret);
+ }, arguments) };
+ imports.wbg.__wbg_prototypesetcall_dfe9b766cdc1f1fd = function(arg0, arg1, arg2) {
+ Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), getObject(arg2));
+ };
+ imports.wbg.__wbg_stack_0ed75d68575b0f3c = function(arg0, arg1) {
+ const ret = getObject(arg1).stack;
+ const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export, wasm.__wbindgen_export2);
+ const len1 = WASM_VECTOR_LEN;
+ getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
+ getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
+ };
+ imports.wbg.__wbg_value_57b7b035e117f7ee = function(arg0) {
+ const ret = getObject(arg0).value;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_cast_2241b6af4c4b2941 = function(arg0, arg1) {
+ // Cast intrinsic for `Ref(String) -> Externref`.
+ const ret = getStringFromWasm0(arg0, arg1);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_cast_4625c577ab2ec9ee = function(arg0) {
+ // Cast intrinsic for `U64 -> Externref`.
+ const ret = BigInt.asUintN(64, arg0);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_cast_9ae0607507abb057 = function(arg0) {
+ // Cast intrinsic for `I64 -> Externref`.
+ const ret = arg0;
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
+ const ret = getObject(arg0);
+ return addHeapObject(ret);
+ };
+ imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
+ takeObject(arg0);
+ };
+ imports.wbg.__wbindgen_object_is_undefined = function(arg0) {
+ const ret = getObject(arg0) === undefined;
+ return ret;
+ };
+
+ return imports;
+}
+
+function __wbg_finalize_init(instance, module) {
+ wasm = instance.exports;
+ __wbg_init.__wbindgen_wasm_module = module;
+ cachedDataViewMemory0 = null;
+ cachedUint8ArrayMemory0 = null;
+
+
+ wasm.__wbindgen_start();
+ return wasm;
+}
+
+function initSync(module) {
+ if (wasm !== undefined) return wasm;
+
+
+ if (typeof module !== 'undefined') {
+ if (Object.getPrototypeOf(module) === Object.prototype) {
+ ({module} = module)
+ } else {
+ console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
+ }
+ }
+
+ const imports = __wbg_get_imports();
+ if (!(module instanceof WebAssembly.Module)) {
+ module = new WebAssembly.Module(module);
+ }
+ const instance = new WebAssembly.Instance(module, imports);
+ return __wbg_finalize_init(instance, module);
+}
+
+async function __wbg_init(module_or_path) {
+ if (wasm !== undefined) return wasm;
+
+
+ if (typeof module_or_path !== 'undefined') {
+ if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
+ ({module_or_path} = module_or_path)
+ } else {
+ console.warn('using deprecated parameters for the initialization function; pass a single object instead')
+ }
+ }
+
+ if (typeof module_or_path === 'undefined') {
+ module_or_path = new URL('weaver_renderer_bg.wasm', import.meta.url);
+ }
+ const imports = __wbg_get_imports();
+
+ if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
+ module_or_path = fetch(module_or_path);
+ }
+
+ const { instance, module } = await __wbg_load(await module_or_path, imports);
+
+ return __wbg_finalize_init(instance, module);
+}
+
+export { initSync };
+export default __wbg_init;
diff --git a/crates/weaver-renderer-js/pkg/full/web/weaver_renderer_bg.wasm.d.ts b/crates/weaver-renderer-js/pkg/full/web/weaver_renderer_bg.wasm.d.ts
new file mode 100644
index 0000000..16b3955
--- /dev/null
+++ b/crates/weaver-renderer-js/pkg/full/web/weaver_renderer_bg.wasm.d.ts
@@ -0,0 +1,25 @@
+/* tslint:disable */
+/* eslint-disable */
+export const memory: WebAssembly.Memory;
+export const __wbg_get_jsmathresult_error: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_html: (a: number, b: number) => void;
+export const __wbg_get_jsmathresult_success: (a: number) => number;
+export const __wbg_jsmathresult_free: (a: number, b: number) => void;
+export const __wbg_jsresolvedcontent_free: (a: number, b: number) => void;
+export const __wbg_set_jsmathresult_error: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_html: (a: number, b: number, c: number) => void;
+export const __wbg_set_jsmathresult_success: (a: number, b: number) => void;
+export const create_resolved_content: () => number;
+export const init: () => void;
+export const jsresolvedcontent_addEmbed: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const render_faceted_text: (a: number, b: number, c: number, d: number) => void;
+export const render_markdown: (a: number, b: number, c: number, d: number) => void;
+export const render_math: (a: number, b: number, c: number) => number;
+export const render_record: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
+export const jsresolvedcontent_new: () => number;
+export const __wbindgen_export: (a: number, b: number) => number;
+export const __wbindgen_export2: (a: number, b: number, c: number, d: number) => number;
+export const __wbindgen_export3: (a: number) => void;
+export const __wbindgen_export4: (a: number, b: number, c: number) => void;
+export const __wbindgen_add_to_stack_pointer: (a: number) => number;
+export const __wbindgen_start: () => void;