Skip to content

Conversation

@brianmhunt
Copy link
Member

@brianmhunt brianmhunt commented Dec 23, 2025

Consolidate the docs into a new tko.io site

Summary by CodeRabbit

  • New Features

    • Interactive documentation with live JSX editors and real-time previews.
    • Automated documentation deployment to GitHub Pages.
  • Documentation

    • Major site redesign: new layout, navigation, templated pages, and updated cross‑references.
    • Added migration guide and site README.
  • Chores

    • Migrated docs build to Eleventy and modernized build tooling; removed legacy build scripts and templates.
    • Added styling, templates, example runner, and custom domain support.

✏️ Tip: You can customize this high-level summary in your review settings.

brianmhunt and others added 8 commits December 23, 2025 09:20
- Remove duplicate docs from individual packages
- tko.io/src/docs/ is now single source of truth
- Update CONTRIBUTING.md with documentation guidelines

Deleted docs directories from:
- packages/binding.core/docs
- packages/binding.if/docs
- packages/binding.template/docs
- packages/observable/docs
- packages/computed/docs
- packages/utils.component/docs
- packages/bind/docs
- packages/lifecycle/docs
- packages/provider/docs
- packages/provider.databind/docs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 23, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Migrates the TKO documentation site from a custom Node.js build to Eleventy, adds interactive JSX live-edit examples (esbuild-wasm + CodeMirror + iframe), converts many docs to YAML front matter with updated links, removes legacy build/UI artifacts, and adds a GitHub Actions workflow to build and deploy the site to GitHub Pages.

Changes

Cohort / File(s) Summary
CI/CD & Deployment
\.github/workflows/deploy-docs.yml
New GitHub Actions workflow to build docs, upload Pages artifact, and deploy via actions/deploy-pages@v4.
Eleventy config & packaging
tko.io/.eleventy.js, tko.io/package.json, tko.io/README.md, tko.io/.gitignore
Add Eleventy configuration, switch package.json to ESM with devDependencies and scripts, add site README, and update ignore rules for Eleventy outputs.
Interactive examples & client runtime
tko.io/src/js/examples.js, tko.io/src/_layouts/base.njk, tko.io/src/css/tko.css
New client-side examples engine (esbuild-wasm + CodeMirror + iframe live preview), plus a base layout and stylesheet to host interactive demos.
Docs content migration
tko.io/src/docs/**, tko.io/src/index.md, tko.io/src/3to4.md
40+ documentation pages: add YAML front matter, normalize links from .html to directory-style relative paths, add raw blocks where needed.
Legacy build & config removed
tko.io/make.js, tko.io/settings.yaml, tko.io/app.yaml, tko.io/src/index.pug, tko.io/src/tko-io.js, tko.io/src/tko.css
Remove old Node.js build script, site settings, App Engine config, Pug template, legacy Knockout UI script, and previous CSS.
Site metadata & pages
tko.io/src/CNAME, CONTRIBUTING.md
Add CNAME for GitHub Pages custom domain and documentation for contributing to the new site.
Library surface change
builds/reference/src/index.ts
Export jsx.render(jsx) that mounts a JsxObserver to a DocumentFragment and returns { node, dispose() }.
Small repo updates
.gitignore
Add .playwright-mcp to ignore list.
Docs cleanup
builds/reference/docs/intro.md
Remove Sponsors/Patreon block from intro.

Sequence Diagram(s)

sequenceDiagram
    participant Browser as User (Browser)
    participant Page as Docs Page (Eleventy)
    participant Examples as examples.js
    participant Esbuild as esbuild-wasm
    participant Iframe as Sandbox Iframe

    rect rgba(200,220,255,0.18)
    Note over Page,Examples: Page loads examples assets and scripts
    Page->>Examples: init (scan code blocks)
    end

    rect rgba(220,255,220,0.18)
    Note over Browser,Examples: Interactive edit
    Browser->>Examples: edit CodeMirror (debounced)
    Examples->>Esbuild: transformJSX(code)
    end

    rect rgba(255,240,200,0.18)
    Note over Esbuild,Iframe: Build & render
    Esbuild->>Esbuild: compile/transform code
    alt success
        Esbuild->>Iframe: inject HTML + transformed JS + TKO
        Iframe->>Iframe: execute in sandbox
        Iframe->>Browser: render live preview
    else error
        Esbuild->>Examples: return error
        Examples->>Browser: show error overlay
    end
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Prefer const #223 — Adds a new render() that instantiates JsxObserver; touches the same rendering API used by builds/reference/src/index.ts.
  • Configure TypeScript to be stricter #222 — Makes changes to JsxObserver implementation in packages/utils.jsx, likely related to the new jsx.render usage.

Poem

🐇 I hopped through files both old and new,
Built a cozy nook where JSX grew.
CodeMirror hums, the iframe sings,
Docs now sparkle with interactive things.
— a rabbit, nibbling deploy yarns and glue

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'New tko io site' is vague and generic, using non-descriptive language that doesn't convey meaningful information about the comprehensive changes in the changeset. Consider a more specific title that captures the main change, such as 'Consolidate documentation into new tko.io site with Eleventy-based static generation' or 'Migrate tko.io to Eleventy documentation site with interactive JSX examples'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch new-tko-io-site

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR consolidates the TKO documentation into a new tko.io site built with Eleventy (11ty), replacing the previous custom build system with a modern static site generator and adding interactive JSX examples.

Key changes:

  • Complete rebuild of the documentation site using Eleventy static site generator
  • Migration from Google App Engine deployment to GitHub Pages
  • Addition of interactive code examples with live preview using CodeMirror and esbuild-wasm
  • Modernized CSS styling with improved typography and responsive design

Reviewed changes

Copilot reviewed 73 out of 76 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tko.io/.eleventy.js New Eleventy configuration defining site structure, collections, and filters
tko.io/src/_layouts/base.njk New base template layout for all documentation pages
tko.io/src/css/tko.css Complete CSS rewrite with modern styling and interactive example support
tko.io/src/js/examples.js New interactive example system using CodeMirror editor and esbuild JSX transformation
tko.io/src/index.md New homepage converted to Markdown format
tko.io/src/3to4.md Migration guide converted to Markdown format
tko.io/src/docs/**/*.md All documentation files updated with frontmatter for Eleventy
tko.io/package.json Updated dependencies and build scripts for Eleventy workflow
.github/workflows/deploy-docs.yml New GitHub Actions workflow for automated deployment
builds/reference/src/index.ts Added public JSX render function to TKO API
tko.io/make.js Removed legacy custom build system
tko.io/app.yaml Removed Google App Engine configuration

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

createElement,
Fragment,
/** Public render function that converts JSX to DOM nodes */
render(jsx: any) {
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The render function parameter uses 'any' type, which bypasses TypeScript's type checking. Consider defining a proper JSX type or using a more specific type to improve type safety and API clarity.

Suggested change
render(jsx: any) {
render(jsx: ReturnType<typeof createElement>) {

Copilot uses AI. Check for mistakes.
2. Whenever it has *any* `change` subscribers, it is awake and ***listening***. When entering the *listening* state, it immediately subscribes to any dependencies. In this state, it operates just like a regular computed observable, as described in [how dependency tracking works](computed-dependency-tracking.md).

#### Why "pure"? {#pure-computed-function-defined}
#### Why "pure"? {% raw %}{#pure-computed-function-defined}{% endraw %}
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The anchor link syntax using {% raw %} tags suggests a migration from another templating system. Eleventy/markdown-it uses different anchor link syntax. Verify these anchor links work correctly or update to use standard markdown anchor syntax.

Copilot uses AI. Check for mistakes.
| `AttributeProvider` | `<span ko-title='x'></span>`
| `TextMustacheProvider` | `{{ x_text }}` <br> `{{{ x_html }}}` <br> `{{# text: thing /}}`
| `AttributeMustacheProvider` | `<span title='The {{ x }} title'></span>`
| `TextMustacheProvider` | {% raw %}`{{ x_text }}`{% endraw %} <br> {% raw %}`{{{ x_html }}}`{% endraw %} <br> {% raw %}`{{# text: thing /}}`{% endraw %}
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple uses of {% raw %} tags within table cells make the markdown harder to read and maintain. Consider if these raw tags are necessary in the Eleventy build, or if there's a cleaner way to escape these template literals.

Suggested change
| `TextMustacheProvider` | {% raw %}`{{ x_text }}`{% endraw %} <br> {% raw %}`{{{ x_html }}}`{% endraw %} <br> {% raw %}`{{# text: thing /}}`{% endraw %}
| `TextMustacheProvider` | {% raw %}`{{ x_text }}` <br> `{{{ x_html }}}` <br> `{{# text: thing /}}`{% endraw %}

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (7)
tko.io/src/docs/bindings/event-binding.md (1)

76-82: Fix list indentation to align with Markdown standards.

The bullet points have 1 space of indentation instead of 0, which violates the MD007 (ul-indent) rule. Remove the leading space from each list item.

🔎 Proposed fix for list indentation
-Two points to note about this example:
-
- * If you're inside a nested [binding context](../../binding-context/binding-context/), for example if you're inside a `foreach` or a `with` block, but your handler function
+Two points to note about this example:
+
+* If you're inside a nested [binding context](../../binding-context/binding-context/), for example if you're inside a `foreach` or a `with` block, but your handler function
   is on the root viewmodel or some other parent context, you'll need to use a prefix such as `$parent` or `$root` to locate the
   handler function.
- * In your viewmodel, it's often useful to declare `self` (or some other variable) as an alias for `this`. Doing so avoids any problems
+* In your viewmodel, it's often useful to declare `self` (or some other variable) as an alias for `this`. Doing so avoids any problems
   with `this` being redefined to mean something else in event handlers or Ajax request callbacks.
tko.io/src/docs/bindings/uniqueName-binding.md (1)

14-14: Remove or fix the broken example link.

The example link ../examples/gridEditor.html on line 14 is broken—neither the gridEditor.html file nor the examples directory exist in the documentation structure. Either remove this link or update it to point to a valid example if one exists elsewhere in the codebase.

tko.io/src/docs/bindings/enable-binding.md (1)

14-14: The <live-example> custom element is not defined anywhere in the build system.

The tag is used in the markdown files but lacks any corresponding shortcode definition in .eleventy.js, Nunjucks filter, or client-side handler. This will render as a non-functional HTML element. Either define the component as an Eleventy shortcode or implement it as a client-side custom element.

tko.io/src/docs/bindings/options-binding.md (1)

144-148: Inconsistent link format: some links still use .html suffix.

Line 144 was updated to use the new directory-based path (../selectedOptions-binding/), but line 148 still uses the old .html format (value-binding.html#...). Additionally, line 132 uses observableArrays.html#.... These should be updated for consistency with the new link structure.

🔎 Proposed fix
-     For a multi-select list, you can read and write the selection state using `selectedOptions`. Technically this is a separate binding, so it has [its own documentation](../selectedOptions-binding/).
+     For a multi-select list, you can read and write the selection state using `selectedOptions`. Technically this is a separate binding, so it has [its own documentation](../selectedOptions-binding/).

   * `valueAllowUnset`

-     If you want Knockout to allow your model property to take values that have no corresponding entry in your `<select>` element (and display this by making the `<select>` element blank), then see [documentation for `valueAllowUnset`](value-binding.html#using-valueallowunset-with-select-elements).
+     If you want Knockout to allow your model property to take values that have no corresponding entry in your `<select>` element (and display this by making the `<select>` element blank), then see [documentation for `valueAllowUnset`](../value-binding/#using-valueallowunset-with-select-elements).

Also update line 132:

-     Sometimes you may want to mark an array entry as deleted, but without actually losing record of its existence. This is known as a non-destructive delete. For details of how to do this, see [the destroy function on `observableArray`](observableArrays.html#destroy_and_destroyall_note_usually_relevant_to_ruby_on_rails_developers_only).
+     Sometimes you may want to mark an array entry as deleted, but without actually losing record of its existence. This is known as a non-destructive delete. For details of how to do this, see [the destroy function on `observableArray`](../../observables/observableArrays/#destroy_and_destroyall_note_usually_relevant_to_ruby_on_rails_developers_only).
tko.io/src/docs/bindings/foreach-binding.md (1)

131-131: Inconsistent link format.

This link still uses the old .html format while other links in this file were updated to the new directory-based structure.

🔎 Proposed fix
-Sometimes you may want to mark an array entry as deleted, but without actually losing record of its existence. This is known as a *non-destructive delete*. For details of how to do this, see [the destroy function on `observableArray`](observableArrays.html#destroy_and_destroyall_note_usually_relevant_to_ruby_on_rails_developers_only).
+Sometimes you may want to mark an array entry as deleted, but without actually losing record of its existence. This is known as a *non-destructive delete*. For details of how to do this, see [the destroy function on `observableArray`](../../observables/observableArrays/#destroy_and_destroyall_note_usually_relevant_to_ruby_on_rails_developers_only).
tko.io/src/docs/bindings/submit-binding.md (1)

56-56: Update internal link to use consistent relative path format.

Line 56 contains a broken link in the old format /a/click-binding.html. Update to ../click-binding/ to match the relative path convention used throughout the documentation (e.g., event-binding.md already uses ../click-binding/ for the same reference).

-For information about how to pass additional parameters to your submit handler function, or how to control the `this` handle when invoking functions that aren't on your view model, see the notes relating to the [click binding](/a/click-binding.html). All the notes on that page apply to `submit` handlers too.
+For information about how to pass additional parameters to your submit handler function, or how to control the `this` handle when invoking functions that aren't on your view model, see the notes relating to the [click binding](../click-binding/). All the notes on that page apply to `submit` handlers too.
tko.io/src/docs/computed/computed-reference.md (1)

42-42: Outdated link format not migrated.

Line 42 still references computed-dependency-tracking.html#controlling-dependencies-using-peek, which uses the old .html link format. This should be updated to the new relative path format (e.g., ../computed-dependency-tracking/#controlling-dependencies-using-peek or similar, depending on the anchor ID structure).

🔎 Proposed fix
-* `peek()` --- Returns the current value of the computed observable without creating a dependency (see the section on [`peek`](computed-dependency-tracking.html#controlling-dependencies-using-peek)).
+* `peek()` --- Returns the current value of the computed observable without creating a dependency (see the section on [`peek`](../computed-dependency-tracking/#controlling-dependencies-using-peek)).

Note: Verify that the anchor ID #controlling-dependencies-using-peek is correct in the target file. If Eleventy uses different anchor ID generation (e.g., kebab-case or auto-generated), adjust accordingly.

🧹 Nitpick comments (11)
tko.io/src/docs/bindings/disable-binding.md (1)

11-11: Consider simplifying the wording for clarity.

The phrase "exactly the same way" is slightly redundant. Consider shortening to "the same way" or "identically" for conciseness.

-This is the mirror image of the `enable` binding. For more information, see [documentation for the `enable` binding](../enable-binding/), because `disable` works in exactly the same way except that it negates whatever parameter you pass to it.
+This is the mirror image of the `enable` binding. For more information, see [documentation for the `enable` binding](../enable-binding/), because `disable` works the same way except that it negates whatever parameter you pass to it.
builds/reference/src/index.ts (1)

66-76: Consider handling the empty render case.

When jsx renders nothing, fragment.childNodes.length will be 0, and fragment.firstChild returns null. The returned node would be null (since the ternary condition is false, it returns the empty fragment, which is fine). However, callers may not expect an empty fragment.

Also, the return type annotation could be more explicit for better TypeScript support.

🔎 Optional improvement for type clarity
-    /** Public render function that converts JSX to DOM nodes */
-    render(jsx: any) {
+    /** Public render function that converts JSX to DOM nodes */
+    render(jsx: any): { node: Node | DocumentFragment; dispose: () => void } {
       const fragment = document.createDocumentFragment()
       const observer = new JsxObserver(jsx, fragment)
       // Return the first child if single node, or the fragment if multiple
-      const node = fragment.childNodes.length === 1 ? fragment.firstChild : fragment
+      const node: Node | DocumentFragment = fragment.childNodes.length === 1 
+        ? fragment.firstChild! 
+        : fragment
       return {
         node,
         dispose: () => observer.dispose()
       }
     },
tko.io/src/js/examples.js (2)

8-15: Initialization error leaves state inconsistent.

If esbuild.initialize() throws, esbuildInitialized remains false, but subsequent calls will retry and potentially fail again with "already initialized" errors from esbuild. Consider catching initialization failures explicitly.

🔎 Proposed fix
 let esbuildInitialized = false;
+let esbuildInitPromise = null;

 async function initEsbuild() {
-  if (!esbuildInitialized) {
-    await esbuild.initialize({
-      wasmURL: 'https://cdn.jsdelivr.net/npm/[email protected]/esbuild.wasm'
-    });
-    esbuildInitialized = true;
+  if (!esbuildInitPromise) {
+    esbuildInitPromise = esbuild.initialize({
+      wasmURL: 'https://cdn.jsdelivr.net/npm/[email protected]/esbuild.wasm'
+    }).then(() => {
+      esbuildInitialized = true;
+    });
   }
+  return esbuildInitPromise;
 }

33-77: EditorView instances are never disposed.

When the page navigates away or if examples are dynamically removed, the EditorView instances and their event listeners are not cleaned up. This could cause memory leaks in single-page application scenarios. Consider storing references for cleanup if needed.

tko.io/src/CNAME (1)

1-1: CNAME configuration is correct.

The file properly configures the custom domain tko.io for GitHub Pages hosting. Ensure that DNS records are configured to point to GitHub's IP addresses and that the repository settings have this custom domain enabled.

tko.io/src/docs/bindings/value-binding.md (1)

65-65: Optional: Consider simplifying wordy phrasing.

The phrase "works in conjunction with" at line 65 is slightly verbose. Consider alternatives like "works with" to improve readability. This is a minor stylistic suggestion and not a blocker.

tko.io/src/docs/computed/computed-pure.md (1)

20-20: Consider adjusting heading hierarchy.

The static analysis tool flagged that this h4 heading follows an h1, skipping h2 and h3 levels. While this works functionally, it may impact document navigation and accessibility.

Consider adjusting the heading level to h2 or adding intermediate headings to maintain a proper hierarchy.

tko.io/src/_layouts/base.njk (2)

10-14: Consider adding accessibility attributes to navigation.

The top navigation bar would benefit from ARIA attributes for better accessibility.

🔎 Proposed accessibility improvements
-  <nav class="top-bar">
+  <nav class="top-bar" role="navigation" aria-label="Main navigation">
     <div class="tko">TKO</div>
     <a href="{{ '/' | url }}">Introduction</a>
     <a class="external" href="https://github.com/knockout/tko">Github</a>
   </nav>

16-51: Consider adding ARIA label to sidebar navigation.

The sidebar navigation would benefit from an ARIA label to improve screen reader experience.

🔎 Proposed accessibility improvement
-  <nav class="sidebar">
+  <nav class="sidebar" aria-label="Documentation navigation">
     <div class="toc">
tko.io/src/docs/components/component-custom-elements.md (1)

84-84: Consider fixing list indentation.

Static analysis flagged inconsistent list indentation at these lines. While this doesn't affect functionality, consistent indentation improves readability.

The expected indentation is 2 spaces for line 84 and 0 spaces for line 116, but actual indentation differs.

Also applies to: 116-116

tko.io/src/css/tko.css (1)

1-1: Consider self-hosting fonts for better privacy and performance.

Importing fonts from Google Fonts creates an external dependency and potential privacy concerns (Google can track page visits).

Consider self-hosting the Inter and JetBrains Mono fonts to improve privacy and reduce external dependencies. This also provides better control over caching and load performance.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6412c34 and e75196f.

⛔ Files ignored due to path filters (2)
  • tko.io/bun.lock is excluded by !**/*.lock
  • tko.io/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (74)
  • .github/workflows/deploy-docs.yml
  • .gitignore
  • CONTRIBUTING.md
  • builds/reference/docs/intro.md
  • builds/reference/src/index.ts
  • packages/binding.if/docs/_config.yml
  • tko.io/.eleventy.js
  • tko.io/.gitignore
  • tko.io/README.md
  • tko.io/app.yaml
  • tko.io/make.js
  • tko.io/package.json
  • tko.io/settings.yaml
  • tko.io/src/3to4.md
  • tko.io/src/CNAME
  • tko.io/src/_layouts/base.njk
  • tko.io/src/css/tko.css
  • tko.io/src/docs/advanced/databind-parser.md
  • tko.io/src/docs/advanced/life-cycle.md
  • tko.io/src/docs/advanced/provider.md
  • tko.io/src/docs/binding-context/binding-context.md
  • tko.io/src/docs/binding-context/binding-preprocessing.md
  • tko.io/src/docs/binding-context/binding-syntax.md
  • tko.io/src/docs/binding-context/custom-bindings-controlling-descendant-bindings.md
  • tko.io/src/docs/binding-context/custom-bindings-disposal.md
  • tko.io/src/docs/binding-context/custom-bindings-for-virtual-elements.md
  • tko.io/src/docs/binding-context/custom-bindings.md
  • tko.io/src/docs/binding-context/unobtrusive-event-handling.md
  • tko.io/src/docs/bindings/attr-binding.md
  • tko.io/src/docs/bindings/checked-binding.md
  • tko.io/src/docs/bindings/click-binding.md
  • tko.io/src/docs/bindings/css-binding.md
  • tko.io/src/docs/bindings/disable-binding.md
  • tko.io/src/docs/bindings/enable-binding.md
  • tko.io/src/docs/bindings/event-binding.md
  • tko.io/src/docs/bindings/foreach-binding.md
  • tko.io/src/docs/bindings/hasfocus-binding.md
  • tko.io/src/docs/bindings/html-binding.md
  • tko.io/src/docs/bindings/if-binding.md
  • tko.io/src/docs/bindings/ifnot-binding.md
  • tko.io/src/docs/bindings/index.md
  • tko.io/src/docs/bindings/options-binding.md
  • tko.io/src/docs/bindings/selectedOptions-binding.md
  • tko.io/src/docs/bindings/style-binding.md
  • tko.io/src/docs/bindings/submit-binding.md
  • tko.io/src/docs/bindings/template-binding.md
  • tko.io/src/docs/bindings/text-binding.md
  • tko.io/src/docs/bindings/textInput-binding.md
  • tko.io/src/docs/bindings/uniqueName-binding.md
  • tko.io/src/docs/bindings/value-binding.md
  • tko.io/src/docs/bindings/visible-binding.md
  • tko.io/src/docs/bindings/with-binding.md
  • tko.io/src/docs/components/component-binding.md
  • tko.io/src/docs/components/component-custom-elements.md
  • tko.io/src/docs/components/component-loaders.md
  • tko.io/src/docs/components/component-overview.md
  • tko.io/src/docs/components/component-registration.md
  • tko.io/src/docs/computed/computed-dependency-tracking.md
  • tko.io/src/docs/computed/computed-pure.md
  • tko.io/src/docs/computed/computed-reference.md
  • tko.io/src/docs/computed/computed-writable.md
  • tko.io/src/docs/computed/computedObservables.md
  • tko.io/src/docs/computed/proxy.md
  • tko.io/src/docs/observables/arraychange.md
  • tko.io/src/docs/observables/extenders.md
  • tko.io/src/docs/observables/observableArrays.md
  • tko.io/src/docs/observables/observables.md
  • tko.io/src/docs/observables/rateLimit-observable.md
  • tko.io/src/docs/observables/throttle-extender.md
  • tko.io/src/index.md
  • tko.io/src/index.pug
  • tko.io/src/js/examples.js
  • tko.io/src/tko-io.js
  • tko.io/src/tko.css
💤 Files with no reviewable changes (8)
  • builds/reference/docs/intro.md
  • tko.io/make.js
  • tko.io/settings.yaml
  • tko.io/app.yaml
  • tko.io/src/index.pug
  • tko.io/src/tko.css
  • packages/binding.if/docs/_config.yml
  • tko.io/src/tko-io.js
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-21T09:16:36.575Z
Learnt from: phillipc
Repo: knockout/tko PR: 221
File: packages/bind/spec/bindingAttributeBehaviors.ts:135-138
Timestamp: 2025-12-21T09:16:36.575Z
Learning: In the TKO framework, data-bind expressions support "naked" arrow function syntax where zero-parameter arrow functions can be written without parentheses, e.g., `data-bind='click: => was_clicked(true)'` or `lambdaLiteral: => null`. This is valid TKO syntax even though it's not standard JavaScript.

Applied to files:

  • tko.io/src/docs/binding-context/unobtrusive-event-handling.md
  • tko.io/src/3to4.md
  • tko.io/src/docs/bindings/index.md
  • tko.io/src/docs/bindings/template-binding.md
  • tko.io/src/docs/binding-context/binding-syntax.md
  • tko.io/src/docs/bindings/event-binding.md
  • tko.io/src/docs/advanced/databind-parser.md
  • tko.io/src/docs/bindings/click-binding.md
🧬 Code graph analysis (2)
builds/reference/src/index.ts (1)
packages/utils.jsx/src/JsxObserver.ts (1)
  • JsxObserver (55-465)
tko.io/.eleventy.js (1)
packages/computed/spec/proxyBehavior.ts (1)
  • a (88-90)
🪛 Biome (2.1.2)
tko.io/src/css/tko.css

[error] 280-280: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

font-size is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🪛 LanguageTool
tko.io/src/docs/bindings/value-binding.md

[style] ~65-~65: ‘in conjunction with’ might be wordy. Consider a shorter alternative.
Context: ...>elements). Thevaluebinding works in conjunction with theoptions` binding to let you read a...

(EN_WORDINESS_PREMIUM_IN_CONJUNCTION_WITH)

tko.io/src/3to4.md

[locale-violation] ~12-~12: In American English, “take a look” is more commonly used.
Context: ...ockout itself. To see the differences, have a look at the [CHANGELOG.md](https://github.co...

(HAVE_A_LOOK)

tko.io/src/docs/bindings/template-binding.md

[style] ~151-~151: Omitting these overused filler words can make your writing sound more assertive.
Context: ...g-context/custom-bindings/), but if you really just want to access the raw DOM elements emitted ...

(REALLY_JUST)

tko.io/src/docs/bindings/text-binding.md

[grammar] ~34-~34: Ensure spelling is correct
Context: ...to detemine text values If you want to detemine text programmatically, one option is to...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

tko.io/src/docs/bindings/disable-binding.md

[style] ~11-~11: ‘exactly the same’ might be wordy. Consider a shorter alternative.
Context: ...e-binding/), because disable works in exactly the same way except that it negates whatever par...

(EN_WORDINESS_PREMIUM_EXACTLY_THE_SAME)

🪛 markdownlint-cli2 (0.18.1)
tko.io/src/docs/computed/computed-pure.md

20-20: Heading levels should only increment by one level at a time
Expected: h2; Actual: h4

(MD001, heading-increment)

tko.io/src/docs/bindings/options-binding.md

9-9: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

tko.io/src/3to4.md

17-17: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


25-25: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


31-31: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


41-41: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


47-47: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


67-67: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


87-87: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


108-108: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


130-130: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


151-151: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


168-168: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


192-192: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


211-211: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


223-223: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


235-235: Heading style
Expected: atx; Actual: setext

(MD003, heading-style)


242-242: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

CONTRIBUTING.md

56-56: Bare URL used

(MD034, no-bare-urls)

tko.io/src/docs/bindings/event-binding.md

78-78: Unordered list indentation
Expected: 0; Actual: 1

(MD007, ul-indent)

tko.io/src/docs/bindings/style-binding.md

8-8: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

tko.io/src/docs/computed/computed-reference.md

24-24: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


25-25: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


26-26: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


27-27: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

tko.io/src/docs/components/component-custom-elements.md

84-84: Unordered list indentation
Expected: 2; Actual: 6

(MD007, ul-indent)


116-116: Unordered list indentation
Expected: 0; Actual: 1

(MD007, ul-indent)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: testheadless (22.x, on)
  • GitHub Check: testheadless (22.x, off)
🔇 Additional comments (99)
tko.io/src/docs/bindings/event-binding.md (2)

1-4: YAML front matter correctly formatted for Eleventy.

The layout and title metadata is properly structured for 11ty's nunjucks template system.


129-129: Content clarification added effectively.

The new sentence at line 129 provides clear guidance on allowing default actions by returning true, which improves the documentation's completeness.

tko.io/src/docs/binding-context/unobtrusive-event-handling.md (1)

1-4: Fix the relative link path and correct spelling errors.

The relative path to the binding context documentation is incorrect. From tko.io/src/docs/binding-context/unobtrusive-event-handling.md, the path ../../binding-context/binding-context/ resolves outside the docs directory and will break the link. Update line 19 to binding-context.md (or ./binding-context.md) since binding-context.md exists in the same directory.

Additionally, correct the spelling of "techinique" to "technique" on lines 8 and 29.

Note: The YAML title "Unobtrusive Event Handling Binding" differs from the document heading "Unobtrusive Event Handlers"—verify this discrepancy is intentional.

⛔ Skipped due to learnings
Learnt from: phillipc
Repo: knockout/tko PR: 221
File: packages/bind/spec/bindingAttributeBehaviors.ts:135-138
Timestamp: 2025-12-21T09:16:36.575Z
Learning: In the TKO framework, data-bind expressions support "naked" arrow function syntax where zero-parameter arrow functions can be written without parentheses, e.g., `data-bind='click: => was_clicked(true)'` or `lambdaLiteral: => null`. This is valid TKO syntax even though it's not standard JavaScript.
.gitignore (1)

32-32: LGTM.

The .playwright-mcp ignore rule is appropriately placed and follows the existing conventions in the file.

tko.io/src/docs/advanced/databind-parser.md (1)

1-4: LGTM.

The YAML front matter is consistent with the new Eleventy-based documentation structure. The layout and title fields align with the base layout configuration introduced in this PR.

tko.io/src/docs/observables/observableArrays.md (1)

1-4: LGTM.

Front matter addition follows the established pattern for documentation pages in this PR and integrates the observable docs into the Eleventy rendering pipeline.

tko.io/src/docs/computed/proxy.md (1)

1-4: LGTM.

Consistent front matter addition for the computed docs collection. The title: Proxy matches the main heading in the documentation.

tko.io/src/docs/bindings/disable-binding.md (1)

1-4: LGTM.

Front matter is consistent. The link update from anchor (#enable-binding) to relative path (../enable-binding/) aligns with the new Eleventy directory-based structure for documentation.

tko.io/src/docs/binding-context/binding-syntax.md (1)

1-4: LGTM.

Front matter is correctly formatted and consistent with the documentation structure migration to Eleventy.

tko.io/src/docs/bindings/uniqueName-binding.md (1)

1-4: LGTM.

Front matter addition is consistent with other documentation pages in the Eleventy migration.

tko.io/src/docs/bindings/options-binding.md (2)

1-4: LGTM!

Front matter correctly specifies the layout and title for the new Eleventy-based documentation site.


13-13: LGTM!

Links correctly updated to use the new directory-based relative paths consistent with the documentation restructure.

CONTRIBUTING.md (1)

29-60: Good addition of documentation guidelines.

The new Documentation section provides clear guidance for contributors. One minor improvement per static analysis: consider formatting the localhost URL as a proper link.

🔎 Optional fix for bare URL
-   Then visit http://localhost:8080
+   Then visit [http://localhost:8080](http://localhost:8080)
tko.io/src/docs/bindings/with-binding.md (3)

1-12: LGTM!

Front matter and internal links correctly updated to use the new directory-based relative paths. The binding context and related binding references are consistent throughout.


41-41: LGTM!

Link to binding context properties correctly uses the new path format.


100-100: LGTM!

References to if and foreach bindings consistently updated to use the new relative path structure.

tko.io/src/docs/bindings/foreach-binding.md (4)

1-4: LGTM!

Front matter correctly configured for the Eleventy build.


12-12: LGTM!

Link to observableArrays documentation correctly updated to use the new relative path structure.


51-83: LGTM!

Binding context references consistently updated throughout this section.


145-145: LGTM!

Link to custom-bindings correctly updated to use the new path format.

tko.io/src/docs/bindings/template-binding.md (4)

1-4: LGTM!

Front matter correctly configured for the Eleventy documentation site.


101-101: LGTM!

Binding context link correctly updated to new relative path structure.


151-170: LGTM!

Links to custom-bindings and foreach-binding documentation correctly use the new directory-based paths.


201-261: LGTM!

All binding context references in this section consistently updated to use the new path format.

builds/reference/src/index.ts (1)

25-25: LGTM!

Import correctly added alongside existing jsx-related imports.

tko.io/src/js/examples.js (3)

1-4: External CDN dependencies.

The code relies on external CDN resources. While versions are pinned, consider adding a fallback or documenting these dependencies for maintainability. If CDN availability is a concern for offline development, you might want to bundle these or use a more resilient loading strategy.


79-133: LGTM!

The runExample function properly handles both success and error cases, manages error display state, and uses srcdoc for secure iframe content. The error overlay management is clean.


135-145: LGTM!

The initialization logic correctly handles both loading and already-loaded document states.

tko.io/src/3to4.md (2)

1-4: LGTM!

Front matter correctly configured for the migration guide.


6-12: LGTM!

Good overview introduction for the migration guide.

tko.io/src/docs/bindings/checked-binding.md (2)

1-4: YAML front matter correctly applied.

The YAML front matter with layout and title is properly formatted and aligns with the new Eleventy-based documentation structure.


14-14: Internal link correctly migrated to relative path.

The link to value-binding has been properly updated from the old .html format to the new relative path structure (../value-binding/).

tko.io/src/docs/bindings/ifnot-binding.md (1)

1-4: YAML front matter correctly applied.

The front matter is properly formatted and consistent with other documentation pages in the migration.

tko.io/src/docs/bindings/submit-binding.md (1)

1-4: YAML front matter correctly applied.

The front matter is properly formatted and consistent with other documentation pages.

tko.io/src/docs/bindings/visible-binding.md (2)

1-4: YAML front matter correctly applied.

The front matter is properly formatted and consistent with other documentation pages in the migration.


14-26: Verify Eleventy configuration supports custom example code blocks.

The file uses custom example code blocks (fenced code with "example" language identifier). Ensure that tko.io/.eleventy.js or related markdown rendering configuration properly handles these custom block types to produce the intended output.

Please verify that the Eleventy markdown configuration (likely in .eleventy.js or a markdown plugin) recognizes and renders the example code fence language identifier correctly. If not, this could result in raw example blocks appearing in the rendered documentation.

Also applies to: 50-60

tko.io/src/docs/bindings/attr-binding.md (2)

1-4: YAML front matter correctly applied.

The front matter is properly formatted and consistent with the documentation migration.


13-13: Verify custom <live-example> component is supported by Eleventy.

Line 13 uses a custom <live-example> component tag that must be registered in the Eleventy build system (likely via a macro in tko.io/_layouts/base.njk, a plugin, or a shortcode). Without proper support, this tag will render literally in the HTML, potentially breaking the documentation page layout and interactivity.

Please confirm that:

  1. The <live-example> component/macro is defined in the Eleventy configuration (shortcodes, filters, or macros)
  2. The params='id: "attr"' attribute format is correctly parsed by the component
  3. The component is available and properly exposed to Markdown-rendered content
tko.io/src/docs/bindings/textInput-binding.md (2)

1-4: YAML front matter correctly applied.

The front matter is properly formatted and consistent with the documentation migration.


15-15: Verify custom <live-example> component is supported by Eleventy.

Line 15 uses a custom <live-example> component tag (similar to attr-binding.md). Ensure that this component is properly registered in the Eleventy build system (shortcodes, macros, or plugins) and that the id parameter is correctly parsed and used to render interactive examples.

This verification is critical to ensure the textInput binding documentation displays its interactive example correctly without rendering the raw tag to users.

tko.io/src/docs/binding-context/custom-bindings.md (2)

1-4: YAML front matter correctly applied.

The front matter is properly formatted and consistent with the documentation migration.


11-11: The link references a non-existent directory; path correction also needed.

Line 11 contains a broken link to ../examples/grid.html. An examples directory does not exist in the repository. While the format should follow the Eleventy pattern (removing .html and adding a trailing slash) as seen in other docs like checked-binding.md, the proposed relative path ../../examples/grid/ is also incorrect. From binding-context/custom-bindings.md, the path ../../ navigates to src/, not to the docs directory where examples would be located. Either remove the link if the example no longer exists, or provide the correct target path if an example resource exists elsewhere.

tko.io/src/docs/components/component-registration.md (2)

1-4: LGTM: Front matter added correctly.

The YAML front matter is properly formatted and aligns with the Eleventy-based site structure.


95-95: Link update looks good, but verify cross-reference consistency.

Line 95 correctly updates the custom-bindings link to a relative path. However, other internal links in this file remain as .html references (e.g., lines 11, 27, 97, 158, 270 referencing component-loaders.html and component-custom-elements.html). This inconsistency suggests either:

  1. Not all links were migrated, which could break the documentation after deployment.
  2. Some links intentionally remain unconverted (though this would be unusual in a full migration).

Additionally, verify that line 315's link to ../if-binding/ resolves correctly—if binding docs are under a bindings/ subdirectory, the path may need to be ../bindings/if-binding/ instead.

tko.io/src/docs/computed/computed-writable.md (1)

1-4: LGTM: Front matter and link update are correct.

The YAML front matter is properly formatted, and the link update on line 25 correctly converts the .html reference to a relative path for an adjacent document in the same directory.

tko.io/src/docs/components/component-binding.md (1)

1-4: LGTM: Front matter is correct.

The YAML front matter follows the consistent pattern and is properly formatted.

tko.io/src/docs/binding-context/custom-bindings-controlling-descendant-bindings.md (2)

1-4: LGTM: Front matter is correct.

The YAML front matter is properly formatted and follows the established pattern.


44-44: Verify relative link path for binding-context reference.

Line 44 updates the binding-context link to ../../binding-context/binding-context/. This double reference (binding-context/binding-context/) is unusual and should be verified against the actual directory structure and Eleventy permalink configuration.

If the Eleventy config uses a permalink structure where each doc gets its own index page (e.g., /binding-context/binding-context/index.html), then the path is correct. However, if the intent is to link to a parent index or a different structure, the path may need adjustment (e.g., ../binding-context/ or similar).

tko.io/src/docs/bindings/hasfocus-binding.md (1)

1-4: LGTM: Front matter is correct.

The YAML front matter is properly formatted and consistent with other documentation pages.

tko.io/src/docs/observables/arraychange.md (1)

1-4: LGTM: Front matter is correct.

The YAML front matter is properly formatted and follows the consistent pattern across the documentation.

tko.io/src/docs/observables/throttle-extender.md (2)

1-4: LGTM: Front matter is correct.

The YAML front matter is properly formatted and consistent with other documentation pages.


8-8: Verify deprecation link in throttle extender note.

Line 8 contains a deprecation notice that links to #rateLimit-observable. Confirm this fragment link correctly points to the rateLimit extender documentation after the migration. If rateLimit docs are on a separate page, this link should be updated to a full relative path (e.g., ../rateLimit-observable/).

tko.io/.gitignore (1)

1-4: LGTM: .gitignore updates are appropriate.

The new ignore patterns are sensible for an Eleventy-based static site project:

  • node_modules/ prevents dependency commits
  • _site/ prevents generated output commits (standard practice)
  • package-lock.json prevents lock file churn
  • src/lib/ excludes generated or vendored source code

These patterns align with best practices for Node.js and static site projects.

tko.io/src/docs/bindings/if-binding.md (1)

1-12: Eleventy integration looks good.

The YAML front matter enables rendering through the new base layout, and the relative link path correctly references the sibling binding documentation.

tko.io/src/docs/bindings/click-binding.md (1)

1-4: YAML front matter addition is correct.

The layout and title metadata align with the new Eleventy documentation system.

tko.io/src/docs/advanced/provider.md (2)

1-4: YAML front matter properly added.

The layout specification enables integration with the new Eleventy-based documentation system.


16-17: Correct use of {% raw %} blocks for Mustache syntax.

Wrapping the Mustache template examples (e.g., {{ x_text }}, {{{ x_html }}}) prevents Eleventy's template processor from attempting to render them as Nunjucks/Liquid variables. This is the right approach for embedding templating-language examples in documentation.

tko.io/src/docs/bindings/style-binding.md (1)

1-4: YAML front matter correctly added.

The layout and title enable proper rendering through the Eleventy documentation system.

tko.io/src/docs/components/component-overview.md (1)

1-4: Front matter correctly added for Eleventy layout system.

The YAML metadata ensures the page is rendered using the shared base layout and properly integrated into the documentation navigation.

tko.io/src/docs/bindings/css-binding.md (2)

1-4: YAML front matter addition is correct.

The layout metadata enables integration with the new Eleventy documentation infrastructure.


11-11: Relative link path is correct.

The reference to ../style-binding/ correctly points to the sibling binding documentation.

tko.io/src/docs/bindings/value-binding.md (2)

1-4: YAML front matter is properly configured.

The layout and title enable rendering through the centralized Eleventy documentation system.


17-17: Relative link paths are correct.

All three binding references (../checked-binding/, ../options-binding/, ../selectedOptions-binding/) correctly point to sibling directories in the documentation structure.

Also applies to: 65-65

tko.io/src/docs/observables/extenders.md (1)

1-4: YAML front matter correctly added.

The front matter enables rendering within the Eleventy documentation framework, consistent with other documentation pages across the site.

tko.io/src/docs/binding-context/binding-context.md (1)

1-9: Front matter and link migration look correct.

The YAML front matter and relative link updates align with the new Eleventy documentation structure. Links to sibling binding pages (e.g., ../with-binding/, ../foreach-binding/) are correctly formatted for the directory-based URL scheme.

tko.io/src/docs/computed/computed-dependency-tracking.md (1)

1-39: Correct front matter and relative links.

The YAML front matter and link updates are properly structured. The relative path to rateLimit-observable correctly uses ../../observables/ to reference the adjacent observables collection, and the computed-pure link correctly uses ../ to reference the sibling computed docs directory.

tko.io/src/docs/components/component-loaders.md (1)

14-14: Anchor ID syntax may not work as intended.

Lines 14 and 50 use {% raw %}{#anchor-id}{% endraw %} to try to preserve custom anchor IDs while preventing Nunjucks processing. However, this syntax won't generate proper anchor elements in the output. The Nunjucks raw block will render the {#id} as literal text.

For Eleventy Markdown processing, verify that the Eleventy configuration uses a Markdown plugin (e.g., markdown-it-anchor) to automatically generate anchor IDs from headings, or adjust the syntax to match the configured plugin's requirements. Otherwise, internal references like those on lines 48 and 81 may break.

Can you confirm the Eleventy Markdown configuration and whether heading-to-anchor-ID generation is properly configured? Consider checking:

  • .eleventy.js Markdown plugin configuration
  • Whether markdown-it-anchor or similar is enabled
  • The expected output of these headings

Alternatively, if Eleventy is configured to support kramdown-style anchors, the syntax {#anchor-id} (without the {% raw %} wrapper) should work directly in the Markdown.

Also applies to: 50-50

tko.io/src/docs/computed/computedObservables.md (1)

1-294: Front matter and link migration complete and correct.

All relative links are properly structured for the documentation hierarchy. The use of ../../observables/ to reference the adjacent observables collection is consistent and correct throughout the file.

tko.io/src/docs/bindings/index.md (1)

10-11: Verify that bare relative links resolve correctly.

Lines 10–11 reference binding pages using bare names (e.g., if-binding, with-binding) without explicit relative paths. In an Eleventy documentation site with directory-based URLs, these should ideally be explicit relative paths like ./if-binding/ or be configured to resolve via Eleventy's URL handling.

Confirm that the Eleventy configuration or markdown processor is set up to resolve these bare links correctly, or update them to explicit relative paths.

Can you verify that these links resolve correctly in the built site? If not, consider updating them to explicit relative paths like ./if-binding/ or if-binding/.

tko.io/src/docs/bindings/html-binding.md (1)

1-50: Front matter and link migration look good.

The YAML front matter is correctly formatted, and the link to the text-binding page is properly updated to the relative path format compatible with the directory-based URL structure.

tko.io/src/docs/computed/computed-reference.md (1)

24-27: List indentation inconsistency flagged by static analysis.

The markdownlint tool flagged indentation issues on lines 24–27 (MD007 rule). These nested bullet items under the numbered list appear to have 2-space indentation. Verify that the indentation matches the expected style for this documentation (typically 0 or consistent spacing for items at the same nesting level).

Review the list indentation on lines 24–27 and ensure it matches the expected Markdown style. If needed, adjust indentation to align with project standards (often 0 spaces for top-level bullets in a numbered list context).

tko.io/src/docs/binding-context/binding-preprocessing.md (1)

1-4: YAML front matter added correctly.

The standard Eleventy front matter with layout and title has been properly added to support the new 11ty-based documentation site.

tko.io/src/docs/bindings/selectedOptions-binding.md (2)

1-4: YAML front matter added correctly.

The standard Eleventy front matter is properly formatted for the new doc site structure.


15-15: Internal link paths have been updated consistently.

Links to related binding and observable documentation have been updated to use relative directory paths aligned with the new site structure.

Also applies to: 41-41, 51-51

tko.io/src/index.md (1)

1-4: YAML front matter and homepage structure look good.

The new homepage introduces TKO well and provides clear getting-started guidance.

tko.io/src/docs/advanced/life-cycle.md (1)

1-6: Front matter and heading restructuring for Eleventy are correct.

The YAML front matter addition and heading reorganization align with the new site structure where page titles are managed in front matter rather than headings.

tko.io/src/docs/observables/observables.md (2)

1-4: YAML front matter properly added for Eleventy configuration.

The metadata is correctly formatted for the new 11ty-based site rendering system.


150-150: Internal links to related observable documentation updated.

Links to extenders and rateLimit observable documentation have been updated to use the new relative path structure.

Also applies to: 158-158

tko.io/src/docs/bindings/text-binding.md (2)

1-4: YAML front matter added correctly.

The Eleventy front matter is properly formatted for the documentation site.


62-62: HTML binding link has been updated correctly.

The link to the html binding documentation has been updated to use the new relative path structure.

tko.io/README.md (1)

1-64: Well-written documentation for the new Eleventy-based TKO docs site.

The README clearly explains the site structure, development workflow, and contribution process. Good guidance for contributors on how to add documentation with front matter and JSX examples.

tko.io/src/docs/binding-context/custom-bindings-disposal.md (1)

1-4: YAML front matter added correctly.

The Eleventy front matter is properly formatted.

tko.io/src/docs/computed/computed-pure.md (2)

1-4: LGTM! Front matter correctly configured.

The YAML front matter is properly structured for Eleventy templating with the correct layout and title metadata.


81-81: LGTM! Link correctly updated to relative path.

The internal link has been properly updated to use the new relative path structure that aligns with the Eleventy-based site organization.

tko.io/src/docs/observables/rateLimit-observable.md (2)

1-4: LGTM! Front matter correctly configured.

The YAML front matter is properly structured with the correct layout and title for the Eleventy build system.


11-13: LGTM! Links correctly updated to relative paths.

The internal documentation links have been properly updated to use relative paths that align with the new Eleventy-based site structure.

tko.io/src/_layouts/base.njk (1)

1-8: LGTM! Standard HTML document structure.

The HTML document structure is properly configured with charset, viewport, and dynamic title templating.

.github/workflows/deploy-docs.yml (3)

1-16: LGTM! Workflow configuration is properly structured.

The workflow triggers, permissions, and concurrency settings are correctly configured for GitHub Pages deployment. The cancel-in-progress: false setting is appropriate to avoid incomplete deployments.


17-36: LGTM! Build job is correctly configured.

The build job properly sets up Bun, installs dependencies, builds the site, and uploads the artifact for deployment. The workflow aligns with the package.json scripts.


38-47: LGTM! Deploy job is correctly configured.

The deploy job properly depends on the build job and uses the correct GitHub Pages deployment action with the appropriate environment configuration.

tko.io/src/docs/components/component-custom-elements.md (2)

1-4: LGTM! Front matter correctly configured.

The YAML front matter is properly structured for the Eleventy build system.


156-156: LGTM! Links and anchors correctly updated.

The anchor wrapped with raw tags and the updated relative link paths are correct for the new Eleventy-based site structure.

Also applies to: 178-178

tko.io/src/css/tko.css (1)

532-621: LGTM! Interactive example styling is well-structured.

The CSS for the interactive examples provides a responsive split-pane layout with proper error display and mobile-friendly breakpoints.

tko.io/package.json (2)

2-5: LGTM! Package metadata correctly updated.

The package name, type, description, keywords, and author fields are appropriately configured for the new documentation site using ES modules.

Also applies to: 13-14


16-20: LGTM! Dependencies correctly configured.

The devDependencies are properly set up with Eleventy, esbuild-wasm, and markdown-it for building the static documentation site.

tko.io/.eleventy.js (4)

1-27: LGTM! Markdown and asset configuration is correct.

The markdown-it configuration with HTML enabled, linkify, and standard line break behavior is appropriate. The passthrough copies and watch targets are properly set up for the static assets.


29-63: LGTM! Documentation collections are well-structured.

The six documentation collections (bindingDocs, observableDocs, computedDocs, componentDocs, bindingContextDocs, advancedDocs) are properly configured with glob patterns, filtering, and sorting. The consistent structure makes the collections easy to maintain.


66-76: LGTM! Template filters are correctly implemented.

The formatTitle and formatBindingName filters provide clean transformation logic for displaying documentation titles in the navigation. The implementation is concise and handles the use cases properly.


78-88: LGTM! Directory configuration is correctly set up.

The Eleventy configuration properly specifies the input/output directories and template engines for the documentation site build process.

Comment on lines +224 to +227
## Hidden

* add `hidden` binding (knockout/knockut#2103)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Typo in GitHub issue reference.

Line 226 contains "knockout/knockut#2103" which should be "knockout/knockout#2103".

🔎 Proposed fix
 ## Hidden

-  * add `hidden` binding (knockout/knockut#2103)
+  * add `hidden` binding (knockout/knockout#2103)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Hidden
* add `hidden` binding (knockout/knockut#2103)
## Hidden
* add `hidden` binding (knockout/knockout#2103)
🤖 Prompt for AI Agents
In tko.io/src/3to4.md around lines 224 to 227, there's a typo in the GitHub
issue reference "knockout/knockut#2103"; update the repository name to
"knockout/knockout#2103" so the issue link points to the correct project.

Comment on lines +272 to +281
.sidebar .section {
font-size: 0.875rem;
font-weight: 600;
color: #111827;
padding: 0.5rem 0.75rem 0.25rem;
margin-top: 1rem;
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 0.75rem;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix duplicate font-size property.

The .sidebar .section selector has font-size declared twice (line 273 and line 280), which causes the second value to override the first. This is likely unintentional.

🔎 Proposed fix

Review the intended font size and remove the duplicate. If 0.75rem is the desired size, remove line 273:

 .sidebar .section {
-  font-size: 0.875rem;
   font-weight: 600;
   color: #111827;
   padding: 0.5rem 0.75rem 0.25rem;
   margin-top: 1rem;
   text-transform: uppercase;
   letter-spacing: 0.05em;
   font-size: 0.75rem;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.sidebar .section {
font-size: 0.875rem;
font-weight: 600;
color: #111827;
padding: 0.5rem 0.75rem 0.25rem;
margin-top: 1rem;
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 0.75rem;
}
.sidebar .section {
font-weight: 600;
color: #111827;
padding: 0.5rem 0.75rem 0.25rem;
margin-top: 1rem;
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 0.75rem;
}
🧰 Tools
🪛 Biome (2.1.2)

[error] 280-280: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

font-size is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🤖 Prompt for AI Agents
In tko.io/src/css/tko.css around lines 272 to 281, the .sidebar .section rule
declares font-size twice which causes the first declaration to be overridden;
remove the unintended duplicate font-size (keep the intended value, e.g.,
0.75rem) so only a single font-size remains and ensure no other conflicting
declarations exist.

```

The binding *name* should generally match a registered binding handler (either built-in or [custom](custom-bindings.html)) or be a parameter for another binding. If the name matches neither of those, Knockout will ignore it (without any error or warning). So if a binding doesn't appear to work, first check that the name is correct.
The binding *name* should generally match a registered binding handler (either built-in or [custom](../../binding-context/custom-bindings/)) or be a parameter for another binding. If the name matches neither of those, Knockout will ignore it (without any error or warning). So if a binding doesn't appear to work, first check that the name is correct.
Copy link
Contributor

@coderabbitai coderabbitai bot Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the directory structure and verify the link path

# List the tko.io/src/docs structure
echo "=== Directory structure check ==="
ls -la tko.io/src/docs/binding-context/ 2>/dev/null || echo "binding-context directory check failed"

# Verify custom-bindings directory exists
echo -e "\n=== Check custom-bindings directory ==="
if [ -d "tko.io/src/docs/binding-context/custom-bindings" ]; then
  echo "✓ custom-bindings directory exists"
  ls -la tko.io/src/docs/binding-context/custom-bindings/
else
  echo "✗ custom-bindings directory does not exist"
fi

# Check the binding-syntax.md file exists and view line 29
echo -e "\n=== Check binding-syntax.md file ==="
if [ -f "tko.io/src/docs/binding-context/binding-syntax.md" ]; then
  echo "✓ binding-syntax.md exists"
  echo "Line 29 content:"
  sed -n '29p' tko.io/src/docs/binding-context/binding-syntax.md
else
  echo "✗ binding-syntax.md does not exist"
fi

Repository: knockout/tko

Length of output: 1351


Fix the broken link path to the custom bindings documentation.

The link ../../binding-context/custom-bindings/ points to a non-existent directory. The custom-bindings documentation is in the file custom-bindings.md, so the link should be ../../binding-context/custom-bindings.md (or custom-bindings.md if using relative path from binding-syntax.md).

🤖 Prompt for AI Agents
In tko.io/src/docs/binding-context/binding-syntax.md around line 29, the link
currently points to ../../binding-context/custom-bindings/ which doesn't exist;
update the link target to the actual file path (e.g.
../../binding-context/custom-bindings.md or ./custom-bindings.md depending on
desired relative path) so the “custom bindings” documentation resolves
correctly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the path is correct

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@phillipc, you're absolutely right! Eleventy converts non-index files into folders with an index.html inside, which provides cleaner URLs. So custom-bindings.md in the source becomes accessible at custom-bindings/ in the generated site.

The link ../../binding-context/custom-bindings/ will work correctly in the built output, even though the source file is custom-bindings.md. This is the standard pattern used throughout this PR (as seen in links like ../with-binding/, ../foreach-binding/, etc.).

(___/)
(='.'=) noted for future!
(")_(")


✏️ Learnings added
Learnt from: phillipc
Repo: knockout/tko PR: 227
File: tko.io/src/docs/binding-context/binding-syntax.md:29-29
Timestamp: 2025-12-24T08:53:44.026Z
Learning: In the TKO repository's tko.io documentation site, which uses Eleventy (11ty) as the static site generator, Markdown links should point to directory-style URLs with trailing slashes (e.g., `../custom-bindings/`) rather than to the source `.md` files. Eleventy automatically transforms each Markdown file into a directory containing an `index.html` file for cleaner URLs, so `custom-bindings.md` becomes accessible at `custom-bindings/` in the built site.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: phillipc
Repo: knockout/tko PR: 221
File: packages/bind/spec/bindingAttributeBehaviors.ts:135-138
Timestamp: 2025-12-21T09:16:36.575Z
Learning: In the TKO framework, data-bind expressions support "naked" arrow function syntax where zero-parameter arrow functions can be written without parentheses, e.g., `data-bind='click: => was_clicked(true)'` or `lambdaLiteral: => null`. This is valid TKO syntax even though it's not standard JavaScript.

# Custom Disposal Logic

In a typical Knockout application, DOM elements are dynamically added and removed, for example using the [`template`](template-binding.html) binding or via control-flow bindings ([`if`](if-binding.html), [`ifnot`](ifnot-binding.html), [`with`](with-binding.html), and [`foreach`](foreach-binding.html)). When creating a custom binding, it is often desirable to add clean-up logic that runs when an element associated with your custom binding is removed by Knockout.
In a typical Knockout application, DOM elements are dynamically added and removed, for example using the [`template`](template-binding.html) binding or via control-flow bindings ([`if`](../if-binding/), [`ifnot`](ifnot-binding.html), [`with`](../with-binding/), and [`foreach`](../foreach-binding/)). When creating a custom binding, it is often desirable to add clean-up logic that runs when an element associated with your custom binding is removed by Knockout.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Update incomplete: Two binding links still use old .html format while others use new relative paths.

Line 8 has inconsistent link formats: template-binding.html and ifnot-binding.html use the old format, while if, with, and foreach use the new directory-relative format. All should be updated to match the new site structure.

🔎 Proposed fix for inconsistent link formats
-In a typical Knockout application, DOM elements are dynamically added and removed, for example using the [`template`](template-binding.html) binding or via control-flow bindings ([`if`](../if-binding/), [`ifnot`](ifnot-binding.html), [`with`](../with-binding/), and [`foreach`](../foreach-binding/)). When creating a custom binding, it is often desirable to add clean-up logic that runs when an element associated with your custom binding is removed by Knockout.
+In a typical Knockout application, DOM elements are dynamically added and removed, for example using the [`template`](../template-binding/) binding or via control-flow bindings ([`if`](../if-binding/), [`ifnot`](../ifnot-binding/), [`with`](../with-binding/), and [`foreach`](../foreach-binding/)). When creating a custom binding, it is often desirable to add clean-up logic that runs when an element associated with your custom binding is removed by Knockout.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
In a typical Knockout application, DOM elements are dynamically added and removed, for example using the [`template`](template-binding.html) binding or via control-flow bindings ([`if`](../if-binding/), [`ifnot`](ifnot-binding.html), [`with`](../with-binding/), and [`foreach`](../foreach-binding/)). When creating a custom binding, it is often desirable to add clean-up logic that runs when an element associated with your custom binding is removed by Knockout.
In a typical Knockout application, DOM elements are dynamically added and removed, for example using the [`template`](../template-binding/) binding or via control-flow bindings ([`if`](../if-binding/), [`ifnot`](../ifnot-binding/), [`with`](../with-binding/), and [`foreach`](../foreach-binding/)). When creating a custom binding, it is often desirable to add clean-up logic that runs when an element associated with your custom binding is removed by Knockout.
🤖 Prompt for AI Agents
tko.io/src/docs/binding-context/custom-bindings-disposal.md around line 8: the
links to template-binding.html and ifnot-binding.html use the old .html format
while the other bindings use new relative paths; update those two links to the
new directory-relative paths to match the site's link style (e.g., replace
template-binding.html with ../template-binding/ and ifnot-binding.html with
../ifnot-binding/ or the exact relative paths used elsewhere in the doc).

Two points to note about this example:

* If you're inside a nested [binding context](binding-context.html), for example if you're inside a `foreach` or a `with` block, but your handler function
* If you're inside a nested [binding context](../../binding-context/binding-context/), for example if you're inside a `foreach` or a `with` block, but your handler function
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all binding-context related files to verify target path
find tko.io/src/docs -type f -name "*binding-context*" 2>/dev/null | sort
# List directory structure around bindings
find tko.io/src/docs -maxdepth 2 -type d 2>/dev/null | sort

Repository: knockout/tko

Length of output: 284


Fix the relative path to binding-context.

The link path ../../binding-context/binding-context/ navigates up two directory levels and then looks for binding-context/binding-context/, but the binding-context directory is a sibling of bindings/ in tko.io/src/docs/. The correct relative path is ../binding-context/binding-context/ (one level up, not two).

🤖 Prompt for AI Agents
In tko.io/src/docs/bindings/click-binding.md around line 38, the relative link
to the binding-context docs is incorrect (uses
../../binding-context/binding-context/) and should navigate one level up to the
sibling binding-context folder; change the path to
../binding-context/binding-context/ so the link points to the correct directory
relative to bindings/.

Two points to note about this example:

* If you're inside a nested [binding context](binding-context.html), for example if you're inside a `foreach` or a `with` block, but your handler function
* If you're inside a nested [binding context](../../binding-context/binding-context/), for example if you're inside a `foreach` or a `with` block, but your handler function
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's explore the repository structure around the docs
echo "=== Repository structure ===" 
git ls-files | head -20

echo ""
echo "=== Checking event-binding.md file ===" 
# Look at the file mentioned in the review
if [ -f "tko.io/src/docs/bindings/event-binding.md" ]; then
  echo "File exists. Content around lines 78 and 127:"
  sed -n '75,82p' tko.io/src/docs/bindings/event-binding.md
  echo ""
  sed -n '124,131p' tko.io/src/docs/bindings/event-binding.md
else
  echo "File not found at tko.io/src/docs/bindings/event-binding.md"
fi

echo ""
echo "=== Searching for binding-context files ===" 
fd "binding-context" tko.io/src/docs --type f

echo ""
echo "=== Searching for click-binding files ===" 
fd "click-binding" tko.io/src/docs --type f

echo ""
echo "=== Full binding-context directory structure ===" 
find tko.io/src/docs/binding-context -type f 2>/dev/null | head -20

echo ""
echo "=== Full bindings directory structure ===" 
find tko.io/src/docs/bindings -type f 2>/dev/null | head -20

Repository: knockout/tko

Length of output: 3801


Internal link targets are broken and will not resolve correctly.

The links have been updated to use directory-based routing syntax (e.g., ../../binding-context/binding-context/ and ../click-binding/), but the actual documentation files exist as .md files without corresponding directory structures:

  • ../../binding-context/binding-context/ (link) → actual file is binding-context.md
  • ../click-binding/ (link) → actual file is click-binding.md

Either update the links to point directly to the .md files (e.g., ../../binding-context/binding-context.md) or restructure the files to have index.md within directories to support the directory-based routing pattern.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

78-78: Unordered list indentation
Expected: 0; Actual: 1

(MD007, ul-indent)

🤖 Prompt for AI Agents
In tko.io/src/docs/bindings/event-binding.md around line 78, the internal links
use directory-based routing (e.g., ../../binding-context/binding-context/ and
../click-binding/) but the actual docs are plain .md files (binding-context.md
and click-binding.md); update those links to point directly to the .md files
(../../binding-context/binding-context.md and ../click-binding.md) or convert
the target files into directory-based index.md pages so the routes resolve
correctly.

Comment on lines 6 to +11
# `style`

### Purpose
The `style` binding adds or removes one or more style values to the associated DOM element. This is useful, for example, to highlight some value in red if it becomes negative, or to set the width of a bar to match a numerical value that changes.

(Note: If you don't want to apply an explicit style value but instead want to assign a CSS class, see [the css binding](css-binding.html).)
(Note: If you don't want to apply an explicit style value but instead want to assign a CSS class, see [the css binding](../css-binding/).)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Address markdown heading level skip.

The document jumps from an h1 heading (# \style`) directly to h3 (### Purpose), skipping h2. While this structure may have existed prior to this PR, consider promoting ### Purposeto## Purpose` to follow proper heading hierarchy, or introduce an h2 section if one is semantically appropriate.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

8-8: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🤖 Prompt for AI Agents
In tko.io/src/docs/bindings/style-binding.md around lines 6 to 11, the markdown
skips from an h1 heading to an h3; change the "### Purpose" heading to "##
Purpose" (or insert an appropriate h2) so heading levels are hierarchical and
consistent; update any adjacent headings if needed to maintain document
structure.


* None

### Note 1: Using functions and expressions to detemine text values
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix spelling error: "detemine" → "determine"

Line 34 contains a spelling error that should be corrected before publication.

🔎 Proposed fix for spelling error
-If you want to detemine text programmatically, one option is to create a [computed observable](../../computed/computedObservables/), and use its evaluator function as a place for your code that works out what text to display.
+If you want to determine text programmatically, one option is to create a [computed observable](../../computed/computedObservables/), and use its evaluator function as a place for your code that works out what text to display.

Also applies to: 34-34

🧰 Tools
🪛 LanguageTool

[grammar] ~32-~32: Ensure spelling is correct
Context: ...e 1: Using functions and expressions to detemine text values If you want to detemine te...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
In tko.io/src/docs/bindings/text-binding.md around lines 32 to 34, there is a
spelling mistake in the heading "Using functions and expressions to detemine
text values"; change "detemine" to "determine" (also update any duplicate
occurrence on line 34) so the heading reads "Using functions and expressions to
determine text values".

return viewModel.firstName() + ' ' + viewModel.lastName();
});

const { node } = ko.jsx.render(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n tko.io/src/index.md | sed -n '35,65p'

Repository: knockout/tko

Length of output: 1001


🌐 Web query:

TKO 4.0.0 release npm package latest version

💡 Result:

There is no published TKO 4.0.0 stable release on npm. The TKO packages on npm are at 4.0.0 beta/alpha versions (for example @tko/build.reference is 4.0.0-beta1.7 and @tko/build.knockout is 4.0.0-beta1.6). [1][2][3]

Sources:

  • @tko/build.reference package info (v4.0.0-beta1.7). [1]
  • @tko/build.knockout package info (v4.0.0-beta1.6). [2]
  • tko (jsDelivr listing showing 4.0.0-alpha versions). [3]

🌐 Web query:

ko.jsx.render TKO knockout API documentation

💡 Result:

I couldn't find any official API documentation for a function named "ko.jsx.render" (no results in TKO/Knockout docs or major repos). If you meant server/client rendering or JSX-style templating with TKO/Knockout, see:

  • TKO (Knockout 4) project docs and getting-started (TKO builds and packages). [1]
  • Knockout template/component rendering APIs (ko.renderTemplate / template binding / components) — how Knockout renders templates and components. [2][3]

If you can confirm whether you meant:

  • a specific third-party plugin named "ko.jsx",
  • server-side rendering with Knockout,
  • or using JSX/React-style syntax with Knockout (bridge libraries),

I’ll search for exact docs or examples and return links.


Update CDN reference to an available TKO version and verify ko.jsx.render API availability.

Line 60 references [email protected], which does not exist as a stable release on npm. Only beta/alpha versions are available (e.g., 4.0.0-beta1.7, 4.0.0-beta1.6). Additionally, ko.jsx.render (lines 38–44) is not documented as a public API in TKO/Knockout. Update the example to use an available version and confirm the JSX rendering approach is supported and documented.

🤖 Prompt for AI Agents
In tko.io/src/index.md around line 38 (and the referenced CDN at line ~60), the
example pins an unavailable stable release ([email protected]) and uses ko.jsx.render
which is not a documented public API; update the CDN import to a published
version (for example [email protected] or the latest published beta) and replace
or verify the ko.jsx.render call with the documented rendering API from TKO
(e.g., switch to the officially supported render/applyBindings method or the
documented JSX helper from the TKO docs), then test the snippet to ensure it
runs with the chosen version and update the docs to reference the exact version
and API used.

@@ -0,0 +1,146 @@
import * as esbuild from 'https://cdn.jsdelivr.net/npm/[email protected]/esm/browser.min.js';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we port this also to TypeScript?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at some point, definitely

@@ -0,0 +1,88 @@
import markdownIt from "markdown-it";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Port to TypeScript at some point?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally yes, good point, but I'm not sure how / whether eleventy can import it.

@phillipc
Copy link
Member

The AI ​​comments are good. I only left a few small comments.

margin: 0;
padding: 0;
overflow-x: hidden;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or Simply, CDN free and the same font everywhere

Suggested change
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif;
font-family: sans-serif;

@@ -0,0 +1,659 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');

See below

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
tko.io/package.json (2)

6-15: Script decomposition improves maintainability, but consider adding error handling.

The breakdown into separate build scripts (build:libdir, build:ko, build:tko) addresses previous maintainability concerns. However, the chained commands in lines 8-9 still lack error handling—if make fails or directories are missing, the build may fail silently.

🔎 Consider moving to a shell script with error handling

Create a scripts/prebuild.sh file:

#!/bin/bash
set -e

mkdir -p src/lib

cd ../builds/knockout
make browser
cp dist/browser.min.js ../../tko.io/src/lib/ko.js

cd ../reference
make browser
cp dist/browser.min.js ../../tko.io/src/lib/tko.js

echo "✓ Prebuild completed"

Then update package.json:

-    "build:libdir": "mkdir -p src/lib",
-    "build:ko": "cd ../builds/knockout && make browser && cp dist/browser.min.js ../../tko.io/src/lib/ko.js",
-    "build:tko": "cd ../builds/reference && make browser && cp dist/browser.min.js ../../tko.io/src/lib/tko.js",
-    "prebuild": "npm run build:libdir && npm run build:ko && npm run build:tko",
+    "prebuild": "bash scripts/prebuild.sh",

17-17: Consider restoring the author field.

The author field was changed from "Knockout Team" to an empty string. If this is intentional, consider removing the field entirely; otherwise, restore the original value.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e75196f and 67e2d98.

📒 Files selected for processing (2)
  • tko.io/package.json
  • tko.io/src/docs/advanced/databind-parser.md
✅ Files skipped from review due to trivial changes (1)
  • tko.io/src/docs/advanced/databind-parser.md
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: phillipc
Repo: knockout/tko PR: 227
File: tko.io/src/docs/binding-context/binding-syntax.md:29-29
Timestamp: 2025-12-24T08:53:44.026Z
Learning: In the TKO repository's tko.io documentation site, which uses Eleventy (11ty) as the static site generator, Markdown links should point to directory-style URLs with trailing slashes (e.g., `../custom-bindings/`) rather than to the source `.md` files. Eleventy automatically transforms each Markdown file into a directory containing an `index.html` file for cleaner URLs, so `custom-bindings.md` becomes accessible at `custom-bindings/` in the built site.
📚 Learning: 2025-12-24T08:53:44.026Z
Learnt from: phillipc
Repo: knockout/tko PR: 227
File: tko.io/src/docs/binding-context/binding-syntax.md:29-29
Timestamp: 2025-12-24T08:53:44.026Z
Learning: In the TKO repository's tko.io documentation site, which uses Eleventy (11ty) as the static site generator, Markdown links should point to directory-style URLs with trailing slashes (e.g., `../custom-bindings/`) rather than to the source `.md` files. Eleventy automatically transforms each Markdown file into a directory containing an `index.html` file for cleaner URLs, so `custom-bindings.md` becomes accessible at `custom-bindings/` in the built site.

Applied to files:

  • tko.io/package.json
🔇 Additional comments (2)
tko.io/package.json (2)

4-5: LGTM! Module type and description are appropriate.

The addition of "type": "module" enables ES module support, and the description accurately reflects the site's purpose as a documentation platform.


16-16: LGTM! Keywords are appropriate.

The keywords accurately describe the package and improve discoverability.

Comment on lines +19 to 23
"devDependencies": {
"@11ty/eleventy": "^3.0.0",
"esbuild-wasm": "^0.24.0",
"markdown-it": "^14.1.0"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

npm view @11ty/[email protected] version 2>/dev/null || echo "Checking available versions..."
npm view @11ty/eleventy versions --json 2>/dev/null | head -50

Repository: knockout/tko

Length of output: 686


🏁 Script executed:

npm view [email protected] version 2>/dev/null || echo "Checking available versions..."
npm view esbuild-wasm versions --json 2>/dev/null | tail -20

Repository: knockout/tko

Length of output: 294


🏁 Script executed:

npm view [email protected] version 2>/dev/null || echo "Checking available versions..."
npm view markdown-it versions --json 2>/dev/null | tail -20

Repository: knockout/tko

Length of output: 291


🌐 Web query:

@11ty/eleventy 3.0.0 security advisories vulnerabilities

💡 Result:

Short answer: There are no published security advisories specifically for @11ty/eleventy v3.0.0.

Sources:

  • GitHub Security page for the project states there are no published security advisories. [1]
  • Snyk vulnerability database shows no direct vulnerabilities for Eleventy (latest 3.x entries show no direct security issues). [2][3]

Notes:

  • Very old Eleventy releases (e.g., ~0.11.x) historically depended on vulnerable packages (example: pug), but that does not apply to v3.0.0; check your project's transitive dependencies with npm audit / Snyk for package-specific issues. [4]

🌐 Web query:

esbuild-wasm 0.24.0 security vulnerabilities

💡 Result:

Short answer: Yes — esbuild had a moderate CORS-related vulnerability (GHSA-67mh-4wv8-2f99) affecting versions <= 0.24.2 that could let a malicious webpage read responses from the development server. It was patched in esbuild 0.25.0. For esbuild-wasm, Snyk reports no direct vulnerabilities for that package version list, but projects using esbuild/esbuild-wasm versions <= 0.24.2 should upgrade. [1][2]

What to do:

  • Upgrade esbuild/esbuild-wasm to a patched version (>= 0.25.0; preferably the latest release). [1][2]

Sources:

  • GitHub Advisory GHSA-67mh-4wv8-2f99 (esbuild; patched in 0.25.0). [1]
  • Snyk package page for esbuild-wasm (no direct vulnerabilities listed; shows latest non-vulnerable versions). [2]

🌐 Web query:

markdown-it 14.1.0 security advisories CVE

💡 Result:

Yes — markdown-it 14.1.0 is associated with CVE-2025-7969, a reflected Cross‑Site Scripting (XSS) issue (lib/renderer.mjs; triggered when custom highlight functions are used). Fluid Attacks published the advisory; the CVE is recorded by NVD and tracked in the markdown‑it GitHub issue (upstream has disputed/not planned). [1][2][3]

Sources:

  • Fluid Attacks advisory (fito) — details & PoC. [1]
  • NVD entry for CVE-2025-7969. [2]
  • markdown-it GitHub issue #1122 (discussion / upstream response). [3]

References:
[1] https://fluidattacks.com/advisories/fito
[2] https://nvd.nist.gov/vuln/detail/CVE-2025-7969
[3] markdown-it/markdown-it#1122


Packages have security vulnerabilities—require updates before merging.

Moving these to devDependencies is correct for a documentation site. However, verification found security issues in the specified versions:

  • esbuild-wasm ^0.24.0: Contains CORS vulnerability (GHSA-67mh-4wv8-2f99) patched in 0.25.0. Upgrade to at least 0.25.0.
  • markdown-it ^14.1.0: Contains reflected XSS vulnerability (CVE-2025-7969) when custom highlight functions are used. Consider updating to a patched version or disabling custom highlighting.
  • @11ty/eleventy 3.0.0: No known vulnerabilities.

Update the vulnerable packages before proceeding.

🤖 Prompt for AI Agents
In tko.io/package.json around lines 19 to 23, the devDependencies list pins
vulnerable versions: esbuild-wasm ^0.24.0 (CORS vuln GHSA-67mh-4wv8-2f99) and
markdown-it ^14.1.0 (reflected XSS CVE-2025-7969). Update esbuild-wasm to at
least 0.25.0 (or latest) and update markdown-it to a patched release (or
latest); if you rely on custom highlight functions for markdown-it,
remove/disable them or adjust to a safe implementation before updating; run
npm/yarn install and lockfile update, then run the site build and security
checks to verify no remaining advisories.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
tko.io/src/3to4.md (1)

227-227: ⚠️ Typo in GitHub repository reference (duplicate of prior comment).

The typo "knockout/knockut#2103" should be "knockout/knockout#2103" to reference the correct repository. This issue was flagged in a previous review but remains in the current code.

🧹 Nitpick comments (1)
tko.io/src/3to4.md (1)

12-12: Minor language preference: "take a look" is more idiomatic.

Replace "have a look" with "take a look" for more natural American English phrasing.

🔎 Proposed change
-To see the differences, have a look at the [CHANGELOG.md](https://github.com/knockout/tko/blob/master/CHANGELOG.md).
+To see the differences, take a look at the [CHANGELOG.md](https://github.com/knockout/tko/blob/master/CHANGELOG.md).
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67e2d98 and d7e4b57.

📒 Files selected for processing (1)
  • tko.io/src/3to4.md
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: phillipc
Repo: knockout/tko PR: 227
File: tko.io/src/docs/binding-context/binding-syntax.md:29-29
Timestamp: 2025-12-24T08:53:44.026Z
Learning: In the TKO repository's tko.io documentation site, which uses Eleventy (11ty) as the static site generator, Markdown links should point to directory-style URLs with trailing slashes (e.g., `../custom-bindings/`) rather than to the source `.md` files. Eleventy automatically transforms each Markdown file into a directory containing an `index.html` file for cleaner URLs, so `custom-bindings.md` becomes accessible at `custom-bindings/` in the built site.
📚 Learning: 2025-12-24T08:53:44.026Z
Learnt from: phillipc
Repo: knockout/tko PR: 227
File: tko.io/src/docs/binding-context/binding-syntax.md:29-29
Timestamp: 2025-12-24T08:53:44.026Z
Learning: In the TKO repository's tko.io documentation site, which uses Eleventy (11ty) as the static site generator, Markdown links should point to directory-style URLs with trailing slashes (e.g., `../custom-bindings/`) rather than to the source `.md` files. Eleventy automatically transforms each Markdown file into a directory containing an `index.html` file for cleaner URLs, so `custom-bindings.md` becomes accessible at `custom-bindings/` in the built site.

Applied to files:

  • tko.io/src/3to4.md
📚 Learning: 2025-12-21T09:16:36.575Z
Learnt from: phillipc
Repo: knockout/tko PR: 221
File: packages/bind/spec/bindingAttributeBehaviors.ts:135-138
Timestamp: 2025-12-21T09:16:36.575Z
Learning: In the TKO framework, data-bind expressions support "naked" arrow function syntax where zero-parameter arrow functions can be written without parentheses, e.g., `data-bind='click: => was_clicked(true)'` or `lambdaLiteral: => null`. This is valid TKO syntax even though it's not standard JavaScript.

Applied to files:

  • tko.io/src/3to4.md
🪛 LanguageTool
tko.io/src/3to4.md

[locale-violation] ~12-~12: In American English, “take a look” is more commonly used.
Context: ...ockout itself. To see the differences, have a look at the [CHANGELOG.md](https://github.co...

(HAVE_A_LOOK)

🪛 markdownlint-cli2 (0.18.1)
tko.io/src/3to4.md

30-30: Table pipe style
Expected: leading_and_trailing; Actual: leading_only; Missing trailing pipe

(MD055, table-pipe-style)


180-180: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


227-227: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


240-240: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


241-241: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


242-242: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


243-243: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


244-244: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


245-245: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


246-246: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


247-247: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


248-248: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)


249-249: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

🔇 Additional comments (2)
tko.io/src/3to4.md (2)

1-4: ✓ Eleventy front matter is correct.

The YAML front matter follows Eleventy conventions with proper layout and title metadata.


32-33: CSP section is well-written.

The security advantages section clearly explains TKO's CSP compatibility and sanitization options.

| `ko.proxy` | Yes | No | No |
| `ko.onError` | Does not automatically throw (you need to add `throw error` to `ko.options.onError`) | Does not rethrow automatically | Always re-throws error |
| `foreach` binding | FastForEach | Template foreach | Template foreach |
| `each` binding | FastForEach | FastForEach | Template foreach
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add missing trailing pipe to table row for consistency.

Line 30 is missing the trailing pipe character, making the table formatting inconsistent with the rest of the table.

🔎 Proposed fix
-| `each` binding    | FastForEach | FastForEach | Template foreach
+| `each` binding    | FastForEach | FastForEach | Template foreach |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| `each` binding | FastForEach | FastForEach | Template foreach
| `each` binding | FastForEach | FastForEach | Template foreach |
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

30-30: Table pipe style
Expected: leading_and_trailing; Actual: leading_only; Missing trailing pipe

(MD055, table-pipe-style)

🤖 Prompt for AI Agents
In tko.io/src/3to4.md around line 30, the markdown table row "| `each` binding  
| FastForEach | FastForEach | Template foreach" is missing the trailing pipe;
update that line to append a final " |" so the row matches the other table rows
and keeps table formatting consistent.


## Namespacing

* incorporate punches namespacing i.e. `data-bind='event.click: => thing(true)'` is equivalent to `data-bind='event: {click: => thing(true)}'`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix unordered list indentation throughout the document.

Several unordered lists have 2-space indentation but should start at column 0 (no indentation). This affects clarity and violates Markdown best practices.

🔎 Proposed fixes

Line 180:

-  * incorporate punches namespacing i.e. `data-bind='event.click: => thing(true)'` is equivalent to `data-bind='event: {click: => thing(true)}'`
+* incorporate punches namespacing i.e. `data-bind='event.click: => thing(true)'` is equivalent to `data-bind='event: {click: => thing(true)}'`

Line 227:

-  * add `hidden` binding (knockout/knockut#2103)
+* add `hidden` binding (knockout/knockout#2103)

Lines 240-249 (Deprecated section):

-# Deprecated
-
-  - Template binding options are deprecated
-  - expressionWriting (twoWayBinding)
-  - '.' in binding handler names
-  - jsonExpressionRewriting (expressionRewriting)
-  - form parsing
-  - `bind` shim
-  - ko.utils.parseJson
-  - getFormFields
-  - fieldsIncludedWithJsonPost
-  - postJson
+# Deprecated
+
+- Template binding options are deprecated
+- expressionWriting (twoWayBinding)
+- '.' in binding handler names
+- jsonExpressionRewriting (expressionRewriting)
+- form parsing
+- `bind` shim
+- ko.utils.parseJson
+- getFormFields
+- fieldsIncludedWithJsonPost
+- postJson

Also applies to: 227-227, 240-249

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

180-180: Unordered list indentation
Expected: 0; Actual: 2

(MD007, ul-indent)

🤖 Prompt for AI Agents
In tko.io/src/3to4.md around lines 180, 227 and 240-249, several unordered list
items are incorrectly indented by two spaces; remove the leading two-space
indentation so those list markers start at column 0 (no indentation), adjusting
any sublist nesting only where intended so Markdown renders correct top-level
unordered lists and nested lists remain properly indented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants