Repository navigation
v0.12.0
The @markii/* packages and the VS Code extension ship this release as
0.12.0, the Obsidian plugin as 0.9.0.
Added
-
VS Code:
Markii: Install Pack from File…(markii.installPack).
Picks a.mkpfile, validates it, asks the user to confirm that
installing it will let its code run inside every Markii preview, asks
before replacing an already-installed pack of the same namespace, unzips
it into the extension's owninstalled-packsdirectory under
globalStorage, and adds that directory tomarkii.packs. A rejected
archive reports the reason on the Markii output channel and installs
nothing. An archive is the only way a pack enters a host this way: a
markii.packsentry always names a folder. -
VS Code:
Markii: Remove Installed Pack…
(markii.removeInstalledPack). Lists the packs installed under
globalStorage, each with the version its manifest declares, asks for
confirmation, then deletes the pack's directory and removes its
markii.packsentry in one step, so an installed pack can be taken back
out without finding the storage folder by hand. -
VS Code:
Markii: Export Packgains an archive output. Alongside
today's folder export, the command now offers a single.mkpfile,
built by@markii/host's newexportPackArchive(the same compile,
zipped withfflateinstead of written as separate files) and named
with@markii/pack'spackArchiveFileName. -
@markii/host:exportPackArchive, the archive-producing counterpart
ofexportPack: it compiles a pack through the same build cache and
returns a.mkpfile's bytes rather than writing a folder. -
Obsidian: three bundled component packs,
read,dash, andprep,
need no installation. Their prebuilt registration scripts and stylesheets
are compiled at plugin build time (reusing@markii/host's
buildPackRegistrationScript, the same compiler VS Code and this plugin's
own on-demand pack loading already use) and embedded intomain.jsas
base64, the sameesbuild.options.mjspattern the Run path's worker
bundle and wasmoon'sglue.wasmalready use, with the build failing
loudly if the substitution did not happen. That makes the three-file BRAT
install carry them, with no esbuild-wasm runtime required at load time.
They behave as ordinary packs: namespaced (read_source, and so on),
listed by a note'suses:, and shown in the Insert Component and
completion catalogs. They load before any installed pack, and an
installed pack that claims a namespace one of the three already holds is
refused at install time: the bundled pack wins the namespace, matching
the ordinary collision rule rather than making an exception to it. The pack contract itself is unchanged; only
apps/obsidian's build and pack-loading pipeline gained a bundled-pack
source ahead of its on-disk one. -
Obsidian: an app-managed pack store. Installed packs live in the
plugin's own directory, one folder per namespace, and the settings tab
lists them with the version each manifest declares, a Remove control that
deletes the folder and the device's trust entry together, and an Enable
control for a pack folder that is present without being installed here.
Which namespaces this device loads is recorded device-locally, never in
plugin data, so a synced or shared vault carries none of those decisions.
A pack folder that arrives another way, through Sync or a hand copy, sits
inert until it is enabled, and enabling asks the same consent question
installing asks. A folder whosepack.jsondeclares some other namespace
than the folder's own name is not loaded at all. -
Obsidian:
Reload Markii packs. Installing, removing, and enabling a
pack already reload every open preview and Reading view on the spot; this
command does the same on demand, and each reload writes what loaded and
what was skipped to the diagnostics console. -
A
tablestandard component, data-bound likestat,progress, and
chart. It handles four bound shapes: an array of objects (columns from
the union of keys, in first-seen order), an array of arrays (rows as
given), an array of primitives (one column), and a single object
(key/value rows).columns=picks and orders columns,limit=caps the
rows shown,caption=adds a caption, andformat=/decimals=apply to
numeric cells only. A missing, stale, or failed binding collapses to one
quiet empty state rather than an error. -
format=anddecimals=attributes on:value[...],stat,
progress, andtable.numbergroups thousands,compactshortens
them,percentreads a fraction as a percentage, anddateand
relativeread an ISO date or epoch milliseconds.plainstays the
default, so existing documents render unchanged. An invalidformator
decimalsis ignored rather than raised, and non-numeric input under a
numeric format shows unchanged. The logic lives in one@markii/stdlib
primitive both renderers call, so the two engines cannot format a value
differently. -
conformance/render/, a render-level fixture set: each.mk.mdinput
is paired with committed.htmlthat@markii/htmlis byte-diffed
against, with@markii/reactcross-checked for the same classes and
structure. The existing corpus pins the AST; this pins the rendered
output. -
docs/spec.md§9, a requirement-to-fixture map tying every literal
MUST and MUST NOT in the spec's core sections to the test that pins it. A
new test in@markii/coreparses the table and fails when a row cites a
fixture that does not exist, so the map cannot rot into decoration. -
A dark palette for exported documents.
doc.cssremaps its Tier 1
tokens underprefers-color-scheme: dark, so a standalone HTML export
opened by a viewer with a dark OS preference renders themed instead of a
light page glaring back. A host's own theme layer (VS Code, Obsidian)
still wins the cascade for its own preview, since it redeclares the same
tokens unconditionally afterdoc.cssloads: only a page with no such
layer after it, an export, ever resolves the new block. -
A print stylesheet for exported documents.
@markii/host's
EXPORT_PAGE_CSSnow sets@pagemargins, keeps a card, callout, or
table from splitting across a page break, and hides the collapsed script
marker and the VS Code webview's run marker when printing. -
An
index.htmlentry file for a cascade export.@markii/host's new
buildCascadeIndexHtmllists every note a cascade exported by title,
linking to its file, and both hosts write it into the archive alongside
the notes.assignCascadeFileNamestakes an optionalreservedNames
list so a walked note literally calledindexgets suffixed instead of
colliding with the archive's own index page. -
A
hideScriptBlocksexport option.buildNoteHtmlExport,
composeNoteHtmlExport, andbuildNoteExportaccept it, and
exportHtmlDocumentgrew a matchingdocClassNameoption to carry it
onto the.docwrapper. Both hosts pass their existing preview
preference (VS Code'smarkii.hideScriptBlocks, Obsidian's "Hide script
blocks" setting) into every export, so a note exported with scripts
hidden in the editor stays that way in the file. -
Obsidian:
.mk.mdnotes render inline in Reading view. A markdown
post processor renders the whole note through the same@markii/react
seam the Markii Preview pane uses, into the first Reading-view section
Obsidian calls it for, and leaves every later section empty, since
Obsidian's section splits do not line up with a Markii:::container's
span. Wikilinks and embeds are converted to ordinary markdown first,
resolved through Obsidian's metadata cache, so an unresolved link keeps
pointing at its own text instead of breaking the render. A run's values
update the rendered note without reopening it. A plain.mdfile is
never touched, and Live Preview stays untouched by design. The new
"Render components in Reading view" setting, on by default, turns this
off while leaving the Markii Preview pane exactly as it was. -
Obsidian: install a pack from a
.mkpfile. The new "Install Markii
pack from file" command validates the archive, asks in words that say the
pack's code will run in the preview, asks again before replacing a pack of
the same name, and writes nothing until all of that has passed. A rejected
archive is reported and leaves nothing behind. An entry in the device-local
pack list can also point straight at a.mkp, read where it sits and never
compiled, so it works on an install that carries no compiler. -
An optional
versionfield on a pack manifest (@markii/pack). A
pack'spack.jsonmay now declare a plain semverversionstring
(MAJOR.MINOR.PATCH, digits only, no leading zeros, no prerelease or
build suffix). Omitting it stays fully valid, with no warning. A present
but malformed value is a validation error, the same posturenamegets,
since a version a host cannot trust is worse than none. The three
bundled packs (read,dash,prep) now declare"version": "1.0.0". -
.mkppack archives: a reader in@markii/pack.openPackArchive
takes the raw bytes of a.mkpfile (a zip of a pack's prebuilt form,
files at the archive root:pack.json,webview.js,webview.csswhen
present,scripts/when present) and returns its validated manifest,
compiled script, optional stylesheet, and optional shared Lua modules, or
a structured error. It never compiles anything: an archive with no
webview.jsis rejected, since.mkpexists for hosts that may not
carry a compiler. It reuses@markii/bundle's zip reader and path jail
rather than a second implementation, so a.mkpgets the same
decompression-bomb guard and zip-slip rejection (../, an absolute
path) a.mkzbundle gets.packArchiveFileNameimplements the naming
rule for a produced archive,<name>-<version>.mkp, falling back to
<name>.mkpwhen the manifest declares noversion. -
The VS Code extension ships three bundled packs by default:
read,
dash, andprep(their sources now live atpacks/in this
repository, moved from the separatemarkii-packsrepo).esbuild.config.mjs
compiles each one at extension build time intodist/packs/<name>/
(pack.json,webview.js,webview.csswhen the pack has CSS, and
scripts/when it has Lua), reusing the same@markii/hostpack
compiler themarkii.exportPackcommand runs. The extension treats
dist/packsas an always-present pack root, ordered ahead of the
user'smarkii.packsentries: a bundled pack is namespaced, listed by
a note'suses:, and shown in the Insert Component and completion
catalogs like any other pack. A user pack claiming the same namespace
as a bundled one is skipped, with a line on the Markii output channel
explaining that the bundled pack won. -
A root
typecheck:packsscript (tsc -p packs/tsconfig.json),
wired into the rootbuildchain, so a broken bundled pack source
fails the build instead of shipping silently.packs/is not an npm
workspace, so nothing else typechecks it.
Changed
- Obsidian: packs are installed, not configured. A
.mkparchive
installed with "Install Markii pack from file" is now the only way a pack
enters the plugin. The device-local pack-folder list is gone and its
entries are no longer read, and with them the ability to compile a pack
from source: the plugin loads the prebuilt form only, which is what an
archive carries. To carry a source pack over, export it from VS Code with
"Markii: Export Pack" as a.mkpand install that file. VS Code is
unchanged here: it is the authoring host and still loads source folders. - Obsidian: the plugin is three files again. Dropping the compiler
removes theesbuild-wasmruntime from the plugin folder, so an install
ismain.js,manifest.json, andstyles.cssby either route, and the
release no longer attaches a separate runtime asset. The Obsidian Sync
file-size caveat that runtime carried is gone with it. - VS Code: a pack change takes effect at once. Installing a pack,
removing one, or editingmarkii.packsnow reloads the open preview's
packs and re-renders it, instead of asking you to reopen the preview. - The four
width=presets are themeable.--mk-width-fit,
--mk-width-narrow,--mk-width-wide, and--mk-width-fulljoin the
Tier 1 token contract, bringing it to 19 properties, so a host can widen
or shrink a preset without overriding a selector. Both host theme layers
map them to today's values, so nothing changes visually. - A bundle manifest declares its spec version as
spec. The retired
namemarkis still read, so existing bundles keep working, and it
records a warning asking for the rename. When both are presentspec
wins.markis never written.
Fixed
@markii/pack's manifest validation accepts an emptycomponentsmap.
A pack that carriesscripts/*.luaand nothing to render used to be
rejected with"components" must have at least one entry. There is
exactly one way to share Lua beyond a bundle's ownscripts/folder: a
pack module. A folder of shared code with nothing to render is simply a
pack whosecomponentsis{}, not a separate "vault library" concept,
so it is no longer an error. An end-to-end test in@markii/host
(pack-module-require.e2e.test.ts) pins the whole chain: manifest
parsing, pack discovery, module loading, andrequire "name/module"
resolving against the real wasmoon interpreter.
Security
- Consent prompting is unified on what a script actually does. A run
prompts based on the static scan of script content; manifest
declarations inform diagnostics rather than driving a second prompt, and
a declaredpermissions.bundlegrant no longer raises a prompt of its
own. The path jail and the read-only tier gate for automatic and
scheduled triggers are unchanged. An executed probe drives the real
worker thread and the real Lua sandbox rather than asserting on mocks.
Install
The renderer pulls the rest in as dependencies:
npm install @markii/react@0.12.0
All eight packages, if you want them explicitly:
npm install @markii/core@0.12.0
npm install @markii/stdlib@0.12.0
npm install @markii/bundle@0.12.0
npm install @markii/pack@0.12.0
npm install @markii/runtime@0.12.0
npm install @markii/lua@0.12.0
npm install @markii/react@0.12.0
npm install @markii/html@0.12.0
Downloads
The attached tarballs are the packed npm packages. The names are
stable across releases, so the latest of each is always at a fixed URL:
https://github.com/markii-org/markii/releases/latest/download/markii-core.tgz
https://github.com/markii-org/markii/releases/latest/download/markii-stdlib.tgz
https://github.com/markii-org/markii/releases/latest/download/markii-bundle.tgz
https://github.com/markii-org/markii/releases/latest/download/markii-pack.tgz
https://github.com/markii-org/markii/releases/latest/download/markii-runtime.tgz
https://github.com/markii-org/markii/releases/latest/download/markii-lua.tgz
https://github.com/markii-org/markii/releases/latest/download/markii-react.tgz
https://github.com/markii-org/markii/releases/latest/download/markii-html.tgz