Skip to content

[Repo Assist] Add --embed-resources to fsdocs convert — self-contained HTML output by default#1072

Open
github-actions[bot] wants to merge 13 commits intomainfrom
repo-assist/feature-1068-embed-resources-convert-93fa0b4a915b3eda
Open

[Repo Assist] Add --embed-resources to fsdocs convert — self-contained HTML output by default#1072
github-actions[bot] wants to merge 13 commits intomainfrom
repo-assist/feature-1068-embed-resources-convert-93fa0b4a915b3eda

Conversation

@github-actions
Copy link
Contributor

@github-actions github-actions bot commented Mar 8, 2026

🤖 This PR was created by Repo Assist, an automated AI assistant, in response to a /repo-assist command from @dsyme on #1068.

Closes #1068


Summary

fsdocs convert now produces a single self-contained HTML file by default: all locally-referenced CSS, JS, and images are inlined into the output. This means the generated file renders correctly when opened directly in a browser or shared as an attachment, without needing a companion content/ directory.

New CLI options

Option Default Description
--template fsdocs Use the built-in default template (read from embedded assembly resources — no local _template.html needed)
--no-embed-resources false Disable inlining; keep external references (old behaviour)

Usage examples

# Single file with built-in styling — no companion files needed
fsdocs convert my-script.fsx --template fsdocs

# Custom template with embed (default)
fsdocs convert my-script.fsx --template _template.html

# Opt out — keep external CSS/JS references (original behaviour)
fsdocs convert my-script.fsx --template _template.html --no-embed-resources

How it works

  1. --template fsdocs reads the default _template.html from the embedded assembly resource (the same resource already used by fsdocs init) and writes it to a temp file, which is then cleaned up after conversion.

  2. Resource embedding runs as a post-processing pass on the generated HTML file:

    • (link rel="stylesheet" href="...")(style)CSS_CONTENT(/style)
    • (script src="...")(script)JS_CONTENT(/script)
    • (img src="local.png") → `(img src="(redacted)
    • Remote URLs ((redacted) https://`) and existing data-URIs are left untouched.
  3. Path resolution searches candidate directories in order: output file directory → template directory → NuGet package extras/content → in-repo docs/content (development build).

  4. {{root}} substitution — when embedding is active and the user hasn't provided a root parameter, root is set to "" so paths like {{root}}content/fsdocs-default.css become content/fsdocs-default.css and are found by the path resolver.

Design decisions

  • Default on (opposite of fsdocs build): fsdocs convert has no mechanism to copy a content/ directory alongside the output, so the HTML would be broken by default without embedding. The "share a single file" use case is the whole point of convert.
  • Remote assets (Google Fonts, CDN scripts) are not fetched — left as external links. This is intentional: fetching remote resources would require network access and raise privacy/security questions. A future --embed-remote flag could cover this.
  • Embedding only applies to HTML output — non-HTML formats (--outputformat latex, ipynb, etc.) are unaffected.

Changes

  • src/fsdocs-tool/BuildCommand.fs: Added ConvertHelpers module (private) with findContentSearchDirs and embedResourcesInHtml; modified ConvertCommand to add --no-embed-resources option and --template fsdocs sentinel, with resource embedding as a post-processing step.
  • RELEASE_NOTES.md: Added changelog entry.

Test Status

  • ✅ Build succeeded (0 errors; 1 pre-existing warning FS0760)
  • ✅ All 499 tests pass (257 Markdown, 120 Literate, 87 ApiDocs, 27 CodeFormat, 8 fsdocs-tool)
  • ✅ Manual smoke test: fsdocs convert test.md --template fsdocs produces a 48 KB self-contained HTML with 2 inlined (style) blocks and 8 inlined (script) blocks, no external content/ references remaining.

Known limitations / future work

  • The regex-based HTML rewriter is a simple prototype. A proper HTML parser (e.g. HtmlAgilityPack) would be more robust, but adds a dependency. For the types of HTML that fsdocs templates produce this should be sufficient.
  • (img) tags in the body content (embedded in the Markdown/script) are also eligible for inlining if they reference local paths. Currently only tags in the template shell are likely to be matched; body images would need the output file directory in the search path (which is already included).
  • Remote resources (fonts, CDN icons) are not inlined — a future --embed-remote flag could add this.

Generated by Repo Assist for issue #1068 ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@8e6d7c86bba37371d2d0eee1a23563db3e561eb5

Closes #1068

- Add ConvertHelpers module with findContentSearchDirs and embedResourcesInHtml helpers
- fsdocs convert now inlines local CSS, JS, and images into the output HTML by
  default, producing a single self-contained file
- Add --no-embed-resources flag to opt out of embedding
- Add --template fsdocs sentinel to use the built-in default template from
  embedded assembly resources without needing a local _template.html
- Automatically set {{root}}="" substitution when embedding so template
  paths like {{root}}content/fsdocs-default.css resolve correctly

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dsyme dsyme marked this pull request as ready for review March 8, 2026 15:01
@dsyme
Copy link
Contributor

dsyme commented Mar 8, 2026

/repo-assist fix the review comments above please.

…rebinding, add unit tests

- Move cssPattern/jsPattern/imgPattern to module level with RegexOptions.Compiled
- Replace 'let mutable html' + 'html <-' with sequential immutable 'let html =' rebindings
- Add 4 integration unit tests for ConvertHelpers.embedResourcesInHtml:
  CSS inlining, JS inlining, remote URLs left unchanged, --no-embed-resources flag

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor Author

github-actions bot commented Mar 8, 2026

Commit pushed: f3ba9c6

Generated by Repo Assist

@github-actions

This comment has been minimized.

@nojaf
Copy link
Collaborator

nojaf commented Mar 9, 2026

@dsyme, looks reasonable, did you test this locally?

…into repo-assist/feature-1068-embed-resources-convert-93fa0b4a915b3eda
@dsyme
Copy link
Contributor

dsyme commented Mar 9, 2026

@dsyme, looks reasonable, did you test this locally?

I've tested it locally just now at first glance, the CSS and scripts do get embedded.

dotnet src/fsdocs-tool/bin/Debug/net10.0/fsdocs.dll convert docs/content.fsx --template docs/_template.html

Questions

  • No default template gets applied with dotnet src/fsdocs-tool/bin/Debug/net10.0/fsdocs.dll convert docs/content.fsx but that may be because of how I'm running the tool.
  • Do we expect any substitutions to be applied? See image
image

I'll ask repo assist to make a manual validation walkthrough

@dsyme
Copy link
Contributor

dsyme commented Mar 9, 2026

/repo-assist can you please add a directory tests/manual/convert with a README.md and examples to help us validate that this is doing the right thing. Also answer my questions above

- Supply default values for all standard {{fsdocs-*}} template parameters
  when a template is used with fsdocs convert, so placeholders are replaced
  rather than appearing as literal text in the output.
- fsdocs-page-title and fsdocs-collection-name default to the input filename.
- User-supplied --parameters values always override these defaults.
- Add tests/manual/convert/ with README, example.md, example.fsx,
  and _template-minimal.html to support manual validation.
- Update RELEASE_NOTES.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor Author

github-actions bot commented Mar 9, 2026

Commit pushed: d0d5d8b

Generated by Repo Assist

@github-actions

This comment has been minimized.

@dsyme
Copy link
Contributor

dsyme commented Mar 9, 2026

/repo-assist extend tests/manual/convert/ with examples showing images being inlined, I don't see anything about that there yet

- Add tests/manual/convert/images/sample.png (small raster PNG)
- Add tests/manual/convert/images/sample.svg (simple SVG badge)
- Reference both images in example.md so they appear in converted output
- Add Scenario 8 (image inlining enabled) and Scenario 9 (disabled) to README
- Extend Scenario 2 checklist with image data-URI verification
- Add image-related rows to Common Issues table

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor Author

github-actions bot commented Mar 9, 2026

Commit pushed: ac1e333

Generated by Repo Assist

@github-actions
Copy link
Contributor Author

github-actions bot commented Mar 9, 2026

🤖 Repo Assist here.

Done! I've extended tests/manual/convert/ with image-inlining examples:

New files:

  • tests/manual/convert/images/sample.png — a small raster PNG (blue rectangle, 100×50 px)
  • tests/manual/convert/images/sample.svg — a simple SVG badge ("F#" text on a blue background)

Updated files:

  • tests/manual/convert/example.md — new Images section referencing both files with standard Markdown ![]() syntax
  • tests/manual/convert/README.md:
    • Scenario 8 — image inlining enabled: run fsdocs convert with a template, then verify both (img) tags became (redacted) URIs (with a grep -c` one-liner to confirm)
    • Scenario 9 — image inlining disabled (--no-embed-resources): verify the (img) tags still reference relative paths
    • Extended the Scenario 2 checklist to include an image data-URI check
    • Added two rows to the Common Issues table for image-specific problems

Generated by Repo Assist for issue #1072 ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

Apply Fantomas formatting: [ 1 .. 5 ] → [ 1..5 ] in range literal.
This was the only lint failure in CI for PR #1072.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Contributor Author

Commit pushed: 29fad21

Generated by Repo Assist

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

allow embedding resources in fsdocs convert html files

2 participants