Skip to content

Embedded text

A context or a commons reads a project file’s text with an embed declaration. The file’s contents become a String constant compiled into the code; unlike an asset it is never served. See the grammar for embed_decl and §5.12a of the specification.

commons app.page
---
The page shell.
---
embed shell = "embeds/page.html"
fn page(title: String, content: String) -> String {
shell.replace("{{title}}", title).replace("{{content}}", content)
}

embeds/page.html is an ordinary file, so an editor gives it the highlighting, formatting and diffs of its own language. shell is a String; {{title}} and {{content}} are the author’s convention, not syntax the language knows.

  • Path: relative to the project root, and inside the project’s embeds/ folder. Anything else is bynk.embed.outside_embeds_dir; a path that is empty, absolute or contains .. is bynk.embed.unsafe_path. The file must exist as a regular file (bynk.embed.missing_file) and be readable (bynk.embed.unreadable_file); symbolic links are not followed. Only the files a declaration names are read.
  • Name: a value of type String, in the same namespace as functions, assets, types and events, so it may not repeat an embed (bynk.embed.duplicate) or reuse one of those names (bynk.resolve.name_conflict) in the same unit.
  • Where: in a context or a commons, never an adapter (bynk.embed.outside_context_or_commons). A unit sees its own embeds and those of each commons it uses, like functions.
  • A dependency may not declare one yet (bynk.package.unsupported_in_dependency), as for an asset.

The value is the file’s contents verbatim, with three exceptions that keep a build the same on every checkout:

  • A leading byte-order mark is dropped.
  • \r\n and a bare \r become \n.
  • Nothing else changes; a trailing newline is kept.

The file must be UTF-8 text: invalid UTF-8 is bynk.embed.invalid_encoding and a NUL byte is bynk.embed.binary_content. A binary file belongs in assets/.

The text is not interpreted. \( and {{ }} mean nothing to the language, so substituting into a template is ordinary String code, and nothing is escaped for you. Escape every value you substitute into markup, and check a rendered page for a placeholder you forgot to fill:

expect page("Home", "hi").contains("{{") == false

An embedded file may be at most 256 KiB, and the files a project’s declarations name at most 1 MiB in all, each file counted once (bynk.embed.too_large). The text is part of the Worker’s code, so an embed is for markup and prose, not data.

An embed is an exported string constant of the declaring module, imported by name like a function wherever a unit uses it. A bundler drops one that nothing references. bynk dev rebuilds when a file in embeds/ changes.

A unit-tier suite case can name its target’s embeds, and those of the commons the target uses, to assert on the text. A system suite cannot: an embed is code, not something a Worker serves.

A single file (bynkc compile page.bynk) has no project to find embeds/ in, so building one that declares an embed is bynk.embed.needs_project. Checking it is unaffected.

assetembed
Folderassets/embeds/
Publicyes, served by the platformno, part of the code
Valuean Asset, with a .urla String
Contentany fileUTF-8 text only

To link a stylesheet from a page whose shell is an embed, substitute the asset’s .url into the shell; see Serve a page from an HTML file.