Compare commits
272 Commits
33a5e01511
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f689a51b0 | |||
| ddc5dfa1be | |||
| 6c589ecabc | |||
| da63faa4a4 | |||
| d0f0873ca9 | |||
| 058a5fd2f8 | |||
| e84cd47f08 | |||
| 7adab8e19e | |||
| dff4983d4a | |||
| d9bacc4072 | |||
| 58a7bf91b0 | |||
| 91adec5797 | |||
| 2252232fd6 | |||
| 4d3231c86b | |||
| 95af770e0a | |||
| 361139a4d4 | |||
| dccd8dcf3a | |||
| cd2b573372 | |||
| 94eaee6bae | |||
| e949f2099c | |||
| 32df104649 | |||
| 1df58cf33e | |||
| e17e247351 | |||
| 5f3705c430 | |||
| 7b344334b6 | |||
| 8d9d1ecb5b | |||
| 3f2f63aac0 | |||
| 8cecf27757 | |||
| 1f7d11ea3e | |||
| 050e52296a | |||
| bd8d240712 | |||
| 3edc12aaa9 | |||
| c81bda9bfb | |||
| 160c2a7052 | |||
| e2a660ee8e | |||
| f105bc9a57 | |||
| 6c499127b5 | |||
| 151bf38398 | |||
| a4b6b48635 | |||
| 1a266d5661 | |||
| 9bdbcd880e | |||
| c3e86f8430 | |||
| 2395cf077e | |||
| 95ff9ee910 | |||
| 6681bec391 | |||
| 6c8ed03d36 | |||
| 43869a7219 | |||
| 33f3bf7ee4 | |||
| 1d369ec5c5 | |||
| 52cf681a1c | |||
| 06103ea2ba | |||
| 7c15b02258 | |||
| 692433b712 | |||
| b9e2842310 | |||
| 75c5917712 | |||
| daaa2134b3 | |||
| af7658a863 | |||
| 13b04e46d3 | |||
| 474e6a2991 | |||
| 23804a5b3a | |||
| 8d2d2405f3 | |||
| 4443ea57af | |||
| 09d2e54f5a | |||
| 2701e165c4 | |||
| 2a3c90d63b | |||
| bbfc8724fc | |||
| fa6df33987 | |||
| 8a898436ea | |||
| 621dc75f86 | |||
| d5dae87c9b | |||
| 348865398c | |||
| ff23145a5a | |||
| d2a3d74030 | |||
| 50f97513e8 | |||
| e5771bc60b | |||
| fb97285899 | |||
| c64eed9301 | |||
| d10da170b1 | |||
| c694896090 | |||
| becd12e294 | |||
| f855e1b348 | |||
| c6781aa9b3 | |||
| 740a7b1e59 | |||
| a74e8742ff | |||
| 11e55732e7 | |||
| 8e09cd2214 | |||
| 5d5952c576 | |||
| 1271365b38 | |||
| 1f4a94974a | |||
| 326352fa98 | |||
| 9e2c0fda15 | |||
| f594dafc5b | |||
| 613dc0edbb | |||
| 2f03e20549 | |||
| ae2dc6054b | |||
| 7a53b6f7a0 | |||
| 1eb7b54f19 | |||
| 4df17055ef | |||
| 8cb85f3d27 | |||
| 969326b776 | |||
| b42218e655 | |||
| c1fed0885b | |||
| bf87e6ea18 | |||
| 53ff7e0204 | |||
| d1a208146f | |||
| 687ba9bf90 | |||
| 0094b361ab | |||
| dbd80b98c3 | |||
| 8572d76ee9 | |||
| 62ece3f9ac | |||
| 8f33f67f72 | |||
| 3a18627389 | |||
| dc11daa540 | |||
| 7b814e02dc | |||
| 5e55ce2a8e | |||
| cf9a737e71 | |||
| 1c0a6526b1 | |||
| 8418150cd3 | |||
| d35637c8fa | |||
| c46b8243ba | |||
| 69f116db1b | |||
| 1104c57c0e | |||
| c6acef081f | |||
| 59a37d1945 | |||
| 37abc1ddc1 | |||
| cb30512a90 | |||
| 3fce43e884 | |||
| 0644d1bc5d | |||
| b1dc6a1f45 | |||
| 0fd412e426 | |||
| 3d0f82cbd4 | |||
| 68942c9919 | |||
| d5370b126d | |||
| 15fb7fca81 | |||
| b90baa257c | |||
| d0088fc922 | |||
| 2b15530a57 | |||
| 132f9f7467 | |||
| 7be4f59f0b | |||
| d3a2129967 | |||
| 6715c97599 | |||
| 75791783d8 | |||
| 6944d505f1 | |||
| 754f1e3b33 | |||
| 2f7005590c | |||
| 67c3345fd2 | |||
| 7f290d220d | |||
| c2acee7a1d | |||
| e964abaa4b | |||
| 3d0926dcaf | |||
| 3ee1605ed3 | |||
| 0c8fd36ef8 | |||
| 39ea801fbe | |||
| c2bf5c0ea8 | |||
| eed1ac0290 | |||
| 77ae596d2e | |||
| f79241f56f | |||
| b969bb36d6 | |||
| 6efbac4598 | |||
| 4b2f3b1bb3 | |||
| 057729f830 | |||
| 8b5e05f5a9 | |||
| ee10b63fe7 | |||
| e34d39fdee | |||
| 5c47fb69ad | |||
| 61faf6f493 | |||
| 665c63af4b | |||
| 78b2924fe1 | |||
| 1fb712c76d | |||
| be25a7a3f5 | |||
| 6ffafe7536 | |||
| 00e18d66b5 | |||
| cd3bdf0d5d | |||
| d6756ea5e6 | |||
| 3f8afcb9d7 | |||
| 4ab1ed5132 | |||
| 7d1463da0d | |||
| 4a80e38f19 | |||
| 20cd21789b | |||
| 8961cbd20a | |||
| a2928a8789 | |||
| 9d5a8e4137 | |||
| 6e9e38776f | |||
| 3a22ff388d | |||
| b695c4c88c | |||
| 88e5213326 | |||
| 451a617b13 | |||
| ed099a093d | |||
| 5b78e608f0 | |||
| f303a815f7 | |||
| 42ab63a03b | |||
| 128e55e448 | |||
| 39039081ee | |||
| dfc91a651b | |||
| 0361646e1a | |||
| 047ce3bc42 | |||
| a774be59f4 | |||
| 7b726ef6ec | |||
| 503efa4f82 | |||
| 538e0ce665 | |||
| 4147f6623c | |||
| 9d780aa910 | |||
| 59b51e8aad | |||
| c7a7a4333b | |||
| 98ff478fe9 | |||
| 53ef06f565 | |||
| 9a6615c356 | |||
| 498c73c004 | |||
| 43292555cd | |||
| b792c946c5 | |||
| 9fe5d198d1 | |||
| d282470efa | |||
| 153808358a | |||
| 17a26b2691 | |||
| e7e78f0d64 | |||
| bcbd1b74bc | |||
| 8d07ccd663 | |||
| 6358a2263c | |||
| d7881d2d3f | |||
| 58392ace7c | |||
| 582594a6d6 | |||
| 356b7512c8 | |||
| ba91900b89 | |||
| 4aa9e88238 | |||
| 5bec3fbbb6 | |||
| 2f23c13528 | |||
| 9ba2d09ee3 | |||
| 65c09bdbae | |||
| 302804cc4e | |||
| fe064efdb9 | |||
| 16af0b9592 | |||
| 4ac4a119e4 | |||
| ad1f3e996b | |||
| b6ba440410 | |||
| 7d20f3e895 | |||
| 5fe2e6ec42 | |||
| ef71d55c13 | |||
| a3073c69b2 | |||
| 8e7d429379 | |||
| 755b5cbe01 | |||
| fe47e6bc7b | |||
| aeb54d98d1 | |||
| 4735933d61 | |||
| ec5c92d4fd | |||
| fb10a1dc04 | |||
| 2901a28fcb | |||
| 047827fd86 | |||
| e23fd9495e | |||
| 10d63ff8e6 | |||
| f8149321f2 | |||
| a581e454ae | |||
| 342c2027d8 | |||
| fade9f51ea | |||
| b6930b45a4 | |||
| e166e969cb | |||
| 507f68aa13 | |||
| a2672bdc5b | |||
| 9303235434 | |||
| eafd863a32 | |||
| 1125715371 | |||
| 31156f4914 | |||
| 0185879943 | |||
| 9cd4b33020 | |||
| 758a5724e9 | |||
| 276433d635 | |||
| 7672531cdc | |||
| ec5f80e47f | |||
| da58a59f70 | |||
| 2796487b30 | |||
| dcea401ec2 | |||
| 25d851cc67 | |||
| 0f03edc8ef |
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||||
|
"categories": { "correctness": "off" },
|
||||||
|
"ignorePatterns": ["src/**/*.test.ts", "src/conformance/property-harness.ts"],
|
||||||
|
"rules": {
|
||||||
|
"eslint/max-lines-per-function": ["error", { "IIFEs": true, "max": 52, "skipBlankLines": false, "skipComments": false }]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,350 +1,182 @@
|
|||||||
# Working in this repo
|
# Working in this repo
|
||||||
|
|
||||||
Decisions a reader would otherwise relitigate, and the rules for every collaborator, human or
|
The rules for every collaborator, human or agent, and an index of the decisions a reader would
|
||||||
agent. Using the library: `README.md`. What is still to build: `todo.md`.
|
otherwise relitigate. Using the library: `README.md`. What is still to build: `todo.md`.
|
||||||
|
|
||||||
## 1. Three formats, ADF is the hub
|
## Decisions
|
||||||
|
|
||||||
ADF, one markdown flavour, one HTML dialect. Six directions exposed, but markdown↔HTML compose
|
In `docs/decisions.md`:
|
||||||
through ADF: four conversions exist to keep correct — never write a fifth. No fourth format, ever;
|
|
||||||
each one doubles the directions.
|
|
||||||
|
|
||||||
## 2. The round-trip is the product
|
- Plain markdown is a flavour of the grammar
|
||||||
|
- The round-trip is the product
|
||||||
|
- Markdown in is a canonical fixpoint
|
||||||
|
- Equality is editor-normal
|
||||||
|
- Unknown nodes ride the carry
|
||||||
|
- Foreign HTML sorts three ways
|
||||||
|
- Names stay text
|
||||||
|
- Directives under `!adf:`
|
||||||
|
- CommonMark is a subset
|
||||||
|
- Tables
|
||||||
|
- Links
|
||||||
|
- Ids stay site-local
|
||||||
|
- Plain task ids come from position
|
||||||
|
- A callout title keeps its link targets
|
||||||
|
- The plain flavour's spellings
|
||||||
|
- The HTML dialect
|
||||||
|
- No runtime dependencies
|
||||||
|
- Standards ship as data
|
||||||
|
- fast-check
|
||||||
|
- Any ES2022 engine
|
||||||
|
- ESM only
|
||||||
|
- One built entrypoint
|
||||||
|
- Public on npm
|
||||||
|
- The formats are API
|
||||||
|
- The code list
|
||||||
|
- Which code a cause takes
|
||||||
|
- `message` and `path`
|
||||||
|
- Publish on a version bump
|
||||||
|
- Docs describe the release being built
|
||||||
|
- No schema validation
|
||||||
|
- The gate runs on Deno and Bun
|
||||||
|
- The gate installs the tarball
|
||||||
|
- Firefox reads the build
|
||||||
|
- The coverage floors
|
||||||
|
- The size ratchet
|
||||||
|
- Properties on a fixed seed
|
||||||
|
- The CommonMark suite checks three ways
|
||||||
|
- The flavour spec is read as a source
|
||||||
|
- The node tables answer to Atlassian's schema
|
||||||
|
- Nothing recurses unbounded
|
||||||
|
- Nothing spreads an unbounded array
|
||||||
|
- A retry loop checks its own termination
|
||||||
|
- Readers scan by index
|
||||||
|
- The spelling memo
|
||||||
|
- Cost fixes are measured, never timed
|
||||||
|
- Only the hard break holds a raw newline
|
||||||
|
- Emphasis follows CommonMark's matching
|
||||||
|
- Readable spellings take the `try` prefix
|
||||||
|
- The attribute vocabulary is ADF's
|
||||||
|
- The source parts by ADF and format
|
||||||
|
|
||||||
`markdownToAdf(adfToMarkdown(doc))` and `htmlToAdf(adfToHtml(doc))` must equal `doc` — anything
|
## 1. Nothing about any consumer
|
||||||
less silently destroys content an editor could not represent, in a document it did not author.
|
|
||||||
When losslessness and readability conflict, losslessness wins.
|
|
||||||
|
|
||||||
The other direction is a canonical fixpoint, not byte-identity: human markdown normalizes, the way
|
|
||||||
back yields the library's canonical spelling, and that spelling round-trips byte-identically —
|
|
||||||
where there is a way back. CommonMark spells some things the flavour has no escape for — a link
|
|
||||||
destination or title holding a backslash or newline, a paragraph opening with a code span whose
|
|
||||||
backticks read back as a fence — so a parse succeeding does not imply a spellable document;
|
|
||||||
`corpus/commonmark-spec/exceptions.json` names those.
|
|
||||||
|
|
||||||
"Equals" is structural equality over editor-normal ADF — adjacent text nodes with identical marks
|
|
||||||
merged, JSON number semantics, an empty attrs object, marks array or content array the absent
|
|
||||||
key — the only domain markdown can restore.
|
|
||||||
|
|
||||||
Round-trip equality is a property tested over a corpus, not a claim made in prose.
|
|
||||||
|
|
||||||
## 3. Unknown input policy
|
|
||||||
|
|
||||||
- Unknown ADF node: carried opaquely — raw JSON rides a dedicated syntax in both formats and
|
|
||||||
restores to a deep-equal node. The round-trip holds for documents newer than the library. So
|
|
||||||
does a known node no section spells where it stands: a markdown serializer spells a node by type
|
|
||||||
without checking its position, and refusing loses a document ADF itself keeps in an
|
|
||||||
`unsupportedBlock`. Where a container's own spelling cannot hold the child it has — a
|
|
||||||
`bulletList` outside `listItem`, a `codeBlock` outside text — the error result names that
|
|
||||||
instead.
|
|
||||||
- Unmappable foreign HTML element: error result naming the element — never a silent drop.
|
|
||||||
- Bare `@name` / `:smile:` in typed text: stays a text node. Only directives produce
|
|
||||||
mention/emoji/media nodes; resolving names to ids needs I/O, which is the consumer's job.
|
|
||||||
|
|
||||||
## 4. The flavour
|
|
||||||
|
|
||||||
- Directives, one grammar for everything markdown lacks: `:::panel info` … `:::` blocks,
|
|
||||||
`:mention[@Mikael]{id=5b10a2}` inline. Prior art: CommonMark's generic-directives proposal.
|
|
||||||
- Plain CommonMark is a subset, with carve-outs (`spec/flavour.md`): literal text shaped like a
|
|
||||||
directive, a pipe table or a `~~` pair is claimed — plus one image gap.
|
|
||||||
- Tables: one header row plus plain inline cells → pipe table; anything richer → directive form.
|
|
||||||
- Identity-bearing nodes carry their ids in attributes; a document is only portable within its
|
|
||||||
site — accepted.
|
|
||||||
- The HTML dialect mirrors this: semantic elements, stable `adf-*` classes, `data-*` for what HTML
|
|
||||||
cannot express, text always escaped. No stylesheet ships.
|
|
||||||
|
|
||||||
## 5. Dependencies
|
|
||||||
|
|
||||||
`dependencies` is empty. A runtime dependency enters only through a decision entry here stating
|
|
||||||
why ~20 lines of own code cannot do the job, who maintains it, and what auditing it costs. So the
|
|
||||||
CommonMark and HTML parsers are written in this repo. A table a standard fixes is data rather than
|
|
||||||
a dependency: HTML5's 2125 semicolon-terminated character references ship packed in their own
|
|
||||||
module, so entity decoding is complete without one. The CommonMark spec suite is the same shape of
|
|
||||||
data and ships vendored at `corpus/commonmark-spec/` rather than as the `commonmark-spec` dev
|
|
||||||
dependency — that package is CommonJS-only, and Renovate auto-bumping a spec version would silently
|
|
||||||
point the vendored exception list's example numbers at a renumbered suite. A spec bump is a
|
|
||||||
deliberate re-pin, exceptions re-derived by hand beside it. Atlassian's ADF JSON Schemas ship
|
|
||||||
vendored the same way, at `spec/adf-schema/`, rather than as the `@atlaskit/adf-schema` dev
|
|
||||||
dependency — CommonJS-only, some fifty packages with React among them, and a release most days for
|
|
||||||
Renovate to automerge — re-pinned by hand when a payload or a report shows the need.
|
|
||||||
`devDependencies`: few, each earning its keep; they never reach a consumer.
|
|
||||||
|
|
||||||
## 6. The package contract
|
|
||||||
|
|
||||||
- Runs on any ES2022 engine, not only Node — a browser as readily as a server. The shipped source
|
|
||||||
is ECMAScript and nothing else: no host import, no host global, no DOM. `tsconfig.build.json` is
|
|
||||||
that gate, typechecking and emitting the shipped files alone, so `node:fs`, `process` and an
|
|
||||||
ES2024 method are compile errors here rather than a consumer's crash there. The standard is the line, never an
|
|
||||||
engine list: one implementing it in part — Hermes is the live doubt, on §10's property escapes
|
|
||||||
and on lookbehind — is out of scope rather than a bug. Node's test runner, the corpus reads and
|
|
||||||
the build are the repo's own,
|
|
||||||
never the library's, and `engines.node` states the floor the shipped JavaScript needs — `>=18` —
|
|
||||||
never the higher one those repo-only tools want.
|
|
||||||
- ESM only — no CommonJS build, no dual-package hazard.
|
|
||||||
- One entrypoint: built JavaScript, `.d.ts` beside it. Do not add a TypeScript-source entrypoint —
|
|
||||||
Node refuses to type-strip under `node_modules` (`ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`),
|
|
||||||
so it cannot serve an npm consumer.
|
|
||||||
- Published to public npmjs as `@larvit/adf-codec`. Public source: the Gitea repo
|
|
||||||
goes public, LICENSE in place, before the first publish.
|
|
||||||
- Exact versions: `save-exact=true` in `.npmrc`.
|
|
||||||
|
|
||||||
## 7. Nothing about any consumer
|
|
||||||
|
|
||||||
No Jira client, no HTTP, no REST shapes, no issue keys, no actual consumer named anywhere. Design
|
No Jira client, no HTTP, no REST shapes, no issue keys, no actual consumer named anywhere. Design
|
||||||
against the README's personas.
|
against the README's personas.
|
||||||
|
|
||||||
## 8. Semver: the formats are API
|
## 2. Release automation
|
||||||
|
|
||||||
The emitted markdown and HTML are contracts. After 1.0: previously-emitted output parsing
|
- The bump commit renames `CHANGELOG.md`'s `## Unreleased` to the version.
|
||||||
differently, or not at all, is MAJOR; new syntax while old output still round-trips is MINOR.
|
- Exact versions: `save-exact=true` in `.npmrc`.
|
||||||
Pre-1.0, normal 0.x rules.
|
|
||||||
|
|
||||||
The error surface is a contract too. `ConvertError` is `{ code, message, path, position? }` — the
|
|
||||||
code from a closed list a consumer may switch exhaustively, the message free text, the path the
|
|
||||||
node's place from the document root, the position where a parse read the refusal in its input.
|
|
||||||
A message names the violation, not the rule alone — a rule by itself states a truth the reader
|
|
||||||
must invert before it reads as a failure — and where the flavour's claim refuses ordinary prose it
|
|
||||||
names the escape that unclaims the form claimed: `\:::` for a directive line, `\|` for every pipe
|
|
||||||
row, `\:` for an inline directive.
|
|
||||||
Adding, removing or renaming a code is breaking, so a milestone meeting a new failure cause
|
|
||||||
reuses a code where one fits; the list is complete at `0.1.0`. A code names the
|
|
||||||
cause; where one cause recurs across node types, across one mark's attributes or across
|
|
||||||
directions, one code covers them all and
|
|
||||||
`path` and `message` say which — `unsupported-nesting-depth` is the 500-level guard whichever
|
|
||||||
direction hits it, `unspellable-link` the destination and the title alike. Where two codes stay
|
|
||||||
apart, the line between them is what they name: `unspellable-character` is a character CommonMark
|
|
||||||
rewrites wherever text holds it, `unspellable-whitespace` the newline no inline directive's
|
|
||||||
content slot spans, in either direction. A claim code names the spelling claimed, never the node that spelling would have built:
|
|
||||||
a malformed `:::table` is a `malformed-directive`, and an alignment colon a `malformed-pipe-table` —
|
|
||||||
the flavour's own delimiter row is `-` runs, so the grammar refuses the colon rather than ADF's
|
|
||||||
missing column model doing it. A refusal no spelling recovers from is a gap in the flavour rather
|
|
||||||
than a code: give the flavour the spelling and the code goes, which the freeze is the last moment
|
|
||||||
for. A cause the carry answers gets no code: a mark no
|
|
||||||
spelling writes rides the carry with its node. A directive whose name reads back to no node is
|
|
||||||
`unknown-directive-name` rather than a claim code — the spelling is well formed, and telling that
|
|
||||||
apart from a typo is what a consumer switches on when a later MINOR gives the name meaning. A
|
|
||||||
reserved name is a known name, so never that code, and the two the flavour reserves part on form:
|
|
||||||
a form the grammar does not have is a claim code — `::adf`, whose carry is the fence — and a
|
|
||||||
well-formed form in the wrong place is `unsupported-node-shape`, `::listBreak` parting anything
|
|
||||||
but two adjacent lists of one type. What
|
|
||||||
the grammar itself refuses stays a claim code, key order among it; a well-formed directive the
|
|
||||||
node tables refuse — an attribute a node does not hold or spells elsewhere, a value outside its
|
|
||||||
kind or its canonical spelling, an argument or a body its content model does not take — is
|
|
||||||
`unsupported-node-shape`, the emitter's code for the same mismatch read the other way — one code
|
|
||||||
across both directions for good, since the call site knows which direction it called and parting
|
|
||||||
them after `0.1.0` is MAJOR. `unmappable-html` names the version rather than the element: this one
|
|
||||||
converts no raw HTML, so at `0.3.0` the mapped elements stop erroring and the code stays for what
|
|
||||||
no ADF node carries. A refusal found before its path is known — the block walk's, a directive
|
|
||||||
reader's — is a `ConvertFault`, the code and message alone; the node walk attaches the path as it
|
|
||||||
descends, so a document reports its first error in document order. `not-an-adf-document` carries
|
|
||||||
the document's own path throughout: eight of the guard's nine branches read the document's own
|
|
||||||
shape, and threading a path to the ninth — a malformed node anywhere in the tree — wants the
|
|
||||||
manual stack §11's no-recursion rule forces, whose empty half no input reaches. The message names
|
|
||||||
the violation instead. Depth is not one of the nine: `adfDocumentFault` returns the code with the
|
|
||||||
message, so an attribute value past 500 levels is `unsupported-nesting-depth` from the emitter as
|
|
||||||
it already is from the parser, both directions refusing the same value. A node's attribute is
|
|
||||||
counted from the value itself, never from the `attrs` object holding it; a mark's is counted three
|
|
||||||
levels in, because the block directive spells the whole mark set as one JSON attribute and the
|
|
||||||
parser reads the value at the bottom of array, mark and `attrs`. `isAdfDocument` is true for a depth fault:
|
|
||||||
a deep document is a document, as the 2000-level blocks and the 600-deep marks the guard already
|
|
||||||
waves through are, and depth is the walks' answer rather than the shape's. A non-finite number
|
|
||||||
stays parted where depth is joined: the parse says `unsupported-node-shape` because the markdown is
|
|
||||||
at fault, the emit `not-an-adf-document` because the input is, and unlike depth nothing round-trips
|
|
||||||
inconsistently between them.
|
|
||||||
|
|
||||||
`position` is the parse side's alone: an emitter reads no source, so an emit error carries `path`
|
|
||||||
and nothing more. It is `{ line, offset }` at the start of the line the block holding the refusal
|
|
||||||
begins on — the offset indexing the string the caller passed, the line counted from 1 — minted by
|
|
||||||
the block walk and attached as results return, so the innermost block wins, the emitter's own
|
|
||||||
refusals the parser re-enters for the CommonMark spelling included.
|
|
||||||
|
|
||||||
A parse names a position for every refusal it returns, so the type says so rather than the prose:
|
|
||||||
`Result<T, E extends ConvertError = ConvertError>`, and a direction reading a source returns
|
|
||||||
`Result<T, ParseError>` — `ConvertError` with `position` required. An optional field a direction
|
|
||||||
always fills is a branch a consumer cannot take, and the `!` §11 bans is how they take it anyway.
|
|
||||||
`htmlToAdf` inherits this at `0.3.0`; the composed `markdownToHtml` and `htmlToMarkdown` keep the
|
|
||||||
wide `Result<T>`, since half their refusals come from an emit stage that read no source.
|
|
||||||
|
|
||||||
## 9. Release automation
|
|
||||||
|
|
||||||
- `package.json` version on `main` is the source of truth. CI on `main`: tests green and version
|
|
||||||
differs from npm → publish and tag `vX.Y.Z`. No bump, no deploy; the bump is each shipping PR's
|
|
||||||
deliberate semver judgment. `publish.sh` is that job, and `private: true` stops it before it
|
|
||||||
reads the token, so the pipeline is live and silent until the maintainer's first bump drops the
|
|
||||||
field.
|
|
||||||
- The publish and the tag each observe their own end state — the version on npm, the tag on the
|
|
||||||
remote — and neither gates the other, so a run that dies between them converges on the next push
|
|
||||||
to `main` rather than leaving npm ahead of the tags. An unanswered registry reads the same as an
|
|
||||||
unpublished version, which npm's own duplicate rejection is what catches. The job rebuilds rather
|
|
||||||
than taking the gate's `dist`: the lockfile is committed, the image is patch-pinned and `tsc` is
|
|
||||||
deterministic, so the two builds agree, and promoting an artifact would make the release path
|
|
||||||
depend on a store that the gate would then have to keep.
|
|
||||||
- Renovate watches devDependencies, Docker pins and action tags; automerges everything on green CI.
|
- Renovate watches devDependencies, Docker pins and action tags; automerges everything on green CI.
|
||||||
- Docker images pin the full patch version (`node:24.19.0-alpine3.24`, never `node:24`), as
|
- Docker images pin the full patch version (`node:24.19.0-alpine3.24`, never `node:24`), as
|
||||||
specific as the publisher tags: `oven/bun:1.4.0-alpine` pins Bun's patch and leaves the base
|
specific as the publisher tags: `oven/bun:1.4.0-alpine` pins Bun's patch and leaves the base
|
||||||
floating because Bun publishes nothing narrower. Actions pin semver tags.
|
floating because Bun publishes nothing narrower. Actions pin semver tags.
|
||||||
|
|
||||||
## 10. Tests first, in Docker
|
## 3. Tests first, in Docker
|
||||||
|
|
||||||
Test for the behaviour wanted first, then implement until green. `node --test`, beside the code.
|
Test for the behaviour wanted first, then implement until green. `node --test`, beside the code.
|
||||||
Node, tsc and npm never run on the host — only via the pinned images (§9). Tests are independent,
|
Node, tsc and npm never run on the host — only via the pinned images (§2). Tests are independent,
|
||||||
coverage does not decline, containers are torn down after a run.
|
containers are torn down after a run. A test reaches only for what Node's, Deno's and Bun's `node:`
|
||||||
|
shims all carry.
|
||||||
|
|
||||||
The gate runs that same suite under Deno and Bun as well as Node, the three images pinned alike,
|
Every leg announces its name and, where a container is in play, the image, before it runs and its
|
||||||
and neither extra leg is Node's proof twice. Deno refuses an extensionless or directory specifier,
|
elapsed time after, `publish.sh` alongside `ci.sh`, so a long run reads as progress rather than as
|
||||||
so it holds the module graph to the fully-spelled form a browser can load; Bun runs
|
a hang. A leg added later owes the same marker, and a function a leg reaches chains its statements
|
||||||
JavaScriptCore, the one engine of the three that is not V8, where the Unicode property escapes
|
with `&&`, because the `||` that captures the leg's status suspends `set -e` for everything it
|
||||||
emphasis matching leans on can disagree. Both refuse a run matching no test, so Node's is the only
|
calls. A leg whose output is both streamed and grepped keeps the copy in a `mktemp`
|
||||||
vacuous-green guard, and a test may reach only for what all three `node:` shims carry — the price
|
file: `tee /dev/stderr` reopens fd 2, and under `./ci.sh > log 2>&1` the two offsets punch NUL
|
||||||
of proving those engines over the corpus rather than over a smoke import.
|
holes through each other's lines.
|
||||||
|
|
||||||
The gate then packs the build and installs the tarball under `package-tests/`, so `files`,
|
`PROPERTY_RUNS=<runs>` raises the property runs and randomizes the seed for local digging. The
|
||||||
`exports` and `types` are proved on the artifact that ships rather than on the source tree a
|
generators and run parameters properties share live in `src/conformance/property-harness.ts`,
|
||||||
self-reference would resolve against. `consumer.ts` typechecks the emitted `.d.ts` from outside
|
outside the build and coverage.
|
||||||
`tsconfig.build.json` — declaration emit leaves the `.ts` specifiers
|
|
||||||
`rewriteRelativeImportExtensions` rewrites in the JavaScript, and this is what says a consumer's
|
|
||||||
resolver maps them, under `NodeNext` alone; a `.d.ts` reader that is not `tsc` stays unproven.
|
|
||||||
`node-floor.js` round-trips the installed package under a Node pinned to `engines.node`'s floor.
|
|
||||||
|
|
||||||
A fourth engine reads the build rather than the source: a headless Firefox loads `dist/index.js`
|
Each `- ` bullet in `spec/flavour.md`'s `## Block nodes`, `## Inline nodes` and `## Marks` declares
|
||||||
over HTTP and converts the round-trip, normalization and error fixtures — the `commonmark-spec`
|
the nodes named before its first em dash, with the attributes following `Attributes: ` — a
|
||||||
sort is the Node suite's to check — which is §6's browser half and the only SpiderMonkey
|
parenthesized value set reading `string`; fenced examples are skipped. Keep prose out of a bullet.
|
||||||
there is — the gate's other three engines are two V8s and a JavaScriptCore that is not Safari's.
|
|
||||||
A WebDriver session is what carries a verdict back out, the driver and the page's server sharing
|
|
||||||
one network namespace so each is the other's `127.0.0.1`; `--headless --screenshot` has no such
|
|
||||||
channel, and loading `dist/index.js` in a globals-stripped realm buys one by not running a browser.
|
|
||||||
The leg re-checks the conversions and nothing else — each fixture's emitted markdown, its parsed
|
|
||||||
document, its error code — leaving the corpus's pairing, uniqueness, source positions and
|
|
||||||
byte-level equality to the Node suite that owns them.
|
|
||||||
|
|
||||||
The floors live in the `test` script, so `npm test` and the gate are one path: 100% of lines and
|
## 4. Code rules
|
||||||
functions, and a branch floor that only ever moves upward. It sits below 100 because the guards
|
|
||||||
`noUncheckedIndexedAccess` and ADF's optional keys force — `?? []`, `?? {}`, `?.`, an index
|
|
||||||
compared against `undefined` — have a half no valid document reaches.
|
|
||||||
|
|
||||||
The corpus, all checked in: hand-built fixtures per node and combination; real sanitized ADF from
|
- Two-space indent, English everywhere. Alphabetical order wherever order carries no meaning,
|
||||||
live Atlassian APIs; the CommonMark spec suite against `markdownToAdf` and `markdownToHtml`.
|
keyed on the name a line introduces: an import sorts on its first binding, type imports ahead of
|
||||||
|
value imports, so moving or renaming a module reorders nothing.
|
||||||
`spec/flavour.md` is read as a source too, so the node tables cannot drift from the prose they
|
|
||||||
copy: each `- ` bullet in `## Block nodes`, `## Inline nodes` and `## Marks` declares the nodes
|
|
||||||
named before its first em dash, with the attributes following `Attributes: ` — a parenthesized
|
|
||||||
value set reading `string` — and must equal the tables in `adf/`. Keep prose in those sections out
|
|
||||||
of a bullet; fenced examples are skipped. It guards the attributes alone: nodes that differ in
|
|
||||||
content model share a bullet, and the argument attribute is spelled ahead of `Attributes: `, so
|
|
||||||
both answer to the round-trip corpus and to nothing else where a node has no fixture.
|
|
||||||
|
|
||||||
The tables answer to Atlassian's schema too (§5): for every node and mark they spell, the attribute
|
|
||||||
names and kinds equal what `full.json` and `stage-0.json` hold between them. Value sets stay
|
|
||||||
documentation, since any value round-trips. What the schema holds and the tables do not spell is
|
|
||||||
pinned by name — an attribute as a gap, a type as carried — so a re-pin adding either goes red until
|
|
||||||
someone spells it or pins it.
|
|
||||||
|
|
||||||
## 11. Code rules
|
|
||||||
|
|
||||||
- Two-space indent, strict TypeScript, English everywhere. Alphabetical order wherever order
|
|
||||||
carries no meaning.
|
|
||||||
- Failures are values: everything returns
|
|
||||||
`Result<T>` — `{ ok: true; value } | { ok: false; error: ConvertError }` — nothing throws.
|
|
||||||
`try/catch` only wrapped tightly around a call that genuinely throws, converted to a result on
|
|
||||||
the spot. A reader with no path to name returns `Read<T>` instead, the same two arms over a
|
|
||||||
`ConvertFault`, and `faulted` attaches the path where the walk knows it.
|
|
||||||
- Only the hard break's inline segment holds a raw newline — every other spelling escapes one or
|
|
||||||
refuses it — which is how the whitespace carry finds a line edge.
|
|
||||||
- Emphasis is spelled against CommonMark's matching, never flanking alone: a delimiter run in text
|
|
||||||
escapes wherever CommonMark could open or close with it, leaving the emitter's own delimiters the
|
|
||||||
only ones in play, and a pair that matching hands to another delimiter rides the carry instead.
|
|
||||||
`matchEmphasis` transcribes the reference `process_emphasis` line for line, and its closer walk and
|
|
||||||
opener search stay whole: broken into named steps they drift from the algorithm being faithful is
|
|
||||||
the whole point of.
|
|
||||||
- A readable spelling tried ahead of a general one — a CommonMark block, the image, the pipe
|
|
||||||
table, a pipe cell — gives way with `undefined` for every shape it cannot spell, and fails only
|
|
||||||
where the general form fails on the same node. Refusing there refuses a document the general
|
|
||||||
form spells, so a refusal the general form does not share belongs in the general form or
|
|
||||||
nowhere — save the nested list a tight spelling would swallow, whose refusal the
|
|
||||||
tight-versus-blank answer owns (`todo.md` 2b).
|
|
||||||
- Nothing recurses unbounded: the guards walk iteratively, and blocks, marks and JSON values — an
|
|
||||||
attribute's and a carried node's alike — are all held to 500 levels, so a deep document is a
|
|
||||||
`Result` rather than the stack overflow that waits near 2000.
|
|
||||||
- A reader takes the text and an index — a sticky regex whose `lastIndex` the caller sets on the
|
|
||||||
line before it reads, `indexOf` — never a fresh slice per character, and a per-character walk
|
|
||||||
hoists the scan that does not vary with the character. The pipeline persona feeds documents
|
|
||||||
nobody typed, and a megabyte through a quadratic walk is a minute rather than a millisecond.
|
|
||||||
- No casts: `as`, `as unknown as`, non-null `!`. A boundary owes a type guard validating the
|
- No casts: `as`, `as unknown as`, non-null `!`. A boundary owes a type guard validating the
|
||||||
fields it claims (`isAdfDocument`); past it everything is typed. Make invalid states
|
fields it claims (`isAdfDocument`); past it everything is typed. Make invalid states
|
||||||
unrepresentable.
|
unrepresentable.
|
||||||
- `src/adf/` holds ADF's own knowledge and imports no format. Each format directory (`markdown/`,
|
- Failures are values: everything returns `Result<T>`, nothing throws. `try/catch` only wrapped
|
||||||
`html/`) parts into `emit/` (ADF→format) and `parse/` (format→ADF), its root holding what both
|
tightly around a call that genuinely throws, converted to a result on the spot. A reader with no
|
||||||
directions read. A construct's reader lives in that root beside the regex the emitter escapes
|
path to name returns `Read<T>`, and the walk attaches the path where it knows it.
|
||||||
against, so the two cannot drift; a reader with no emit counterpart goes in `parse/`, unless it is
|
|
||||||
part of a construct the root already holds — a grammar stays in one file rather than splitting
|
|
||||||
across the seam. A rule both
|
|
||||||
directions must answer alike — whether a list marker interrupts a paragraph — is one function
|
|
||||||
there too, never a copy per direction, however conservative the copy would be. Where the rule is
|
|
||||||
the emitter's own choice, input consults it rather than restating it: the parser asks
|
|
||||||
`commonMarkSpelling` which form the emitter picks, so no fixture the emitter writes can be
|
|
||||||
refused, and a spelling the emitter refuses gives its own error rather than a second name for it.
|
|
||||||
- The attribute vocabulary is ADF's: `adf/` walks it and narrows each value to its kind, and a
|
|
||||||
format spells the narrowed value. A spelling that re-checks the type is the check's second copy.
|
|
||||||
Reading a spelling back is the format's own: the reader sits beside the spelling it inverts, so
|
|
||||||
decode-respell-compare cannot drift, and each format writes its own — canonical JSON for a
|
|
||||||
number is the markdown flavour's choice, not ADF's.
|
|
||||||
- Explicit over implicit; descriptive names; no catch-all files (`utils`, `helpers`, `misc`); a
|
|
||||||
file does not repeat its directory in its name — `adf/document.ts`, never
|
|
||||||
`adf/adf-document.ts`.
|
|
||||||
- Reuse before adding; the smallest sufficient diff is the benchmark; no speculative generality —
|
- Reuse before adding; the smallest sufficient diff is the benchmark; no speculative generality —
|
||||||
a second consumer, or it goes.
|
a second consumer, or it goes.
|
||||||
|
- Explicit over implicit; descriptive names; no catch-all files (`utils`, `helpers`, `misc`); a file
|
||||||
|
does not repeat its directory in its name — `adf/document.ts`, never `adf/adf-document.ts`. A name
|
||||||
|
is the noun `spec/flavour.md` or ADF's schema uses for the thing.
|
||||||
|
|
||||||
## 12. Prose to a minimum
|
## 5. Prose to a minimum
|
||||||
|
|
||||||
Applies everywhere: comments, every markdown file in this repo (this one included), PR text.
|
Applies everywhere: comments, every markdown file in this repo (this one included), PR text.
|
||||||
|
|
||||||
- Default is no comment. One earns its single line only by naming an invariant, footgun or
|
- Default is no comment. One earns its single line only by naming an invariant, footgun or
|
||||||
external constraint the code cannot show — never restatement, history, absence or arrangement.
|
external constraint the code cannot show — never restatement, history, absence or arrangement.
|
||||||
A second line belongs in the commit message or a decision entry here.
|
A second line belongs in the commit message or a `docs/decisions.md` entry.
|
||||||
- Every prose comment in a diff is a review question; the default answer is delete.
|
|
||||||
- A doc paragraph says what the repo cannot say for itself, or it goes. The fix for a redundant
|
- A doc paragraph says what the repo cannot say for itself, or it goes. The fix for a redundant
|
||||||
one is deletion, not trimming. A false claim in any doc is a bug, fixed where found.
|
one is deletion, not trimming. A false claim in any doc is a bug, fixed where found.
|
||||||
- Published text — npm README, error messages, API docs — never references internal systems,
|
- Published text — npm README, error messages, API docs — never references internal systems,
|
||||||
tickets or repos.
|
tickets or repos.
|
||||||
|
|
||||||
## 13. Commits and PRs
|
## 6. Commits and PRs
|
||||||
|
|
||||||
One-line commit messages and PR titles; short PR summaries. No AI-attribution markers, ever.
|
One-line commit messages and PR titles; short PR summaries. No AI-attribution markers, ever.
|
||||||
|
|
||||||
## 14. Non-goals
|
## 7. The working loop
|
||||||
|
|
||||||
No wiki markup (§1), no network or filesystem I/O, no name→id resolution (§3), no ADF schema
|
A session works one chunk, starting from the first item in `todo.md` not waiting on an unmet "Lands
|
||||||
validation or exported validator — a refusal that keeps the round-trip is not schema validation,
|
after", and stops when that chunk merges, whatever it was asked to finish: a release is a chain of
|
||||||
so the one a spelled node carrying the same mark type twice earns stays, and input nesting a
|
sessions, so an instruction to work until a release is done names the chain, not the session. An
|
||||||
spelling inside its own kind (`*(*a*)*`) names that mark once, no shipped CSS (§4), no
|
open PR is a chunk already in flight, and finishing it is the session.
|
||||||
streaming APIs, no performance budget past §11's scanning rule — nothing here is tuned, and no
|
Per chunk:
|
||||||
figure is promised. A CLI is a later goal (`todo.md`), not a non-goal.
|
|
||||||
|
|
||||||
## 15. The working loop
|
1. Fresh worktree off updated `origin/main`; implement tests-first (§3).
|
||||||
|
|
||||||
One unchecked `todo.md` item per session, in the smallest PR-able chunk — split a big milestone
|
|
||||||
into sub-items in `todo.md` before starting it. A chunk running a little over or under that is not
|
|
||||||
worth deliberating; what matters is that nothing is left undone in the end. Per chunk:
|
|
||||||
|
|
||||||
1. Fresh worktree off updated `origin/main`; implement tests-first (§10).
|
|
||||||
2. Run the larv-review flow until it passes and CI is green. A reviewer launch states the latest
|
2. Run the larv-review flow until it passes and CI is green. A reviewer launch states the latest
|
||||||
gate result (commit and outcome); a reviewer does not re-run `ci.sh` or the tests when a
|
gate result (commit and outcome); a reviewer does not re-run `ci.sh` or the tests when a
|
||||||
result exists for the commit under review, or when the diff since that result cannot affect
|
result exists for the commit under review, or when the diff since that result cannot affect
|
||||||
it (docs-only) — re-run only what its own findings or fixes invalidate.
|
it (docs-only) — re-run only what its own findings or fixes invalidate.
|
||||||
3. Merge the PR (standing authorization, this repo only, granted through the `0.2.0` release —
|
3. Merge the PR (standing authorization, this repo only, granted by the maintainer through the
|
||||||
the maintainer, 2026-09-13), check the box in `todo.md` and move the item's text to
|
`0.2.0` release), report, stop.
|
||||||
`todo-history.md`, leaving its title behind, report, stop. The next chunk gets a fresh session.
|
|
||||||
|
|
||||||
Ask, don't guess: any choice where what the maintainer would pick is not near-certain gets asked,
|
Reserved for the maintainer whatever any rule here says: changing `version` in `package.json` (a
|
||||||
and the answer lands as a decision in this file. The confidence bar is very high — asking too
|
bump on `main` publishes, `docs/decisions.md` §Publish on a version bump — every release is the
|
||||||
often is the accepted cost, guessing wrong is not.
|
maintainer's) and the `NPM_TOKEN` secret.
|
||||||
|
|
||||||
Reserved for the maintainer, never the agent: changing `version` in `package.json` (a bump on
|
### Ask, don't guess
|
||||||
`main` publishes, §9 — every release is the maintainer's) and the `NPM_TOKEN` secret.
|
|
||||||
|
|
||||||
A continuous loop session (`/loop`) counts as a chain of sessions: one chunk per iteration, each
|
Any choice where what the maintainer would pick is not near-certain gets asked. The confidence bar
|
||||||
iteration starting by re-reading `AGENTS.md` and `todo.md` and trusting them over anything
|
is very high — asking too often is the accepted cost, guessing wrong is not.
|
||||||
remembered from earlier iterations. The loop session is a thin driver: each chunk's work runs in
|
|
||||||
a fresh-context subagent holding this file as its charter, and the driver only relays maintainer
|
An ask is a gap in `docs/decisions.md`, and its answer is the entry that closes it, landing there —
|
||||||
questions, runs the review flow, merges, and cleans up. The loop stops when only
|
never the instance alone; an answer that is a goal lands in the README, one that is a working rule
|
||||||
maintainer-reserved acts remain.
|
here. Before asking, name the class the question belongs to and the entries of that class; where
|
||||||
|
one already decides it, apply it without asking, and where it reads two ways on this input, that
|
||||||
|
reading is the ask. Never ask "A or B?": state the gap, the earlier entries of its class, the
|
||||||
|
nearest text, a candidate entry in that file's voice, and the instance it yields. An entry that
|
||||||
|
keeps collecting instances is wrong: rewrite it.
|
||||||
|
|
||||||
|
Which output the audience expects — README goal 5 — is settled by a reader panel rather than
|
||||||
|
asked: three fresh-context readers, one per README persona the conversion serves, each given only
|
||||||
|
`## Audience` and the input, writing what they expect before picking among outputs the goals
|
||||||
|
allow, rendered, shuffled, with no rationale and nothing saying what is implemented. Three agreeing
|
||||||
|
settle it; otherwise four more read, five of seven settle it, and less is a missing goal, asked.
|
||||||
|
The verdict lands in `docs/decisions.md`.
|
||||||
|
|
||||||
|
### Stated numbers
|
||||||
|
|
||||||
|
A stated number — 500 levels, the branch floor — is kept; a chunk that cannot keep it asks, naming
|
||||||
|
the number it can reach. A number the code needs and no entry states is a gap.
|
||||||
|
|
||||||
|
### The continuous loop
|
||||||
|
|
||||||
|
A `/loop` session counts as a chain of sessions, each iteration starting by re-reading `AGENTS.md`
|
||||||
|
and `todo.md` and trusting them over anything remembered from earlier iterations. The loop session
|
||||||
|
is a thin driver: each chunk's work runs in a fresh-context subagent holding this file as its
|
||||||
|
charter, and the driver only relays maintainer questions, runs the review flow, merges, and cleans
|
||||||
|
up. The loop stops when only maintainer-reserved acts remain.
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- **Breaking:** directives, the opaque carry among them (now `carry`), are spelled under an `!adf:`
|
||||||
|
prefix (`!adf:name … !adf:/name`, `!adf:name[content]{attrs}`, `!adf:name arg {attrs}`) in place
|
||||||
|
of the `:::`/`::`/`:name` forms: text holding an unescaped `!adf:` is claimed, and `adf` is an
|
||||||
|
ordinary code block language. Convert stored markdown per `MIGRATION.md`.
|
||||||
|
- **Breaking:** `unspellable-link` leaves `ConvertErrorCode`; a link whose `href` or `title` no
|
||||||
|
CommonMark escape spells is written as `!adf:link[text]{attrs}`.
|
||||||
|
- **Breaking:** some directive refusals carry `malformed-directive` where they carried
|
||||||
|
`unsupported-node-shape`, and an empty node's leaf and closed spellings swap which one parses;
|
||||||
|
`MIGRATION.md` lists each.
|
||||||
|
- **Breaking:** a link whose text holds another link keeps the inner link and leaves the outer
|
||||||
|
brackets literal text, where `0.1.0` split the outer link around it; see `MIGRATION.md`.
|
||||||
|
- Add `adfToPlainMarkdown` and `plainMarkdownToAdf`, a lossy pair converting ADF to and from
|
||||||
|
markdown GitHub, GitLab and Obsidian render: alerts, callouts, task lists, `==highlights==` and
|
||||||
|
pipe tables.
|
||||||
|
- Spell `rule`'s `color`, `style` and `weight`, `layoutSection`'s `columnRuleStyle` and a link's
|
||||||
|
`collection`, `id` and `occurrenceKey` directly where they rode the opaque carry.
|
||||||
|
- Fix an image inside another image's description: it flattens into the alt text, where it was
|
||||||
|
refused.
|
||||||
|
|
||||||
|
## 0.1.0
|
||||||
|
|
||||||
|
- First release: lossless conversion between ADF and an extended markdown flavour —
|
||||||
|
`adfToMarkdown`, `markdownToAdf` and `isAdfDocument`. Nothing throws, and every error carries a `code` from a
|
||||||
|
closed list.
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Migrating
|
||||||
|
|
||||||
|
## From `0.1.0` to `0.2.0`
|
||||||
|
|
||||||
|
Directives moved under the `!adf:` prefix. `0.2.0` reads `0.1.0`'s spelling without an error,
|
||||||
|
turning each directive into text and each carried node into an `adf` code block. Before `0.2.0`
|
||||||
|
reads any `0.1.0` markdown, convert what is stored or in flight (an open editor, a queue) with the
|
||||||
|
recipe below, and rewrite markdown your code writes or matches (templates, prompts, patterns) by
|
||||||
|
the tables below. Stored ADF needs no change.
|
||||||
|
|
||||||
|
### Convert markdown
|
||||||
|
|
||||||
|
Read it with `0.1.0` and write it with `0.2.0`, installed side by side:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install @larvit/adf-codec@0.2.0 adf-codec-0.1@npm:@larvit/adf-codec@0.1.0
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { adfToMarkdown } from '@larvit/adf-codec'
|
||||||
|
import { markdownToAdf as markdownToAdf010 } from 'adf-codec-0.1'
|
||||||
|
|
||||||
|
function migrateMarkdown(stored: string) {
|
||||||
|
const parsed = markdownToAdf010(stored)
|
||||||
|
return parsed.ok ? adfToMarkdown(parsed.value) : parsed
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Convert each document once: a second pass can return ok while turning the directives into text.
|
||||||
|
Stop `0.1.0` writing first, and record which documents are converted.
|
||||||
|
- A refusal carrying `position` is `0.1.0`'s parse, which refused that markdown before too. One
|
||||||
|
without is `0.2.0`'s emit: store the document `markdownToAdf010` read as ADF rather than keeping
|
||||||
|
the unconverted markdown.
|
||||||
|
|
||||||
|
### Spellings
|
||||||
|
|
||||||
|
| `0.1.0` | `0.2.0` |
|
||||||
|
| --- | --- |
|
||||||
|
| `:::panel info` … `:::`, the fence longer per nesting level | `!adf:panel info` … `!adf:/panel` at any depth |
|
||||||
|
| `::media {id=a type=file}` | `!adf:media {id=a type=file}` |
|
||||||
|
| `::taskItem TODO {localId=i}`: an empty `caption`, `decisionItem`, `paragraph` or `taskItem`, or an empty `heading` carrying `localId` | `!adf:taskItem TODO {localId=i}` then `!adf:/taskItem` |
|
||||||
|
| `:mention[@Mikael]{id=5b10a2}` | `!adf:mention[@Mikael]{id=5b10a2}` |
|
||||||
|
| the `adf` code fence and `:adf{json="…"}` | the `carry` code fence and `!adf:carry{json="…"}` |
|
||||||
|
| `\:` keeps a directive literal | `\!adf:` keeps a directive literal |
|
||||||
|
| `:adf{json="…"}` carrying a link for its `collection`, `id` or `occurrenceKey` | `!adf:link[text]{attrs}` |
|
||||||
|
|
||||||
|
A colon run and `:name[` are plain text now, and `adf` an ordinary code block language; text
|
||||||
|
holding an unescaped `!adf:` and a `carry` fence are claimed instead.
|
||||||
|
|
||||||
|
### Readings
|
||||||
|
|
||||||
|
Markdown the spelling table leaves alone, which `0.2.0` reads as a different document.
|
||||||
|
|
||||||
|
| Input | `0.1.0` | `0.2.0` |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| a link whose text already holds one (`[a<https://example.com/>b](/v)`) | marks every node the inner link does not, splitting the outer link around it | leaves the outer brackets literal text; write the pieces as separate links to keep them |
|
||||||
|
|
||||||
|
### Error codes
|
||||||
|
|
||||||
|
`unspellable-link` leaves `ConvertErrorCode`: a `switch` naming it stops compiling, and the link
|
||||||
|
it named converts.
|
||||||
|
|
||||||
|
| Input | `0.1.0` | `0.2.0` |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| a link whose `href` or `title` no CommonMark escape spells, on emit | `unspellable-link` | spells `!adf:link[text]{attrs}` |
|
||||||
|
| a leaf node given a body (`media`, `listBreak`) | `unsupported-node-shape` | `malformed-directive` |
|
||||||
|
| a node with a block body written as a leaf (`panel`) | `unsupported-node-shape` | `malformed-directive` |
|
||||||
|
| an empty node the `::taskItem` spelling row names, written as a leaf | parses | `malformed-directive` |
|
||||||
|
| an empty node the `::taskItem` spelling row names, written with a closer | `unsupported-node-shape` | parses |
|
||||||
@@ -4,9 +4,13 @@ Lossless conversion between **Atlassian Document Format** (ADF), an extended mar
|
|||||||
an HTML dialect.
|
an HTML dialect.
|
||||||
|
|
||||||
**Status: published — the markdown round-trip (`adfToMarkdown`, `markdownToAdf`); HTML at
|
**Status: published — the markdown round-trip (`adfToMarkdown`, `markdownToAdf`); HTML at
|
||||||
`0.3.0`.**
|
`0.2.0`.**
|
||||||
Plan: `todo.md`. Decisions: `AGENTS.md`. The flavour's grammar:
|
Plan:
|
||||||
[`spec/flavour.md`](spec/flavour.md).
|
[`todo.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/todo.md). Decisions:
|
||||||
|
[`docs/decisions.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/docs/decisions.md). Changes:
|
||||||
|
[`CHANGELOG.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/CHANGELOG.md). The lossless flavour's grammar:
|
||||||
|
[`spec/flavour.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/spec/flavour.md).
|
||||||
|
Upgrading from `0.1.0`: [convert your markdown first](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/MIGRATION.md).
|
||||||
|
|
||||||
## What it is for
|
## What it is for
|
||||||
|
|
||||||
@@ -18,6 +22,36 @@ one-directional and lossy. A consumer that shows a document and lets someone edi
|
|||||||
directions lossless — otherwise saving destroys the panels, mentions and attachments it could not
|
directions lossless — otherwise saving destroys the panels, mentions and attachments it could not
|
||||||
represent.
|
represent.
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
|
||||||
|
The most useful ADF conversion library available, judged by these goals, in priority order:
|
||||||
|
|
||||||
|
1. **Lossless, and every call returns a result, never a throw.**
|
||||||
|
2. **ADF is the hub.**
|
||||||
|
3. **Each format reads and writes as its standard says.**
|
||||||
|
4. **Our markdown is CommonMark, extended only where CommonMark has no spelling.**
|
||||||
|
5. **No surprises: output reads and edits the way its audience expects.**
|
||||||
|
6. **Lossy conversion drops form, never content.**
|
||||||
|
7. **Runs in any JavaScript engine, with no runtime dependencies and nothing to configure or connect.**
|
||||||
|
8. **Fast, and linear in the document's size.**
|
||||||
|
9. **Easy to find, and clear at a glance what it does.**
|
||||||
|
|
||||||
|
## Audience
|
||||||
|
|
||||||
|
Application developers embedding the library, in four personas. All four rely on the guarantees
|
||||||
|
below and on an error's `code` being a closed list; none may rely on an error message's wording,
|
||||||
|
which is free text.
|
||||||
|
|
||||||
|
- **Viewer/editor app** — shows a document, lets a human edit, posts it back. Relies on the
|
||||||
|
round-trip holding for whatever the site's editor wrote, unknown node types included, and on a
|
||||||
|
refusal arriving before the save rather than after.
|
||||||
|
- **Bot posting content** — turns generated markdown into ADF. Relies on plain CommonMark being
|
||||||
|
valid input, so nothing upstream has to learn a flavour.
|
||||||
|
- **Export/indexing tool** — converts ADF to markdown or HTML in bulk. Relies on readable output
|
||||||
|
and on every refusal being deterministic, so a document that fails fails the same way next run.
|
||||||
|
- **LLM/agent pipeline** — hands documents to a model as markdown and writes the edits back.
|
||||||
|
Relies on the round-trip and on markdown a reader half-knowing the lossless flavour can still edit.
|
||||||
|
|
||||||
## The shape
|
## The shape
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -27,7 +61,7 @@ npm install @larvit/adf-codec
|
|||||||
```ts
|
```ts
|
||||||
import { markdownToAdf } from '@larvit/adf-codec'
|
import { markdownToAdf } from '@larvit/adf-codec'
|
||||||
|
|
||||||
const result = markdownToAdf('# Release notes\n\n:::panel info\nShipped on Tuesday.\n:::\n')
|
const result = markdownToAdf('# Release notes\n\n!adf:panel info\nShipped on Tuesday.\n!adf:/panel\n')
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
send(result.value)
|
send(result.value)
|
||||||
} else {
|
} else {
|
||||||
@@ -36,25 +70,84 @@ if (result.ok) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Pure functions, no I/O, no configuration. ADF is the hub: markdown↔HTML compose through it.
|
Serves Goals 1, 2 and 7. Pure functions, each taking a whole document and returning a whole
|
||||||
|
result; no I/O, no configuration. `markdownToHtml` and `htmlToMarkdown` convert through ADF:
|
||||||
|
they keep only what ADF holds, and refuse what `markdownToAdf` or `htmlToAdf` refuses.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
adfToMarkdown(doc: AdfDocument): Result<string>
|
adfToMarkdown(doc: AdfDocument): Result<string>
|
||||||
markdownToAdf(markdown: string): Result<AdfDocument, ParseError>
|
markdownToAdf(markdown: string): Result<AdfDocument, ParseError>
|
||||||
isAdfDocument(v: unknown): v is AdfDocument
|
isAdfDocument(v: unknown): v is AdfDocument
|
||||||
|
|
||||||
adfToHtml(doc: AdfDocument): Result<string> // 0.3.0
|
adfToPlainMarkdown(doc: AdfDocument): Result<string>
|
||||||
htmlToAdf(html: string): Result<AdfDocument, ParseError> // 0.3.0
|
plainMarkdownToAdf(markdown: string): Result<AdfDocument, ParseError>
|
||||||
markdownToHtml(markdown: string): Result<string> // 0.3.0, via ADF
|
|
||||||
htmlToMarkdown(html: string): Result<string> // 0.3.0, via ADF
|
adfToHtml(doc: AdfDocument): Result<string> // 0.2.0
|
||||||
|
htmlToAdf(html: string): Result<AdfDocument, ParseError> // 0.2.0
|
||||||
|
markdownToHtml(markdown: string): Result<string> // 0.2.0
|
||||||
|
htmlToMarkdown(html: string): Result<string> // 0.2.0
|
||||||
```
|
```
|
||||||
|
|
||||||
`Result<T>` is `{ ok: true; value: T } | { ok: false; error: ConvertError }` — nothing throws.
|
`Result<T>` is `{ ok: true; value: T } | { ok: false; error: ConvertError }` — nothing throws.
|
||||||
|
|
||||||
|
## Plain markdown
|
||||||
|
|
||||||
|
Serves Goal 6. Plain markdown is a second flavour of the same grammar. `adfToPlainMarkdown` writes
|
||||||
|
markdown other tools render — GitHub, GitLab, Obsidian and the like — keeping the content and
|
||||||
|
dropping the rest: attributes, colours, layout, identity. Content is what a reader of the rendered
|
||||||
|
document sees or follows: its text, images and link targets. It refuses only
|
||||||
|
`not-an-adf-document`, `unsupported-document-version` and `unsupported-nesting-depth`, and writes
|
||||||
|
no directive.
|
||||||
|
|
||||||
|
`plainMarkdownToAdf` reads what `markdownToAdf` reads and refuses what it refuses, and reads the
|
||||||
|
conventions below as nodes, taking other tools' spellings too; a backslash keeps a marker as text:
|
||||||
|
`\==x==`, `> \[!NOTE]`, `- \[x]`. Markdown `adfToPlainMarkdown` wrote reads back and writes again
|
||||||
|
byte for byte; the document it came from does not come back.
|
||||||
|
|
||||||
|
To edit a document and save it back, use `adfToMarkdown` and `markdownToAdf`: saving what this pair
|
||||||
|
read replaces mentions, attachments and macros with text.
|
||||||
|
|
||||||
|
| ADF | Written | Read back |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `panel` | a GitHub alert, `> [!WARNING]`: info `NOTE`, note `IMPORTANT`, tip and success `TIP`, warning `WARNING`, error `CAUTION`, custom `NOTE` | `NOTE` info, `IMPORTANT` note, `TIP` tip, `WARNING` warning, `CAUTION` error, and Obsidian's: hint tip; success, check, done success; attention warning; danger, failure, fail, missing, bug, error error; any other word info — in any case; the rest of the marker's line is the first paragraph |
|
||||||
|
| `expand`, `nestedExpand` | Obsidian's folded callout, `> [!NOTE]- Title` | `-` or `+` after any word, the rest of the marker's line the title; a link reads `text (target)`, or its text alone where the text is the target with or without `mailto:`; an expand inside an expand is a `nestedExpand` |
|
||||||
|
| `taskList` | `- [x] Done`, `- [ ] Todo` | a bullet list whose every item is so marked, `[X]` too |
|
||||||
|
| `backgroundColor` | `==text==` | `==text==` on one line, the text touching both delimiters, bounded outside by whitespace, punctuation or a line edge, or touching a Han, Hangul, Hiragana, Katakana, Thai, Lao, Khmer or Myanmar character on either side, in the editor's default highlight `#f8e6a0` |
|
||||||
|
| `table` | a pipe table: the first row its header, a cell's blocks on one line, a span kept under its header by empty cells | — |
|
||||||
|
| `decisionList` | a bullet list | — |
|
||||||
|
| `mention`, `status`, `emoji`, `date` | their text: `@` kept, a mention with none `@` and its id, an emoji its `shortName` without, a date `2026-09-13` in UTC | — |
|
||||||
|
| `inlineCard`, `blockCard`, `embedCard` | a link to the card's URL, else its name | — |
|
||||||
|
| external `media` | `` in a block, `[alt](url)` inline | — |
|
||||||
|
| stored `media`, `mediaInline`, `extension`, `inlineExtension` | their `alt` or `text` | — |
|
||||||
|
| `layoutSection`, `bodiedExtension`, `bodiedSyncBlock`, `multiBodiedExtension`, `extensionFrame`, `caption`, a node this version does not know | its blocks or its text | — |
|
||||||
|
| `placeholder` | nothing | — |
|
||||||
|
|
||||||
|
- Content the document only references, with no text of its own to keep, leaves an italic note
|
||||||
|
naming it where it stood: `_(image not included)_` for stored media with no `alt`,
|
||||||
|
`_(link card not included)_` for a card with neither URL nor name, an extension with no `text`
|
||||||
|
its key, `_(jira-issues-table not included)_`, or `_(extension not included)_` without one, and
|
||||||
|
`_(synced block not included)_` for a `syncBlock`.
|
||||||
|
- `backgroundColor`, `code`, `em`, `link`, `strike` and `strong` stay; every other mark drops,
|
||||||
|
keeping its text, and so does a mark the flavour cannot spell where it stands.
|
||||||
|
- A newline in text is a hard break and in an expand's title a space, edge whitespace outside a
|
||||||
|
link or code span is trimmed, carriage returns and null characters are removed, and an empty
|
||||||
|
paragraph drops.
|
||||||
|
- An ordered list numbered past `999999999`, or adjacent ordered lists whose numbering does not
|
||||||
|
continue, is one bullet list keeping its numbers as text.
|
||||||
|
- A task list beside a bullet or decision list, or holding a block other than a task, joins one
|
||||||
|
bullet list keeping its states as text: `- \[x] Done`.
|
||||||
|
- Text that would read as a marker takes a backslash: `==` wherever it could open or close a
|
||||||
|
highlight, `[!…]` opening a quote, and `[x]` or `[ ]` opening any list item, since GitHub reads
|
||||||
|
that marker per item.
|
||||||
|
- A node read back carries no `localId` except a `taskList`, `taskItem` or `blockTaskItem`, which
|
||||||
|
Atlassian's schema requires one on: each gets a UUID v4 hashed from the whole markdown and its
|
||||||
|
position, the same on every read. Join markdown bound for one document and read it once: the same
|
||||||
|
markdown read twice into one document repeats its ids.
|
||||||
|
|
||||||
## The errors
|
## The errors
|
||||||
|
|
||||||
An ADF node type this version does not know is not an error: it is carried opaquely and restores
|
Serves Goal 1. An ADF node type this version does not know is not an error: the lossless pair
|
||||||
unchanged (AGENTS.md §3).
|
carries it opaquely and restores it unchanged ([`docs/decisions.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/docs/decisions.md#unknown-nodes-ride-the-carry)).
|
||||||
|
|
||||||
`ConvertError` is `{ code, message, path, position? }`. `code` is the exported `ConvertErrorCode`,
|
`ConvertError` is `{ code, message, path, position? }`. `code` is the exported `ConvertErrorCode`,
|
||||||
stable across minors and safe to `switch` on exhaustively with no `default`; `message` is free text
|
stable across minors and safe to `switch` on exhaustively with no `default`; `message` is free text
|
||||||
@@ -74,17 +167,17 @@ UTF-16 code unit, a JavaScript string index rather than a codepoint or a byte of
|
|||||||
or before the refusal — currently the start of the line the enclosing block begins on; a later
|
or before the refusal — currently the start of the line the enclosing block begins on; a later
|
||||||
minor may narrow that, never widen it.
|
minor may narrow that, never widen it.
|
||||||
|
|
||||||
Parsing — `markdownToAdf`, and `htmlToAdf` at `0.3.0`:
|
Parsing — `markdownToAdf` and `plainMarkdownToAdf`, and `htmlToAdf` at `0.2.0`:
|
||||||
|
|
||||||
| Code | Fires when | What you can do |
|
| Code | Fires when | What you can do |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `malformed-directive` | a `:::` block or `:name[…]` inline directive the grammar cannot read — an unclosed fence or `[content]`, `{attrs}` out of order or duplicated, invalid JSON in an `adf` carry | write the spelling the message names, or escape the line — `\:::` for a block, `\:` for an inline one — to keep it literal text |
|
| `malformed-directive` | an `!adf:` the grammar cannot read — a prefix completing no directive, an unclosed container, `[content]` or `{attrs}`, a closer with no container of its name open, a leaf given a body, `{attrs}` out of order or duplicated, invalid JSON in a `carry` | write the spelling the message names, or escape the prefix — `\!adf:`, block and inline alike — to keep it literal text |
|
||||||
| `malformed-pipe-table` | a pipe row that is no pipe table — a missing or ragged `---` delimiter row, an alignment colon in it, or a row not opening with a pipe | open every row with a pipe and give the delimiter row the header's cell count; to keep the lines literal text instead, escape the leading pipe of every one — escaping a single row leaves the next to open a fresh table and fail the same way |
|
| `malformed-pipe-table` | a pipe row that is no pipe table — a missing or ragged `---` delimiter row, an alignment colon in it, or a row not opening with a pipe | open every row with a pipe and give the delimiter row the header's cell count; to keep the lines literal text instead, escape the leading pipe of every one — escaping a single row leaves the next to open a fresh table and fail the same way |
|
||||||
| `unknown-directive-name` | a directive whose name is no node or mark this version spells | check the name in `spec/flavour.md`, or escape the colon; the spelling itself is well formed, so a later minor may give the name meaning |
|
| `unknown-directive-name` | a directive whose name is no node or mark this version spells | check the name in `spec/flavour.md`, or escape the prefix as `\!adf:`; the spelling itself is well formed, so a later minor may give the name meaning |
|
||||||
| `unmappable-html` | the markdown holds a raw HTML tag, comment or processing instruction | remove it or write it in the flavour — ADF holds no raw-HTML node, and the element mapping lands at `0.3.0` |
|
| `unmappable-html` | the input holds an HTML construct the documented element set does not map, a comment and a processing instruction among them — at this version that is every raw HTML construct in markdown, the element set landing at `0.2.0` | remove the construct, or write what it holds in the lossless flavour |
|
||||||
| `unmappable-image` | an image sits inside other content, or carries a title | give the image a paragraph of its own and drop the title |
|
| `unmappable-image` | an image sits inside other content that is not another image's description, or carries a title | give the image a paragraph of its own and drop the title |
|
||||||
|
|
||||||
Emitting — `adfToMarkdown`, and `adfToHtml` at `0.3.0`:
|
Emitting — `adfToMarkdown`, and `adfToHtml` at `0.2.0`:
|
||||||
|
|
||||||
| Code | Fires when | What you can do |
|
| Code | Fires when | What you can do |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
@@ -99,59 +192,58 @@ emit refuses:
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `unspellable-character` | text or a code block holds a carriage return or a null character, which CommonMark rewrites wherever it sits | strip or replace the character; no escape carries it through the round-trip |
|
| `unspellable-character` | text or a code block holds a carriage return or a null character, which CommonMark rewrites wherever it sits | strip or replace the character; no escape carries it through the round-trip |
|
||||||
| `unspellable-line-start` | a paragraph line begins with a code span whose backticks would read back as a code fence | put any text before the code span |
|
| `unspellable-line-start` | a paragraph line begins with a code span whose backticks would read back as a code fence | put any text before the code span |
|
||||||
| `unspellable-link` | a link `href` or `title` holds what no canonical escape spells — a backslash, a newline, a control character, an entity reference, an angle bracket beside a space | percent-encode the destination (`%5C` for the backslash, `%26` for the `&` that opens the entity), or drop the title |
|
|
||||||
| `unspellable-whitespace` | an `emoji`, `mention` or `status` holds a newline in the text its inline directive spells in the content slot | replace it with a space — an inline directive never spans lines |
|
| `unspellable-whitespace` | an `emoji`, `mention` or `status` holds a newline in the text its inline directive spells in the content slot | replace it with a space — an inline directive never spans lines |
|
||||||
| `unsupported-nesting-depth` | blocks, marks, an attribute's JSON or a carried node's JSON nest past 500 levels | keep the ADF and pass the document over, or show it read-only; flatten the input where you are the one who wrote it |
|
| `unsupported-nesting-depth` | blocks, marks, an attribute's JSON or a carried node's JSON nest past 500 levels | keep the ADF and pass the document over, or show it read-only; flatten the input where you are the one who wrote it |
|
||||||
| `unsupported-node-shape` | a node carries an attribute, value, argument or body its type does not take — or markdown writes as a directive a node the flavour spells as CommonMark | write the shape the message names; `spec/flavour.md` lists every type's attributes and body |
|
| `unsupported-node-shape` | a node carries an attribute, value, argument or body its type does not take, or lacks one it needs — or markdown writes as a directive a node or mark the lossless flavour spells as CommonMark | write the shape the message names; `spec/flavour.md` lists every type's attributes and body |
|
||||||
|
|
||||||
## The guarantees
|
## The guarantees
|
||||||
|
|
||||||
|
Serves Goals 1, 3 and 4.
|
||||||
|
|
||||||
- `markdownToAdf(adfToMarkdown(doc))` equals `doc` — unknown node types included, carried opaquely
|
- `markdownToAdf(adfToMarkdown(doc))` equals `doc` — unknown node types included, carried opaquely
|
||||||
(AGENTS.md §3).
|
([`docs/decisions.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/docs/decisions.md#unknown-nodes-ride-the-carry)).
|
||||||
- Plain CommonMark is valid input to `markdownToAdf` apart from the raw HTML below, with three
|
- Markdown this library reads, and markdown it writes, means what the CommonMark spec says; from
|
||||||
carve-outs — literal text matching directive, pipe-table or strikethrough syntax is claimed
|
`0.2.0`, well-formed HTML means what the HTML standard says, read or written. The bullets below
|
||||||
(escapable — `spec/flavour.md`) — and one gap: a CommonMark image fits only as its own
|
name every exception.
|
||||||
title-less paragraph; mid-text and titled images are error results. Converting back yields the
|
- Plain CommonMark is valid input to `markdownToAdf` apart from the raw HTML `unmappable-html`
|
||||||
library's canonical spelling, which round-trips byte-identically — where it converts back at
|
names, with three carve-outs — literal text matching directive, pipe-table or strikethrough
|
||||||
all: a parse succeeding is no promise of that, so keep the source until the way back succeeds.
|
syntax is claimed (escapable — `spec/flavour.md`) — and one gap: a CommonMark image fits only as
|
||||||
`[a](/a\b)`, `<http://x?a=1&b=2>` and `[a](/x y)` read cleanly and then refuse.
|
its own title-less paragraph; mid-text and titled images are error results, save an image inside
|
||||||
- Three CommonMark spellings parse without an error and build a document the reference renders
|
another's description, which flattens into the alt text. Converting back yields the library's
|
||||||
differently: `[](/url)` and `[]()` stay literal text against CommonMark's empty link, a list
|
canonical spelling, which round-trips byte-identically — where it converts back at all: a parse
|
||||||
continuing past a marker change stays one list against CommonMark's two, and a shortcut
|
succeeding is no promise of that, so keep the source until the way back succeeds.
|
||||||
reference matching its definition only under Unicode case folding stays unresolved. Each is
|
``` ` `` ` ``` reads cleanly and then refuses.
|
||||||
pinned `pending` in `corpus/commonmark-spec/exceptions.json`.
|
- Four CommonMark spellings parse without an error and build a document the reference
|
||||||
- Raw HTML in markdown input is an error result, never a silent drop — a tag, a comment and a
|
implementation renders differently: `[](/url)` and `[]()` stay literal text against CommonMark's
|
||||||
processing instruction alike. ADF holds no raw-HTML node; the element mapping ships at `0.3.0`.
|
empty link, a list continuing past a marker change stays one list against CommonMark's two, a
|
||||||
|
shortcut reference matching its definition only under Unicode case folding stays unresolved, and
|
||||||
|
a link whose text holds an autolink keeps the inner link and leaves the outer brackets literal
|
||||||
|
text, which the spec requires and the reference itself breaks, nesting one `<a>` in the other.
|
||||||
|
The first three are pinned `pending` in `corpus/commonmark-spec/exceptions.json`; the suite
|
||||||
|
holds no example of the fourth.
|
||||||
- Not every document converts back: `adfToMarkdown` is partial on valid ADF — a text node holding
|
- Not every document converts back: `adfToMarkdown` is partial on valid ADF — a text node holding
|
||||||
a carriage return, a link destination or title no canonical escape spells, a paragraph line
|
a carriage return, or a paragraph line beginning with a code span whose backticks read back as a
|
||||||
beginning with a code span whose backticks read back as a fence. Show the refusal and keep the
|
fence. Show the refusal and keep the document read-only; saving markdown you could not produce
|
||||||
document read-only; saving markdown you could not produce is the loss the round-trip exists to
|
is the loss the round-trip exists to stop.
|
||||||
stop.
|
|
||||||
- The pipe table narrows GFM's twice: every row opens with a pipe, so GFM's bare form is an error
|
- The pipe table narrows GFM's twice: every row opens with a pipe, so GFM's bare form is an error
|
||||||
result rather than the prose it reads as, and an alignment colon in the delimiter row is an
|
result rather than the prose it reads as, and an alignment colon in the delimiter row is an
|
||||||
error too — ADF holds no column alignment. The trailing pipe is canonical output, optional in
|
error too — ADF holds no column alignment. The trailing pipe is canonical output, optional in
|
||||||
input.
|
input.
|
||||||
- Past that and `~~`, no GFM: an autolink literal and a `- [ ]` marker stay text, and a checklist
|
- Past that and `~~`, no GFM: an autolink literal and a `- [ ]` marker stay text, and a checklist
|
||||||
is the `taskList` directive.
|
is the `taskList` directive — `plainMarkdownToAdf` turns the marker into a `taskList`.
|
||||||
- A document nested deeper than 500 levels is an error result, not a stack overflow.
|
- A document nested deeper than 500 levels is an error result, not a stack overflow, and no input
|
||||||
- The emitted formats are semver surface (AGENTS.md §8).
|
makes a call loop forever.
|
||||||
- **`0.3.0`** — `htmlToAdf(adfToHtml(doc))` equals `doc`; fidelity HTML cannot express rides
|
- The emitted formats are semver surface
|
||||||
`data-*` attributes. Foreign HTML maps a documented element set, an unmappable element is an
|
([`docs/decisions.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/docs/decisions.md#the-formats-are-api)).
|
||||||
error, and well-formed HTML only — no tag-soup recovery.
|
- **`0.2.0`** — `htmlToAdf(adfToHtml(doc))` equals `doc`; fidelity HTML cannot express rides
|
||||||
|
`data-*` attributes. Foreign HTML maps a documented element set, which markdown's raw HTML reads
|
||||||
## Who it is for
|
through as well, and a construct outside it is an error; well-formed HTML only — no tag-soup
|
||||||
|
recovery.
|
||||||
Personas, never named consumers (AGENTS.md §7):
|
|
||||||
|
|
||||||
- **Viewer/editor app** — shows a document, lets a human edit, posts back. Losslessness above all.
|
|
||||||
- **Bot posting content** — converts generated markdown to ADF; needs the CommonMark promise.
|
|
||||||
- **Export/indexing tool** — bulk ADF→markdown/HTML; needs readable output.
|
|
||||||
- **LLM/agent pipeline** — documents to a model as markdown, edits back; needs the round-trip and
|
|
||||||
markdown legible to a reader that half-knows the flavour.
|
|
||||||
|
|
||||||
## The package
|
## The package
|
||||||
|
|
||||||
ESM only, no runtime dependencies, public npmjs. Built JavaScript with `.d.ts` beside it.
|
Serves Goal 7. ESM only, no runtime dependencies, public npm. Built JavaScript with `.d.ts`
|
||||||
Pure ECMAScript at an ES2022 baseline, reaching for no host API; the test suite runs under Node,
|
beside it. Pure ECMAScript at an ES2022 baseline, reaching for no host API; the test suite runs
|
||||||
Deno and Bun, and a headless Firefox converts the corpus through the built entrypoint.
|
under Node, Deno and Bun, and a headless Firefox converts the corpus through the built entrypoint.
|
||||||
Contract: `AGENTS.md` §5–6.
|
Contract: [`docs/decisions.md`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/docs/decisions.md#any-es2022-engine), §Any
|
||||||
|
ES2022 engine to §Public on npm.
|
||||||
|
|||||||
@@ -3,6 +3,11 @@ try {
|
|||||||
window.convertCorpus = (corpus) => ({
|
window.convertCorpus = (corpus) => ({
|
||||||
errors: corpus.errors.map(({ markdown, name }) => ({ name, parsed: markdownToAdf(markdown) })),
|
errors: corpus.errors.map(({ markdown, name }) => ({ name, parsed: markdownToAdf(markdown) })),
|
||||||
normalization: corpus.normalization.map(({ markdown, name }) => ({ name, parsed: markdownToAdf(markdown) })),
|
normalization: corpus.normalization.map(({ markdown, name }) => ({ name, parsed: markdownToAdf(markdown) })),
|
||||||
|
realPayloads: corpus.realPayloads.map(({ json, name }) => {
|
||||||
|
const adf = JSON.parse(json)
|
||||||
|
const emitted = adfToMarkdown(adf)
|
||||||
|
return { emitted, isDocument: isAdfDocument(adf), name, parsed: emitted.ok ? markdownToAdf(emitted.value) : undefined }
|
||||||
|
}),
|
||||||
roundTrip: corpus.roundTrip.map(({ json, markdown, name }) => {
|
roundTrip: corpus.roundTrip.map(({ json, markdown, name }) => {
|
||||||
const adf = JSON.parse(json)
|
const adf = JSON.parse(json)
|
||||||
return { emitted: adfToMarkdown(adf), isDocument: isAdfDocument(adf), name, parsed: markdownToAdf(markdown) }
|
return { emitted: adfToMarkdown(adf), isDocument: isAdfDocument(adf), name, parsed: markdownToAdf(markdown) }
|
||||||
|
|||||||
+17
-5
@@ -1,7 +1,8 @@
|
|||||||
import assert from 'node:assert/strict'
|
import assert from 'node:assert/strict'
|
||||||
import { readFileSync, readdirSync } from 'node:fs'
|
|
||||||
import { createServer } from 'node:http'
|
import { createServer } from 'node:http'
|
||||||
import { extname, join } from 'node:path'
|
import { extname, join } from 'node:path'
|
||||||
|
import { readFileSync, readdirSync } from 'node:fs'
|
||||||
|
import { toEditorNormal } from '../dist/adf/editor-normal.js'
|
||||||
|
|
||||||
const contentTypes = { '.html': 'text/html; charset=utf-8', '.js': 'text/javascript' }
|
const contentTypes = { '.html': 'text/html; charset=utf-8', '.js': 'text/javascript' }
|
||||||
const driver = 'http://127.0.0.1:4444'
|
const driver = 'http://127.0.0.1:4444'
|
||||||
@@ -66,6 +67,7 @@ async function whenDriverAnswers() {
|
|||||||
const corpus = {
|
const corpus = {
|
||||||
errors: fixtureNames('errors', '.md').map((name) => ({ markdown: fixture(name, '.md'), name })),
|
errors: fixtureNames('errors', '.md').map((name) => ({ markdown: fixture(name, '.md'), name })),
|
||||||
normalization: fixtureNames('normalization', '.md').map((name) => ({ markdown: fixture(name, '.md'), name })),
|
normalization: fixtureNames('normalization', '.md').map((name) => ({ markdown: fixture(name, '.md'), name })),
|
||||||
|
realPayloads: fixtureNames('real-payloads', '.json').map((name) => ({ json: fixture(name, '.json'), name })),
|
||||||
roundTrip: fixtureNames('round-trip', '.json').map((name) => ({ json: fixture(name, '.json'), markdown: fixture(name, '.md'), name })),
|
roundTrip: fixtureNames('round-trip', '.json').map((name) => ({ json: fixture(name, '.json'), markdown: fixture(name, '.md'), name })),
|
||||||
}
|
}
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
@@ -74,7 +76,7 @@ assert.deepEqual(
|
|||||||
.map((entry) => entry.name)
|
.map((entry) => entry.name)
|
||||||
.filter((name) => name !== 'commonmark-spec')
|
.filter((name) => name !== 'commonmark-spec')
|
||||||
.sort(),
|
.sort(),
|
||||||
['errors', 'normalization', 'round-trip'],
|
['errors', 'normalization', 'real-payloads', 'round-trip'],
|
||||||
'a corpus kind the browser leg does not convert',
|
'a corpus kind the browser leg does not convert',
|
||||||
)
|
)
|
||||||
for (const [kind, fixtures] of Object.entries(corpus)) assert.ok(fixtures.length > 0, `the browser leg found no ${kind} fixture to convert`)
|
for (const [kind, fixtures] of Object.entries(corpus)) assert.ok(fixtures.length > 0, `the browser leg found no ${kind} fixture to convert`)
|
||||||
@@ -105,7 +107,7 @@ for (const [index, { json, markdown, name }] of corpus.roundTrip.entries()) {
|
|||||||
assert.ok(result.emitted.ok, `it did not emit — ${refusal(result.emitted)}`)
|
assert.ok(result.emitted.ok, `it did not emit — ${refusal(result.emitted)}`)
|
||||||
assert.equal(result.emitted.value, markdown)
|
assert.equal(result.emitted.value, markdown)
|
||||||
assert.ok(result.parsed.ok, `it did not parse — ${refusal(result.parsed)}`)
|
assert.ok(result.parsed.ok, `it did not parse — ${refusal(result.parsed)}`)
|
||||||
assert.deepEqual(result.parsed.value, JSON.parse(json))
|
assert.deepEqual(toEditorNormal(result.parsed.value), JSON.parse(json))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +115,17 @@ for (const [index, { name }] of corpus.normalization.entries()) {
|
|||||||
const result = results.normalization[index]
|
const result = results.normalization[index]
|
||||||
checking(name, result, () => {
|
checking(name, result, () => {
|
||||||
assert.ok(result.parsed.ok, `it did not parse — ${refusal(result.parsed)}`)
|
assert.ok(result.parsed.ok, `it did not parse — ${refusal(result.parsed)}`)
|
||||||
assert.deepEqual(result.parsed.value, JSON.parse(fixture(name, '.json')))
|
assert.deepEqual(toEditorNormal(result.parsed.value), JSON.parse(fixture(name, '.json')))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [index, { json, name }] of corpus.realPayloads.entries()) {
|
||||||
|
const result = results.realPayloads[index]
|
||||||
|
checking(name, result, () => {
|
||||||
|
assert.ok(result.isDocument, `${name}.json is no ADF document`)
|
||||||
|
assert.ok(result.emitted.ok, `it did not emit — ${refusal(result.emitted)}`)
|
||||||
|
assert.ok(result.parsed.ok, `it did not parse back — ${refusal(result.parsed)}`)
|
||||||
|
assert.deepEqual(toEditorNormal(result.parsed.value), JSON.parse(json))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,5 +138,5 @@ for (const [index, { name }] of corpus.errors.entries()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`Firefox ${session.capabilities.browserVersion} converted ${corpus.roundTrip.length} round-trip, ${corpus.normalization.length} normalization and ${corpus.errors.length} error fixtures`,
|
`Firefox ${session.capabilities.browserVersion} converted ${corpus.roundTrip.length} round-trip, ${corpus.normalization.length} normalization and ${corpus.errors.length} error fixtures and ${corpus.realPayloads.length} real payloads`,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,28 +3,31 @@ set -euo pipefail
|
|||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
source ./docker-runner.sh
|
source ./docker-runner.sh
|
||||||
|
|
||||||
in_image "$node_image" npm ci
|
leg "install ($node_image)" in_image "$node_image" npm ci
|
||||||
in_image "$node_image" npm run typecheck
|
leg "typecheck ($node_image)" in_image "$node_image" npm run typecheck
|
||||||
|
leg "size ratchet ($node_image)" in_image "$node_image" npm run size-ratchet
|
||||||
|
|
||||||
if ! test_output=$(in_image "$node_image" npm test 2>&1); then
|
test_log=$(mktemp)
|
||||||
printf '%s\n' "$test_output"
|
node_tests() {
|
||||||
exit 1
|
in_image "$node_image" npm test 2>&1 | tee "$test_log"
|
||||||
fi
|
}
|
||||||
printf '%s\n' "$test_output"
|
|
||||||
if printf '%s' "$test_output" | grep -q 'ℹ tests 0'; then
|
leg "tests ($node_image)" node_tests
|
||||||
|
if grep -q 'ℹ tests 0' "$test_log"; then
|
||||||
echo 'the gate ran zero tests — failing instead of a vacuous green'
|
echo 'the gate ran zero tests — failing instead of a vacuous green'
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
rm -f "$test_log"
|
||||||
|
|
||||||
in_image "$deno_image" deno test --allow-read --no-check src/
|
leg "tests ($deno_image)" in_image "$deno_image" deno test --allow-env=PROPERTY_RUNS --allow-read --no-check src/
|
||||||
in_image "$bun_image" bun test src/
|
leg "tests ($bun_image)" in_image "$bun_image" bun test src/
|
||||||
|
|
||||||
in_image "$node_image" npm run build
|
leg "build ($node_image)" in_image "$node_image" npm run build
|
||||||
in_image "$node_image" sh -c 'set -e
|
leg "pack and install the tarball ($node_image)" in_image "$node_image" sh -c 'set -e
|
||||||
rm -rf package-tests/node_modules
|
rm -rf package-tests/node_modules
|
||||||
npm pack --pack-destination /tmp >/dev/null
|
npm pack --pack-destination /tmp
|
||||||
npm install --no-audit --no-fund --no-package-lock --no-save --offline --prefix package-tests /tmp/*.tgz >/dev/null'
|
npm install --no-audit --no-fund --no-package-lock --no-save --offline --prefix package-tests /tmp/*.tgz'
|
||||||
in_image "$node_image" npx tsc -p package-tests
|
leg "typecheck the consumer ($node_image)" in_image "$node_image" npx tsc -p package-tests
|
||||||
in_image "$floor_image" node package-tests/node-floor.js
|
leg "round-trip on the engines floor ($floor_image)" in_image "$floor_image" node package-tests/node-floor.js
|
||||||
|
|
||||||
with_firefox in_image "$node_image" node browser-tests/run.js
|
leg "browser ($firefox_image)" with_firefox in_image "$node_image" node browser-tests/run.js
|
||||||
|
|||||||
+8
-9
@@ -1,26 +1,25 @@
|
|||||||
# The corpus
|
# The corpus
|
||||||
|
|
||||||
One directory per contract kind, each landing with its milestone:
|
One directory per contract kind:
|
||||||
|
|
||||||
- `round-trip/` — `<name>.json` + `<name>.md`: the markdown `adfToMarkdown` must emit for that
|
- `round-trip/` — `<name>.json` + `<name>.md`: the markdown `adfToMarkdown` must emit for that
|
||||||
document, byte for byte, and that `markdownToAdf` must read back to it (AGENTS.md §2). Grouped
|
document, byte for byte, and that `markdownToAdf` must read back to it (`docs/decisions.md` §The
|
||||||
by what the fixture exercises.
|
round-trip is the product). Grouped by what the fixture exercises.
|
||||||
- `normalization/` — `<name>.md` + `<name>.json`: markdown input, and the document
|
- `normalization/` — `<name>.md` + `<name>.json`: markdown input, and the document
|
||||||
`markdownToAdf` must build from it, which must in turn emit and read back to itself. The
|
`markdownToAdf` must build from it, which must in turn emit and read back to itself. The
|
||||||
markdown is not canonical.
|
markdown is not canonical.
|
||||||
- `errors/` — `<name>.md`: markdown input that must not convert. A `<name>.error` beside it
|
- `errors/` — `<name>.md`: markdown input that must not convert. A `<name>.error` beside it
|
||||||
pins which error.
|
pins which error.
|
||||||
- `real-payloads/` — `<name>.json`: sanitized live ADF, round-tripped ADF→markdown→ADF. No
|
- `real-payloads/` — `<name>.json`: ADF Atlassian's editor wrote, round-tripped ADF→markdown→ADF.
|
||||||
expected markdown.
|
No expected markdown.
|
||||||
- `commonmark-spec/` — the CommonMark suite run against `markdownToAdf` by three checks. `spec.json`
|
- `commonmark-spec/` — the CommonMark suite run against `markdownToAdf` by three checks. `spec.json`
|
||||||
is the suite; `refusals.json` pins each refusing example to its error `code`; `exceptions.json`
|
is the suite; `refusals.json` pins each refusing example to its error `code`; `exceptions.json`
|
||||||
pins each known divergence by `check`, `example`, `kind` and the exact `divergence`, with a
|
pins each known divergence by `check`, `example`, `kind` and the exact `divergence`, with a
|
||||||
`reason`. `kind` is `mark-model` (the permanent count divergence from ADF's mark-per-text-node
|
`reason`. `kind` is `mark-model` (the permanent count divergence from ADF's mark-per-text-node
|
||||||
model), `unspellable` (parses but the flavour has no spelling) or `pending` (a parser gap a later
|
model), `unspellable` (parses but the flavour has no spelling) or `pending` (a parser gap).
|
||||||
milestone may close).
|
|
||||||
|
|
||||||
JSON is editor-normal (AGENTS.md §2), two-space indent, keys sorted. `spec.json` is the vendored,
|
JSON is editor-normal (`docs/decisions.md` §Equality is editor-normal), two-space indent, keys
|
||||||
upstream machine-readable suite, byte-exact from
|
sorted. `spec.json` is the vendored, upstream machine-readable suite, byte-exact from
|
||||||
[spec.commonmark.org](https://spec.commonmark.org/0.31.2/spec.json) (CommonMark 0.31.2, © John
|
[spec.commonmark.org](https://spec.commonmark.org/0.31.2/spec.json) (CommonMark 0.31.2, © John
|
||||||
MacFarlane, [CC-BY-SA-4.0](https://creativecommons.org/licenses/by-sa/4.0/)), and is not
|
MacFarlane, [CC-BY-SA-4.0](https://creativecommons.org/licenses/by-sa/4.0/)), and is not
|
||||||
re-serialized by the corpus gate.
|
re-serialized by the corpus gate.
|
||||||
|
|||||||
@@ -1,18 +1,4 @@
|
|||||||
[
|
[
|
||||||
{
|
|
||||||
"check": "fixpoint",
|
|
||||||
"divergence": "unspellable-link",
|
|
||||||
"example": 196,
|
|
||||||
"kind": "unspellable",
|
|
||||||
"reason": "The link title holds literal newlines no escape spells."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"check": "fixpoint",
|
|
||||||
"divergence": "unspellable-link",
|
|
||||||
"example": 202,
|
|
||||||
"kind": "unspellable",
|
|
||||||
"reason": "The link destination holds a backslash the flavour cannot escape."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"check": "count",
|
"check": "count",
|
||||||
"divergence": "ul 2/1",
|
"divergence": "ul 2/1",
|
||||||
@@ -349,13 +335,6 @@
|
|||||||
"kind": "pending",
|
"kind": "pending",
|
||||||
"reason": "An empty link text stays literal text; CommonMark renders an empty link."
|
"reason": "An empty link text stays literal text; CommonMark renders an empty link."
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"check": "fixpoint",
|
|
||||||
"divergence": "unspellable-link",
|
|
||||||
"example": 502,
|
|
||||||
"kind": "unspellable",
|
|
||||||
"reason": "The link destination holds a backslash the flavour cannot escape."
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"check": "count",
|
"check": "count",
|
||||||
"divergence": "a 1/5 em 1/4",
|
"divergence": "a 1/5 em 1/4",
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
:::tableCell {colwidth="[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"}
|
!adf:tableCell {colwidth="[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[1]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"}
|
||||||
:::
|
!adf:/tableCell
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
_a :adf{json="{\"type\":\"blockCard\"}"} b_
|
_a !adf:carry{json="{\"type\":\"blockCard\"}"} b_
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
:adf{json="{"}
|
!adf:carry{json="{"}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
```adf
|
```carry
|
||||||
{"type":
|
{"type":
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
:adf{json="[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"}
|
!adf:carry{json="[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]"}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
> Part.
|
> Part.
|
||||||
:::
|
!adf:/panel
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
:::codeBlock {wrap=true}
|
!adf:codeBlock {wrap=true}
|
||||||
fn main() {}
|
fn main() {}
|
||||||
:::
|
!adf:/codeBlock
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
:::codeBlock {language=rust wrap=true}
|
!adf:codeBlock {language=rust wrap=true}
|
||||||
```
|
```
|
||||||
fn main() {}
|
fn main() {}
|
||||||
```
|
```
|
||||||
:::
|
!adf:/codeBlock
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
:::
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
:::adf
|
|
||||||
{"type":"rule"}
|
|
||||||
:::
|
|
||||||
@@ -1 +1 @@
|
|||||||
::media {type=file id=a-1}
|
!adf:media {type=file id=a-1}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
:::panel info {bogus=1}
|
!adf:panel info {bogus=1}
|
||||||
Part.
|
Part.
|
||||||
:::
|
!adf:/panel
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
unsupported-node-shape
|
malformed-directive
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
:::rule
|
!adf:media {id=01a0aa6b-4221-7518-a640-2b97d6217ce2 type=file}
|
||||||
Part.
|
Part.
|
||||||
:::
|
!adf:/media
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
!adf:carry
|
||||||
|
{"type":"rule"}
|
||||||
|
!adf:/carry
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
!adf:panel info
|
||||||
|
!adf:expand
|
||||||
|
Part.
|
||||||
|
!adf:/panel
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
!adf:panel info
|
||||||
|
Part.
|
||||||
@@ -1 +1 @@
|
|||||||
Part :mention[**@Mikael**]{id=b1c2}.
|
Part !adf:mention[**@Mikael**]{id=b1c2}.
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
:::panel info
|
|
||||||
Part.
|
|
||||||
@@ -1 +1 @@
|
|||||||
::rule
|
!adf:rule
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Part :mention[@A and more.
|
Part !adf:mention[@A and more.
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
unsupported-node-shape
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
See !adf:link[the docs]{href="https://example.com/docs"} here.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
unsupported-node-shape
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
See !adf:link[the docs]{title="Setup guide"} here.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
unsupported-node-shape
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
See !adf:link[<https://example.com/docs>]{collection=contentId-98237 href="/docs"} here.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
unsupported-node-shape
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!adf:link[the docs]{href="https://example.com/docs"}
|
||||||
@@ -1 +1 @@
|
|||||||
Part :em[emphasised] here.
|
Part !adf:em[emphasised] here.
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
:::widget info
|
!adf:widget info
|
||||||
Part.
|
Part.
|
||||||
:::
|
!adf:/widget
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
malformed-directive
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Part !adf: here.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
unsupported-node-shape
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!adf:status[!adf:carry{json="{\"attrs\":{\"localId\":\"x\"},\"text\":\"ok\",\"type\":\"text\"}"}]{color=red}
|
||||||
@@ -1 +1 @@
|
|||||||
Part :text{text=plain} here.
|
Part !adf:text{text=plain} here.
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
::rule {localId="a-1"}
|
!adf:rule {localId="a-1"}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
malformed-directive
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
- Bolt M8
|
||||||
|
|
||||||
|
!adf:listBreak
|
||||||
|
Packed.
|
||||||
|
!adf:/listBreak
|
||||||
|
|
||||||
|
- Nut M8
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
- Bolt M8
|
- Bolt M8
|
||||||
|
|
||||||
::listBreak
|
!adf:listBreak
|
||||||
|
|
||||||
Packed.
|
Packed.
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,107 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "[",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "https://example.com/"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "https://example.com/",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "](/v)",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "[a",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "https://example.com/b"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "https://example.com/b",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "c](/v)",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "[",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"collection": "contentId-98237",
|
||||||
|
"href": "/docs"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "the docs",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "](/v)",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "[",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "/u"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "a",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "](/v)",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[<https://example.com/>](/v)
|
||||||
|
|
||||||
|
[a<https://example.com/b>c](/v)
|
||||||
|
|
||||||
|
[!adf:link[the docs]{collection=contentId-98237 href="/docs"}](/v)
|
||||||
|
|
||||||
|
[[a](/u)](/v)
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "/a\\b"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "a",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "http://x?a=1&b=2"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "http://x?a=1&b=2",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "/x\ny"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "a",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
[a](/a\b)
|
||||||
|
|
||||||
|
<http://x?a=1&b=2>
|
||||||
|
|
||||||
|
[a](/x y)
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "0d42e7ff24ba"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Code blocks",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "a971506228e7"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Run the setup once, then start the server with ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "code"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "npm start",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " and open the page.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"language": "javascript",
|
||||||
|
"localId": "eaf42046-6454-451d-ab13-8bd5ed2333bb",
|
||||||
|
"wrap": true
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "function greet(name) {\n return `Hello, ${name}!`\n}",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "codeBlock"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "d69616dee641"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "The same idea in Python:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"language": "python",
|
||||||
|
"localId": "2094b559-280a-49d5-9be3-182572e5d2d8",
|
||||||
|
"wrap": true
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "def total(prices):\n return sum(prices)\n\nprint(total([3, 4.5]))",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "codeBlock"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "abe1971d1f18"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "A query that lists visitors by city:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"language": "sql",
|
||||||
|
"localId": "5551dc8e-8fe0-455e-a9cf-22e48b589fe8",
|
||||||
|
"wrap": true
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "SELECT name, city\nFROM visitors\nWHERE city = 'Lund'\nORDER BY name;",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "codeBlock"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "51efdd2f1f02"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Plain output, no language chosen:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "d0f83c92-c252-4a70-9e31-dfb5ac255cd1",
|
||||||
|
"wrap": true
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "$ ./setup\nChecking folders... done\n 3 files copied",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "codeBlock"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "3dac57e146fa"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Keep ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "code"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": ".env",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " files out of version control, and never paste a ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "code"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "password",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " into a ticket.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,254 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "0fcbc98aec1f"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Where things stand",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "32b6266eb05c"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Office move ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "blue",
|
||||||
|
"localId": "1ab19511-a0fa-41a1-b6d0-6729813c0526",
|
||||||
|
"style": "mixedCase",
|
||||||
|
"text": "In progress"
|
||||||
|
},
|
||||||
|
"type": "status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " since ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "493624162706",
|
||||||
|
"timestamp": "1790812800000"
|
||||||
|
},
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " , owned by ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"accessLevel": "",
|
||||||
|
"id": "712020:78bf5058-bc76-4783-99af-6d70cb593cee",
|
||||||
|
"localId": "604060e1-e533-4019-aa28-21952dfdea19",
|
||||||
|
"text": "@Larvit Developer"
|
||||||
|
},
|
||||||
|
"type": "mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " .",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "73a94328c89f"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Furniture ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "green",
|
||||||
|
"localId": "7b27ff33-1483-452b-8982-311cf9429023",
|
||||||
|
"style": "mixedCase",
|
||||||
|
"text": "Done"
|
||||||
|
},
|
||||||
|
"type": "status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " , cabling ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "red",
|
||||||
|
"localId": "b6eb05a9-e0e7-4269-9cbd-e912640364a6",
|
||||||
|
"style": "mixedCase",
|
||||||
|
"text": "Blocked"
|
||||||
|
},
|
||||||
|
"type": "status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " , signage ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "yellow",
|
||||||
|
"localId": "ff7ed7fb-1846-48cb-b5ea-8be6b598ccc6",
|
||||||
|
"style": "mixedCase",
|
||||||
|
"text": "Waiting"
|
||||||
|
},
|
||||||
|
"type": "status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " , parking ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "purple",
|
||||||
|
"localId": "e9218ff4-6fcb-4e43-b36a-b1bef8a19376",
|
||||||
|
"style": "mixedCase",
|
||||||
|
"text": "Maybe"
|
||||||
|
},
|
||||||
|
"type": "status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " and keys ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "neutral",
|
||||||
|
"localId": "f1455340-2469-4bc6-a371-ed6b1f54386c",
|
||||||
|
"style": "mixedCase",
|
||||||
|
"text": "Not started"
|
||||||
|
},
|
||||||
|
"type": "status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " ",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "8d9e2dc70265"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"accessLevel": "",
|
||||||
|
"id": "712020:78bf5058-bc76-4783-99af-6d70cb593cee",
|
||||||
|
"localId": "ab5b7997-43ce-4238-b540-db3864e0965c",
|
||||||
|
"text": "@Larvit Developer"
|
||||||
|
},
|
||||||
|
"type": "mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " please confirm the handover on ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "77e2bdefa7fd",
|
||||||
|
"timestamp": "1795132800000"
|
||||||
|
},
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " before lunch.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "f7fb8a7527a3"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Great work so far ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"id": "1f44d",
|
||||||
|
"localId": "8fe9a02e94ce",
|
||||||
|
"shortName": ":thumbsup:",
|
||||||
|
"text": "👍"
|
||||||
|
},
|
||||||
|
"type": "emoji"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " and thanks for the snacks ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"id": "1f389",
|
||||||
|
"localId": "c19496cc742f",
|
||||||
|
"shortName": ":tada:",
|
||||||
|
"text": "🎉"
|
||||||
|
},
|
||||||
|
"type": "emoji"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"id": "1f600",
|
||||||
|
"localId": "c05a6757d0ee",
|
||||||
|
"shortName": ":grinning:",
|
||||||
|
"text": "😀"
|
||||||
|
},
|
||||||
|
"type": "emoji"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " ",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b75918031ebd"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Deliveries go to:",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hardBreak"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Building C, third floor",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hardBreak"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Ring the bell twice",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,527 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 1,
|
||||||
|
"localId": "cfdcc54363d9"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Project handbook",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "91177a27b0ff"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Welcome to the handbook for the spring project.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "7e7d9113a89b"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Getting started",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e65711ca96b6"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Pack the following before the first day:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b5c36c57fe79"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "1f4aa02de452"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "8993e22a13aa"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Laptop",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "2b335a4504ab"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "c9180347caf0"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "60990e48da32"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Charger",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "fc5d4c8a875d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "3b8ec5318463"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Mouse",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "bulletList"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "90f5f37a8a8f"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "90fab5a310c5"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Notebook",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "46840b8bd24b",
|
||||||
|
"order": 1
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b4f06fbd15ef"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "93db4583bdba"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Lined for notes",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "6904c80dd06d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "0bc1c819d38d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Squared for sketches",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "orderedList"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "65bd0afce26e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "a753e5ecdad3"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Water bottle",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "bulletList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 3,
|
||||||
|
"localId": "5b6a671499c5"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Unpacking",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "f460abd3a962"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "The first two steps happen at reception, so ours start at three:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "baf0046a0432",
|
||||||
|
"order": 3
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b4df865a31a9"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "3f1b32f952d0"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Unpack the boxes",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "f64930d87d4e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "d953389c865a"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Label the shelves",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "840daad9cb43"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "8708b8c7aeec"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Recycle the cardboard",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "orderedList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 4,
|
||||||
|
"localId": "27d1d408ae3e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Shelf labels",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "8b5cf239dbb5",
|
||||||
|
"order": 1
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "0948562abdc3"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "4da9d4f45923"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Top shelf",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "36edf97d8e2c"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "7915e252429c"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "9b15cc9fa8a1"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Binders",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "efe607ab9e41"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "d559a2f29321"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Archive boxes",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "bulletList"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "229692097876"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "928b1862c273"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Bottom shelf",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "orderedList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 5,
|
||||||
|
"localId": "353a84ef9126"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Quiet hours",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "9c11b949ed48"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "bd576489e8b6"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Good tools make good work, and quiet rooms make good thinking.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "727fda576a9d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Please keep calls in the booths.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "blockquote"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 6,
|
||||||
|
"localId": "b12277440bc7"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Small print",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "9f6fbb5a19af"
|
||||||
|
},
|
||||||
|
"type": "rule"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "8a6e253c110e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Office hours:",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hardBreak"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Monday to Thursday, eight to five",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hardBreak"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "Friday, eight to three",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b9c3f5daa373"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "That is all for now.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "d5c3a2503683"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Media and attachments",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "f71287760586"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "A photo of the meadow behind the office:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"layout": "align-start",
|
||||||
|
"localId": "95de25bcdecc",
|
||||||
|
"width": 320,
|
||||||
|
"widthType": "pixel"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"alt": "Green meadow under a yellow sun",
|
||||||
|
"collection": "",
|
||||||
|
"height": 180,
|
||||||
|
"id": "8c586460-fb0d-44f6-949f-d800d5dd0f45",
|
||||||
|
"localId": "630d0d0457b8",
|
||||||
|
"type": "file",
|
||||||
|
"width": 320
|
||||||
|
},
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "#091e4224",
|
||||||
|
"size": 2
|
||||||
|
},
|
||||||
|
"type": "border"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "media"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "mediaSingle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b4bfee3ad3ec"
|
||||||
|
},
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "ffe5710ea995"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "The packing list is attached as a file:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"collection": "",
|
||||||
|
"id": "8dfd7046-2382-4377-b3ba-ec31e34cd01a",
|
||||||
|
"type": "file"
|
||||||
|
},
|
||||||
|
"type": "media"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "mediaGroup"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "77fcb609f709"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Both were uploaded from the editor.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,292 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "d483ec27f809"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Panels",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "cb02f8e9812b"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Each colour of panel below holds a short note for the visiting team.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b6d76c21e77e",
|
||||||
|
"panelType": "info"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "2d871d80f6e1"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "The workshop starts at nine in the morning.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "panel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "cbaab515445c",
|
||||||
|
"panelType": "note"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "13cafc26c42d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Bring your own laptop charger.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "panel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "c5fa8b34e2aa",
|
||||||
|
"panelType": "success"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e186fca354d9"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "All rooms are booked for the week.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "panel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "ee223a0f886e",
|
||||||
|
"panelType": "warning"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e0006fb2b972"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "The east entrance closes early on Fridays.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "ea6a56b9c863"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Use the main door after four.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "panel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "fedbadc6d1c7",
|
||||||
|
"panelType": "error"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "c0f6122d81b7"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "The projector in room two is out of order.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "panel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "afe638de11c5"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Expands",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e635bf2eac43",
|
||||||
|
"title": "Agenda for the first day"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "c8beb4c392ee"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "6d6ff472d878"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "d1186101c5a1"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Welcome and introductions",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "01d203b97343"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "61bfec91218d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Tour of the building",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "004e47604c2a"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "726aa40e1e38"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Lunch in the courtyard",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "bulletList"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "expand"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "cb6e48b9d746"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Questions go to the organisers before the event.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "32a8832682b2",
|
||||||
|
"title": "Travel details"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "00b05814cccb"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Trains leave the central station every twenty minutes.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "eec0df0ed4f1",
|
||||||
|
"panelType": "note"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "712c49fa7ecc"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Tickets are cheaper before seven.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "panel"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "expand"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,630 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "3b911072ce78"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Summary of the planning session on Thursday. Attendees: ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"accessLevel": "",
|
||||||
|
"id": "712020:78bf5058-bc76-4783-99af-6d70cb593cee",
|
||||||
|
"localId": "c8b64b9f-d396-4525-9456-38cf690ade1e",
|
||||||
|
"text": "@Larvit Developer"
|
||||||
|
},
|
||||||
|
"type": "mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " and two guests from the design team.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "3e97ef36cbc3"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Where we are",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "530e0e3aa621"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "The beta is ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "green",
|
||||||
|
"localId": "ac0975eb-fafe-44ad-8293-8a12fdbcaebc",
|
||||||
|
"style": "mixedCase",
|
||||||
|
"text": "On track"
|
||||||
|
},
|
||||||
|
"type": "status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " and the public launch is set for ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "84d9a1cde860",
|
||||||
|
"timestamp": "1793664000000"
|
||||||
|
},
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " .",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "ffcd53578640",
|
||||||
|
"panelType": "warning"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "0f0e8b9e13bb"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Translation files are still ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "missing",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " for two languages.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "panel"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "d9b590d479ad"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Decisions",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "69dc2d52-34f7-43bb-8d6c-36d52a47179e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "852a35a7-f660-4161-85dd-2d54adaf662b",
|
||||||
|
"state": "DECIDED"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Ship the beta to internal users first",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "decisionItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "2df16457-331f-4d26-90ba-539f82949d70",
|
||||||
|
"state": "DECIDED"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Keep the old export for one more release",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "decisionItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "decisionList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "7813370b5e89"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Next steps",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "21a7a33c-199d-4396-a148-c8404f70554f"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "5343dfdb-e70d-4ce6-bca5-8a382123c7bd",
|
||||||
|
"state": "TODO"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Draft the release notes",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "taskItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "67d65eb8-17e9-4cd6-93cb-7d495f84e01d",
|
||||||
|
"state": "TODO"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Book the demo room",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "taskItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "taskList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "e5806b037d61"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Numbers",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"isNumberColumnEnabled": false,
|
||||||
|
"layout": "align-start",
|
||||||
|
"localId": "cbae6bea-3c35-42b9-9a8f-3b37749e1a87"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e4d343447bf5"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "4fcec7ad0a0f"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "974849d6e63c"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "Metric",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "42df5203769e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "8b0da0854a0a"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "Beta",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "cbdae6c8508d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "2584f222d6c3"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "Goal",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableRow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "65e4d7a700c0"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "a37175350eea"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "7efe32972497"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Sign-ups",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e0a95cdbd3c5"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "4628a3afe71b"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "140",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b802fc652961"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "94c6ec93acb2"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "200",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableRow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "bd6465cc546d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b6dcef3c6ac5"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "ba5c99353d30"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Crash reports",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "554b7b5a8e71"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "569a134488bc"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "3",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "fb03db2017b1"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "c0ce0ada482c"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "0",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableRow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b4eb1362eb9f"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "The flag that turns the beta on:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"language": "yaml",
|
||||||
|
"localId": "14298a36-6632-458f-a548-7fccd4b7186b",
|
||||||
|
"wrap": true
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "beta:\n enabled: true\n audience: internal",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "codeBlock"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "a98274e22eaa"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Risks we talked about:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "fb3e387688ff"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "fdeee4ce0678"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "5ff2e05f1c7e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Late translations",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "043a7ded718e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "73a4d8e4ef0d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "The holiday week",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "3e32c1b868a1"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "98969cd5548e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "3b9989413325"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Half the team is away",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "bulletList"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "bulletList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "ba7d8422f4c6"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "a6837cfad3f5"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Small steps, shipped often.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "blockquote"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "6ec9ef8df224"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Thanks, everyone ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"id": "1f389",
|
||||||
|
"localId": "2481c60576e0",
|
||||||
|
"shortName": ":tada:",
|
||||||
|
"text": "🎉"
|
||||||
|
},
|
||||||
|
"type": "emoji"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " ",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "782129bf30c1",
|
||||||
|
"title": "Raw notes"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e9614e389875"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "We spent twenty minutes on the colour of the launch banner.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "expand"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "3e9517d02129"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Looks good to me. Two small things:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "5738867bf15d",
|
||||||
|
"order": 1
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "ccd8d283e36d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "638111edfab4"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Rename ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "code"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "beta.enabled",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " before the launch",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "0adfb25bb321"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "980750fad0fe"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Move the demo to the ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "em"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "large",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " room",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "orderedList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "40e080c7acd4"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Thanks ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"accessLevel": "",
|
||||||
|
"id": "712020:78bf5058-bc76-4783-99af-6d70cb593cee",
|
||||||
|
"localId": "c4e073cd-8b3a-48b2-93a0-ade57b4ec2cf",
|
||||||
|
"text": "@Larvit Developer"
|
||||||
|
},
|
||||||
|
"type": "mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " !",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "e632994a13ae"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Smart links",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "dcfa975dde87"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "An inline card sits in a sentence, like ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "042b9a548674",
|
||||||
|
"url": "https://en.wikipedia.org/wiki/Markdown"
|
||||||
|
},
|
||||||
|
"type": "inlineCard"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " which keeps the text flowing.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "c138d931a131"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "A block card stands on its own line:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "9e527ae5f2bd"
|
||||||
|
},
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "88bd10974ec6",
|
||||||
|
"url": "https://spec.commonmark.org/"
|
||||||
|
},
|
||||||
|
"type": "blockCard"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "9879bb1368ea"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": " An embed shows the page itself, where the site allows it:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "ccbed18139bb"
|
||||||
|
},
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"layout": "wide",
|
||||||
|
"localId": "8320cf243168",
|
||||||
|
"originalHeight": 480,
|
||||||
|
"originalWidth": 853.344,
|
||||||
|
"url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
|
||||||
|
"width": 100
|
||||||
|
},
|
||||||
|
"type": "embedCard"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "22f60b236c1c"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": " And a plain address stays a link: ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "https://www.markdownguide.org/"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "https://www.markdownguide.org/",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " for reference.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "3265660b5792"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Shared checklist",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "c7d94ae59a47"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "The block below is synced, so an edit shows up wherever it is used.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "72651b28-757c-44a1-be0b-586c3e6df546",
|
||||||
|
"resourceId": "03a667ab-4c6b-402d-adae-0c55582e32eb"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "0eb44ec3924b"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Before every release:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "4beeefa0c6fa"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "07d19212447f"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "2fd9fc0e5d71"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Run the tests",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "7f5f50f7642c"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "14d3435ce5f4"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Update the changelog",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "listItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "bulletList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e405ebea5e00"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Ask for a second pair of eyes.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "bodiedSyncBlock"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "73b5f0a1ef05"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Anything specific to this release goes below the synced block.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,620 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "a0c750451c14"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "A simple table",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "944306a6da33"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Rooms for the week:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"isNumberColumnEnabled": false,
|
||||||
|
"layout": "align-start",
|
||||||
|
"localId": "92b28760-e51b-436d-82f0-45c6b6bf5b60"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "d53d5ad740cb"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "a8c82e01543e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "00c1bde1a44d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "Room",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "c736c185bcd0"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "3dc846d8aaf9"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "Capacity",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b484834a890d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "5b0671aadeed"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "Notes",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableRow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "45395ea36f04"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "8b19b08b6a93"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "363cf87d44be"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "North",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e189034484f3"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "42a5bad514ea"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "12",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "9cfc78f9a553"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "2ae747c00211"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Projector",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableRow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "8bc7abba3229"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "0e7980a31697"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "a001411b475e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "South",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e61493f2b3d9"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "79c522faf7e8"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "8",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "db911772081a"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "6721e0a4f29f"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Quiet corner",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableRow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "c21221cbaeda"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "A richer table",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b9cdc4e693ca"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Budget by season, with merged, coloured and resized cells:",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"isNumberColumnEnabled": false,
|
||||||
|
"layout": "align-start",
|
||||||
|
"localId": "ac1b1f4b-3d7a-4cd2-a0a7-05ece633ba69"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "c411338ed251"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"background": "#b3d4ff",
|
||||||
|
"colwidth": [
|
||||||
|
135
|
||||||
|
],
|
||||||
|
"localId": "798f1dea331f"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b605b3c1f598"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "Item",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"colwidth": [
|
||||||
|
233
|
||||||
|
],
|
||||||
|
"localId": "db4768c076d4"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b4890b2d833e"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "Spring",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"colwidth": [
|
||||||
|
184
|
||||||
|
],
|
||||||
|
"localId": "4dde2fbfb921"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "7986b41ed947"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "Autumn",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableRow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b4ac97bec992"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"colwidth": [
|
||||||
|
135
|
||||||
|
],
|
||||||
|
"localId": "ba92b57558d8"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "f23f030e9233"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Venue",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"background": "#abf5d1",
|
||||||
|
"colspan": 2,
|
||||||
|
"colwidth": [
|
||||||
|
233,
|
||||||
|
184
|
||||||
|
],
|
||||||
|
"localId": "51af31d44baa"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "ba55f45dc035"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Booked for both",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableRow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e911af70b656"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"colwidth": [
|
||||||
|
135
|
||||||
|
],
|
||||||
|
"localId": "50a820456456"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "b04d0749aee7"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Catering",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"colwidth": [
|
||||||
|
233
|
||||||
|
],
|
||||||
|
"localId": "d0cc276de239"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "90211ae7a504"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "400",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"colwidth": [
|
||||||
|
184
|
||||||
|
],
|
||||||
|
"localId": "1962d05e8763"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "221cf059e38d"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "450",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableRow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "2c8a06942ac4"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"colwidth": [
|
||||||
|
135
|
||||||
|
],
|
||||||
|
"localId": "ba4e1cb93e92"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e6bb346c5fd4"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Notes",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableHeader"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"colwidth": [
|
||||||
|
233
|
||||||
|
],
|
||||||
|
"localId": "d7a1dec97b03"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "5cbd8813deab"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Spring is confirmed.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"colwidth": [
|
||||||
|
184
|
||||||
|
],
|
||||||
|
"localId": "85f9a8dab00b"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "da90346e9a26",
|
||||||
|
"title": "Payment terms"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "ef6c6f374bca"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Invoices arrive monthly.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "nestedExpand"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableCell"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "tableRow"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "table"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "10d03e65eff2"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Figures are estimates.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "26d50a5240c3"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Action items",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "f8b236b2-3b7c-412a-a0df-6c523af43a76"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "eebe3cb9-5773-4753-b6a3-5a5df104b6e8",
|
||||||
|
"state": "DONE"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Book the meeting room",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "taskItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "2263a39a-c49c-4711-8f00-cca6e8f3ea35",
|
||||||
|
"state": "TODO"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Order name badges",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "taskItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "e323e762-8880-43c0-945d-17a7341fdefb"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "55523903-9f79-4711-b276-ec1bc98be977",
|
||||||
|
"state": "DONE"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Print a spare set for the front desk",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "taskItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "taskList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "680d665a-a859-4345-b032-d5a46fd6db0d",
|
||||||
|
"state": "TODO"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Send the agenda to everyone",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "taskItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "48d45b93-2180-4b80-b0ed-f9eb458ed1ed",
|
||||||
|
"state": "TODO"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Ask ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"accessLevel": "",
|
||||||
|
"id": "712020:78bf5058-bc76-4783-99af-6d70cb593cee",
|
||||||
|
"localId": "09321e9b-b551-48ee-8868-5339e8b86863",
|
||||||
|
"text": "@Larvit Developer"
|
||||||
|
},
|
||||||
|
"type": "mention"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " about parking by ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "16c6b2a1718e",
|
||||||
|
"timestamp": "1792022400000"
|
||||||
|
},
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " ",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "taskItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "taskList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "90a7d38e3ed7"
|
||||||
|
},
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "8c510497da2e"
|
||||||
|
},
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "3b52fc685167"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Decisions",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "82dbc28b-49c8-428c-8c21-65cc000ef7c5"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "2f7a7680-2c41-4b45-9162-29d97f922a7b",
|
||||||
|
"state": "DECIDED"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Hold the kickoff on the second floor",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "decisionItem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "c94ef59b-6db4-4ddc-8d22-576821020306",
|
||||||
|
"state": "DECIDED"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Keep the budget under the agreed limit",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "decisionItem"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "decisionList"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "562121f961a8"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Done items are ticked; the rest are still open.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,288 @@
|
|||||||
|
{
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"level": 2,
|
||||||
|
"localId": "ef39f25be439"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Text formatting",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "heading"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "4a24d2441f4b"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "This sentence has ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "bold",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": ", ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "em"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "italic",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": ", ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "underline"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "underlined",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": ", ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strike"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "struck",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " and ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "code"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "inline code",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " words in it.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "707e9aa736b2"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Water is H",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"type": "sub"
|
||||||
|
},
|
||||||
|
"type": "subsup"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "2",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "O and the room measures 20 m",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"type": "sup"
|
||||||
|
},
|
||||||
|
"type": "subsup"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "2",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": ".",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "a03bd1fe3442"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Some words are ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "#ff5630"
|
||||||
|
},
|
||||||
|
"type": "textColor"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "red",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": ", some are ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "#0747a6"
|
||||||
|
},
|
||||||
|
"type": "textColor"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "bold blue",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": ", and one is ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "#f8e6a0"
|
||||||
|
},
|
||||||
|
"type": "backgroundColor"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "highlighted",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": ".",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "f3a744347f56"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "A ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "em"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "strong"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "bold italic",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " phrase, and a ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"type": "strike"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "underline"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "struck underlined",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " one.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"localId": "643a019d97c1"
|
||||||
|
},
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"text": "Read the ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "https://spec.commonmark.org/0.31.2/"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "CommonMark spec",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " or the ",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"marks": [
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"href": "https://www.markdownguide.org/basic-syntax/"
|
||||||
|
},
|
||||||
|
"type": "link"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"text": "basic syntax guide",
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": " before you edit.",
|
||||||
|
"type": "text"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "paragraph"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "doc",
|
||||||
|
"version": 1
|
||||||
|
}
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
- Bolt
|
- Bolt
|
||||||
|
|
||||||
::listBreak
|
!adf:listBreak
|
||||||
|
|
||||||
- Nut
|
- Nut
|
||||||
|
|
||||||
1. Cut
|
1. Cut
|
||||||
|
|
||||||
::listBreak
|
!adf:listBreak
|
||||||
|
|
||||||
1. Weld
|
1. Weld
|
||||||
|
|
||||||
:::panel info
|
!adf:panel info
|
||||||
- Left
|
- Left
|
||||||
::listBreak
|
!adf:listBreak
|
||||||
- Right
|
- Right
|
||||||
:::
|
!adf:/panel
|
||||||
|
|
||||||
- - Head
|
- - Head
|
||||||
|
|
||||||
::listBreak
|
!adf:listBreak
|
||||||
|
|
||||||
- Tail
|
- Tail
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
:::paragraph {localId=01a03d5c-9b21-73f4-8e6a-0c47b1d9e2f8}
|
!adf:paragraph {localId=01a03d5c-9b21-73f4-8e6a-0c47b1d9e2f8}
|
||||||
Every block node in the schema carries one.
|
Every block node in the schema carries one.
|
||||||
:::
|
!adf:/paragraph
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
::::layoutSection {localId=01a033d0-1393-790b-9d44-c572033ea4aa marks="[{\"attrs\":{\"mode\":\"wide\"},\"type\":\"breakout\"}]"}
|
!adf:layoutSection {localId=01a033d0-1393-790b-9d44-c572033ea4aa marks="[{\"attrs\":{\"mode\":\"wide\"},\"type\":\"breakout\"}]"}
|
||||||
:::layoutColumn {width=100}
|
!adf:layoutColumn {width=100}
|
||||||
Full width.
|
Full width.
|
||||||
:::
|
!adf:/layoutColumn
|
||||||
::::
|
!adf:/layoutSection
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
:::codeBlock {language=adf}
|
|
||||||
```
|
|
||||||
{
|
|
||||||
"type": "blockCard"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
:::
|
|
||||||
|
|
||||||
:::codeBlock {language=adf}
|
|
||||||
````
|
|
||||||
```
|
|
||||||
````
|
|
||||||
:::
|
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
},
|
},
|
||||||
"content": [
|
"content": [
|
||||||
{
|
{
|
||||||
"text": ":::",
|
"text": "!adf:/codeBlock",
|
||||||
"type": "text"
|
"type": "text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
:::codeBlock {hideLineNumbers=true localId=01a0431d-201b-70a7-81fa-8d0072e09eab uniqueId=4478e39c wrap=true}
|
!adf:codeBlock {hideLineNumbers=true localId=01a0431d-201b-70a7-81fa-8d0072e09eab uniqueId=4478e39c wrap=true}
|
||||||
```rust
|
```rust
|
||||||
fn main() {}
|
fn main() {}
|
||||||
```
|
```
|
||||||
:::
|
!adf:/codeBlock
|
||||||
|
|
||||||
:::codeBlock {language="a\u0060b"}
|
!adf:codeBlock {language="a\u0060b"}
|
||||||
```
|
```
|
||||||
x
|
x
|
||||||
```
|
```
|
||||||
:::
|
!adf:/codeBlock
|
||||||
|
|
||||||
:::codeBlock {language=" sql"}
|
!adf:codeBlock {language=" sql"}
|
||||||
```
|
```
|
||||||
SELECT 1
|
SELECT 1
|
||||||
```
|
```
|
||||||
:::
|
!adf:/codeBlock
|
||||||
|
|
||||||
:::codeBlock {language="\u0026#97;df"}
|
!adf:codeBlock {language="\u0026#97;df"}
|
||||||
```
|
```
|
||||||
y
|
y
|
||||||
```
|
```
|
||||||
:::
|
!adf:/codeBlock
|
||||||
|
|
||||||
::::panel info
|
!adf:panel info
|
||||||
:::codeBlock {wrap=true}
|
!adf:codeBlock {wrap=true}
|
||||||
```text
|
```text
|
||||||
:::
|
!adf:/codeBlock
|
||||||
```
|
```
|
||||||
:::
|
!adf:/codeBlock
|
||||||
::::
|
!adf:/panel
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@
|
|||||||
"content": [
|
"content": [
|
||||||
{
|
{
|
||||||
"attrs": {
|
"attrs": {
|
||||||
"language": "adf"
|
"language": "carry"
|
||||||
},
|
},
|
||||||
"content": [
|
"content": [
|
||||||
{
|
{
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"attrs": {
|
"attrs": {
|
||||||
"language": "adf"
|
"language": "carry"
|
||||||
},
|
},
|
||||||
"content": [
|
"content": [
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
!adf:codeBlock {language=carry}
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"type": "blockCard"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
!adf:/codeBlock
|
||||||
|
|
||||||
|
!adf:codeBlock {language=carry}
|
||||||
|
````
|
||||||
|
```
|
||||||
|
````
|
||||||
|
!adf:/codeBlock
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
:::codeBlock {language=""}
|
!adf:codeBlock {language=""}
|
||||||
```
|
```
|
||||||
cargo build --release
|
cargo build --release
|
||||||
```
|
```
|
||||||
:::
|
!adf:/codeBlock
|
||||||
|
|||||||
@@ -133,6 +133,14 @@
|
|||||||
},
|
},
|
||||||
"type": "rule"
|
"type": "rule"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"attrs": {
|
||||||
|
"color": "#ff5630",
|
||||||
|
"style": "dashed",
|
||||||
|
"weight": 2
|
||||||
|
},
|
||||||
|
"type": "rule"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"attrs": {
|
"attrs": {
|
||||||
"localId": "01a0431d-201a-7a65-bea7-84b441c85bd6"
|
"localId": "01a0431d-201a-7a65-bea7-84b441c85bd6"
|
||||||
|
|||||||
@@ -1,34 +1,37 @@
|
|||||||
:::heading {level=2 localId=01a0431d-2014-737c-a1bf-f9daedab6de3}
|
!adf:heading {level=2 localId=01a0431d-2014-737c-a1bf-f9daedab6de3}
|
||||||
Release checklist
|
Release checklist
|
||||||
:::
|
!adf:/heading
|
||||||
|
|
||||||
:::paragraph {marks="[{\"attrs\":{\"align\":\"center\"},\"type\":\"alignment\"}]"}
|
!adf:paragraph {marks="[{\"attrs\":{\"align\":\"center\"},\"type\":\"alignment\"}]"}
|
||||||
Centred.
|
Centred.
|
||||||
:::
|
!adf:/paragraph
|
||||||
|
|
||||||
::::bulletList {localId=01a0431d-2015-737f-afad-33064295ad4f}
|
!adf:bulletList {localId=01a0431d-2015-737f-afad-33064295ad4f}
|
||||||
:::listItem {localId=01a0431d-2016-7abb-823f-c0942934c878}
|
!adf:listItem {localId=01a0431d-2016-7abb-823f-c0942934c878}
|
||||||
Tag the commit
|
Tag the commit
|
||||||
:::
|
!adf:/listItem
|
||||||
:::listItem
|
!adf:listItem
|
||||||
Push the tag
|
Push the tag
|
||||||
:::
|
!adf:/listItem
|
||||||
::::
|
!adf:/bulletList
|
||||||
|
|
||||||
::::orderedList
|
!adf:orderedList
|
||||||
:::listItem
|
!adf:listItem
|
||||||
Loosen the clamp
|
Loosen the clamp
|
||||||
:::
|
!adf:/listItem
|
||||||
::::
|
!adf:/orderedList
|
||||||
|
|
||||||
> :::paragraph {localId=01a0431d-2017-72cf-baf3-8934a54e0582}
|
> !adf:paragraph {localId=01a0431d-2017-72cf-baf3-8934a54e0582}
|
||||||
> Hold the line.
|
> Hold the line.
|
||||||
> :::
|
> !adf:/paragraph
|
||||||
|
|
||||||
- :::paragraph {localId=01a0431d-2018-7667-a769-ab0037ca80aa}
|
- !adf:paragraph {localId=01a0431d-2018-7667-a769-ab0037ca80aa}
|
||||||
Indented.
|
Indented.
|
||||||
:::
|
!adf:/paragraph
|
||||||
|
|
||||||
::rule {localId=01a0431d-2019-76b7-bf6f-13841363b111}
|
!adf:rule {localId=01a0431d-2019-76b7-bf6f-13841363b111}
|
||||||
|
|
||||||
::paragraph {localId=01a0431d-201a-7a65-bea7-84b441c85bd6}
|
!adf:rule {color="#ff5630" style=dashed weight=2}
|
||||||
|
|
||||||
|
!adf:paragraph {localId=01a0431d-201a-7a65-bea7-84b441c85bd6}
|
||||||
|
!adf:/paragraph
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
:::heading {level=7}
|
!adf:heading {level=7}
|
||||||
Seventh
|
Seventh
|
||||||
:::
|
!adf:/heading
|
||||||
|
|
||||||
:::heading
|
!adf:heading
|
||||||
Levelless
|
Levelless
|
||||||
:::
|
!adf:/heading
|
||||||
|
|
||||||
::::orderedList {order=999999998}
|
!adf:orderedList {order=999999998}
|
||||||
:::listItem
|
!adf:listItem
|
||||||
One
|
One
|
||||||
:::
|
!adf:/listItem
|
||||||
:::listItem
|
!adf:listItem
|
||||||
Two
|
Two
|
||||||
:::
|
!adf:/listItem
|
||||||
:::listItem
|
!adf:listItem
|
||||||
Three
|
Three
|
||||||
:::
|
!adf:/listItem
|
||||||
::::
|
!adf:/orderedList
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
::::expand {title="Full build log"}
|
!adf:expand {title="Full build log"}
|
||||||
The build ran for 11 minutes.
|
The build ran for 11 minutes.
|
||||||
:::panel warning
|
!adf:panel warning
|
||||||
Three warnings went unread.
|
Three warnings went unread.
|
||||||
:::
|
!adf:/panel
|
||||||
::::
|
!adf:/expand
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
::::panel info
|
!adf:panel info
|
||||||
- :::panel warning
|
- !adf:panel warning
|
||||||
Check the torque before signing off.
|
Check the torque before signing off.
|
||||||
:::
|
!adf:/panel
|
||||||
- - :::expand {title="Deeper still"}
|
- - !adf:expand {title="Deeper still"}
|
||||||
Two list levels down.
|
Two list levels down.
|
||||||
:::
|
!adf:/expand
|
||||||
|
|
||||||
> :::expand {title="Full build log"}
|
> !adf:expand {title="Full build log"}
|
||||||
> The build ran for 11 minutes.
|
> The build ran for 11 minutes.
|
||||||
> :::
|
> !adf:/expand
|
||||||
>
|
>
|
||||||
> :::panel note
|
> !adf:panel note
|
||||||
> Superseded by the next run.
|
> Superseded by the next run.
|
||||||
> :::
|
> !adf:/panel
|
||||||
::::
|
!adf:/panel
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
::::decisionList {localId=01a033c4-7aa0-723f-bd4b-018e0aa0103f}
|
!adf:decisionList {localId=01a033c4-7aa0-723f-bd4b-018e0aa0103f}
|
||||||
:::decisionItem {localId=01a033c8-0df4-74df-a9f4-c2c4aa3cc2c1 state=DECIDED}
|
!adf:decisionItem {localId=01a033c8-0df4-74df-a9f4-c2c4aa3cc2c1 state=DECIDED}
|
||||||
Ship on Friday.
|
Ship on Friday.
|
||||||
:::
|
!adf:/decisionItem
|
||||||
:::decisionItem {localId=01a033cb-e13c-79b2-933f-b3cedd57e33e state=DECIDED}
|
!adf:decisionItem {localId=01a033cb-e13c-79b2-933f-b3cedd57e33e state=DECIDED}
|
||||||
Keep the old endpoint for one release.
|
Keep the old endpoint for one release.
|
||||||
:::
|
!adf:/decisionItem
|
||||||
::::
|
!adf:/decisionList
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
:::expand {title="Full build log"}
|
!adf:expand {title="Full build log"}
|
||||||
The build ran for 11 minutes.
|
The build ran for 11 minutes.
|
||||||
|
|
||||||
Warnings: 3.
|
Warnings: 3.
|
||||||
:::
|
!adf:/expand
|
||||||
|
|
||||||
:::nestedExpand {localId=01a03382-2ca7-745c-b85d-49b84d32cf99 title="Torque values"}
|
!adf:nestedExpand {localId=01a03382-2ca7-745c-b85d-49b84d32cf99 title="Torque values"}
|
||||||
Bolt M8: 25 Nm.
|
Bolt M8: 25 Nm.
|
||||||
:::
|
!adf:/nestedExpand
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
::extension {extensionKey=toc extensionType="com.atlassian.confluence.macro.core" parameters="{\"maxLevel\":2,\"minLevel\":1}" text="Table of contents"}
|
!adf:extension {extensionKey=toc extensionType="com.atlassian.confluence.macro.core" parameters="{\"maxLevel\":2,\"minLevel\":1}" text="Table of contents"}
|
||||||
|
|
||||||
:::bodiedExtension {extensionKey=note extensionType="com.atlassian.confluence.macro.core" layout=default localId=01a033d4-123e-70ec-9a9c-f55f189b3cf7}
|
!adf:bodiedExtension {extensionKey=note extensionType="com.atlassian.confluence.macro.core" layout=default localId=01a033d4-123e-70ec-9a9c-f55f189b3cf7}
|
||||||
Handle with care.
|
Handle with care.
|
||||||
:::
|
!adf:/bodiedExtension
|
||||||
|
|
||||||
::::multiBodiedExtension {extensionKey=tabs extensionType="com.atlassian.confluence.macro.core" localId=01a033de-845f-70e2-abcf-cd5d23ba6101}
|
!adf:multiBodiedExtension {extensionKey=tabs extensionType="com.atlassian.confluence.macro.core" localId=01a033de-845f-70e2-abcf-cd5d23ba6101}
|
||||||
:::extensionFrame
|
!adf:extensionFrame
|
||||||
Tab one.
|
Tab one.
|
||||||
:::
|
!adf:/extensionFrame
|
||||||
:::extensionFrame
|
!adf:extensionFrame
|
||||||
Tab two.
|
Tab two.
|
||||||
:::
|
!adf:/extensionFrame
|
||||||
::::
|
!adf:/multiBodiedExtension
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
::::mediaSingle {layout=center}
|
!adf:mediaSingle {layout=center}
|
||||||
::media {alt="The moon, at night." type=external url="https://example.com/moon.png"}
|
!adf:media {alt="The moon, at night." type=external url="https://example.com/moon.png"}
|
||||||
:::caption
|
!adf:caption
|
||||||
Taken from Kiruna.
|
Taken from Kiruna.
|
||||||
:::
|
!adf:/caption
|
||||||
::::
|
!adf:/mediaSingle
|
||||||
|
|
||||||
:::mediaSingle {layout=center localId=01a03394-6721-7075-bd6e-fd9a57b64b56}
|
!adf:mediaSingle {layout=center localId=01a03394-6721-7075-bd6e-fd9a57b64b56}
|
||||||
::media {alt="Torque chart" type=external url="https://example.com/torque.png"}
|
!adf:media {alt="Torque chart" type=external url="https://example.com/torque.png"}
|
||||||
:::
|
!adf:/mediaSingle
|
||||||
|
|
||||||
:::mediaSingle {layout=center}
|
!adf:mediaSingle {layout=center}
|
||||||
::media {height=480 type=external url="https://example.com/plan.png" width=640}
|
!adf:media {height=480 type=external url="https://example.com/plan.png" width=640}
|
||||||
:::
|
!adf:/mediaSingle
|
||||||
|
|
||||||
:::mediaSingle {layout=center}
|
!adf:mediaSingle {layout=center}
|
||||||
::media {alt="The assembly drawing" marks="[{\"attrs\":{\"href\":\"https://example.com/assembly\"},\"type\":\"link\"}]" type=external url="https://example.com/assembly.png"}
|
!adf:media {alt="The assembly drawing" marks="[{\"attrs\":{\"href\":\"https://example.com/assembly\"},\"type\":\"link\"}]" type=external url="https://example.com/assembly.png"}
|
||||||
:::
|
!adf:/mediaSingle
|
||||||
|
|
||||||
:::mediaSingle {layout=center}
|
!adf:mediaSingle {layout=center}
|
||||||
::media {alt="" type=external url="https://example.com/moon.png"}
|
!adf:media {alt="" type=external url="https://example.com/moon.png"}
|
||||||
:::
|
!adf:/mediaSingle
|
||||||
|
|
||||||
:::mediaSingle {layout=center}
|
!adf:mediaSingle {layout=center}
|
||||||
::media {type=external url="https://example.com/plan.png?a=1\u0026amp;b=2"}
|
!adf:media {type=external url="https://example.com/plan.png?a=1\u0026amp;b=2"}
|
||||||
:::
|
!adf:/mediaSingle
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"content": [
|
"content": [
|
||||||
{
|
{
|
||||||
"attrs": {
|
"attrs": {
|
||||||
|
"columnRuleStyle": "solid",
|
||||||
"localId": "01a033cc-4b60-7b5e-85f4-34f27f039e9a"
|
"localId": "01a033cc-4b60-7b5e-85f4-34f27f039e9a"
|
||||||
},
|
},
|
||||||
"content": [
|
"content": [
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
::::layoutSection {localId=01a033cc-4b60-7b5e-85f4-34f27f039e9a}
|
!adf:layoutSection {columnRuleStyle=solid localId=01a033cc-4b60-7b5e-85f4-34f27f039e9a}
|
||||||
:::layoutColumn {localId=01a03389-a5fb-747d-b418-e91f1b161e7f width=50}
|
!adf:layoutColumn {localId=01a03389-a5fb-747d-b418-e91f1b161e7f width=50}
|
||||||
Left.
|
Left.
|
||||||
:::
|
!adf:/layoutColumn
|
||||||
:::layoutColumn {valign=top width=50}
|
!adf:layoutColumn {valign=top width=50}
|
||||||
Right.
|
Right.
|
||||||
:::
|
!adf:/layoutColumn
|
||||||
::::
|
!adf:/layoutSection
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
:::mediaGroup
|
!adf:mediaGroup
|
||||||
::media {collection=contentId-98237 id=01a03387-e300-7bcf-9a41-c27760696449 occurrenceKey=01a0338a-2f44-764f-a7b7-1c1a2abbb49b type=file}
|
!adf:media {collection=contentId-98237 id=01a03387-e300-7bcf-9a41-c27760696449 occurrenceKey=01a0338a-2f44-764f-a7b7-1c1a2abbb49b type=file}
|
||||||
::media {collection=contentId-98237 id=01a03393-0b0b-71f6-89cd-dd654f42cf34 type=link}
|
!adf:media {collection=contentId-98237 id=01a03393-0b0b-71f6-89cd-dd654f42cf34 type=link}
|
||||||
:::
|
!adf:/mediaGroup
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
::::mediaSingle {layout=center width=50}
|
!adf:mediaSingle {layout=center width=50}
|
||||||
::media {collection=MediaServicesSample id=4478e39c-cf9b-41d1-ba92-68589487cd75 type=file}
|
!adf:media {collection=MediaServicesSample id=4478e39c-cf9b-41d1-ba92-68589487cd75 type=file}
|
||||||
:::caption {localId=01a03389-670b-7331-ae60-0446747ace7a}
|
!adf:caption {localId=01a03389-670b-7331-ae60-0446747ace7a}
|
||||||
The moon, at night.
|
The moon, at night.
|
||||||
:::
|
!adf:/caption
|
||||||
::::
|
!adf:/mediaSingle
|
||||||
|
|
||||||
:::mediaSingle {layout=wrap-right width="33.33" widthType=percentage}
|
!adf:mediaSingle {layout=wrap-right width="33.33" widthType=percentage}
|
||||||
::media {alt="Torque chart" height=480 localId=01a03389-8683-7c05-bfbb-457bcdb0ced3 type=external url="https://example.com/torque.png" width=640}
|
!adf:media {alt="Torque chart" height=480 localId=01a03389-8683-7c05-bfbb-457bcdb0ced3 type=external url="https://example.com/torque.png" width=640}
|
||||||
:::
|
!adf:/mediaSingle
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@
|
|||||||
},
|
},
|
||||||
"content": [
|
"content": [
|
||||||
{
|
{
|
||||||
"text": ":::::::panel warning\n:::",
|
"text": "!adf:panel warning\n!adf:/panel",
|
||||||
"type": "text"
|
"type": "text"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
!adf:table
|
||||||
|
!adf:tableRow
|
||||||
|
!adf:tableCell
|
||||||
|
!adf:nestedExpand {title="Torque values"}
|
||||||
|
Bolt M8: 25 Nm.
|
||||||
|
!adf:/nestedExpand
|
||||||
|
!adf:/tableCell
|
||||||
|
!adf:tableCell
|
||||||
|
```text
|
||||||
|
!adf:panel warning
|
||||||
|
!adf:/panel
|
||||||
|
```
|
||||||
|
!adf:/tableCell
|
||||||
|
!adf:/tableRow
|
||||||
|
!adf:/table
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
::::::table
|
|
||||||
:::::tableRow
|
|
||||||
::::tableCell
|
|
||||||
:::nestedExpand {title="Torque values"}
|
|
||||||
Bolt M8: 25 Nm.
|
|
||||||
:::
|
|
||||||
::::
|
|
||||||
:::tableCell
|
|
||||||
```text
|
|
||||||
:::::::panel warning
|
|
||||||
:::
|
|
||||||
```
|
|
||||||
:::
|
|
||||||
:::::
|
|
||||||
::::::
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
:::panel warning
|
!adf:panel warning
|
||||||
Check the collation before importing.
|
Check the collation before importing.
|
||||||
:::
|
!adf:/panel
|
||||||
|
|
||||||
:::panel info {localId=01a0337c-561a-75aa-b629-3801f68839ad}
|
!adf:panel info {localId=01a0337c-561a-75aa-b629-3801f68839ad}
|
||||||
Backups run at 02:00.
|
Backups run at 02:00.
|
||||||
:::
|
!adf:/panel
|
||||||
|
|
||||||
:::panel custom {panelColor="#c9372c" panelIcon=":rainbow:" panelIconId=1f308 panelIconText="🌈"}
|
!adf:panel custom {panelColor="#c9372c" panelIcon=":rainbow:" panelIconId=1f308 panelIconText="🌈"}
|
||||||
Weather permitting.
|
Weather permitting.
|
||||||
:::
|
!adf:/panel
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
::syncBlock {localId=0198f3a2-af74-7e91-b26c-70b15f4d9ec3 resourceId="ari:cloud:confluence:site/page/123"}
|
!adf:syncBlock {localId=0198f3a2-af74-7e91-b26c-70b15f4d9ec3 resourceId="ari:cloud:confluence:site/page/123"}
|
||||||
|
|
||||||
:::bodiedSyncBlock {localId=01a033df-0dee-7251-a710-98e76dc285e4 resourceId="ari:cloud:confluence:site/page/456"}
|
!adf:bodiedSyncBlock {localId=01a033df-0dee-7251-a710-98e76dc285e4 resourceId="ari:cloud:confluence:site/page/456"}
|
||||||
Shared release notes.
|
Shared release notes.
|
||||||
:::
|
!adf:/bodiedSyncBlock
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
:::::table {displayMode=fixed isNumberColumnEnabled=true layout=default localId=01a0339e-c34f-7658-9d98-eb059401b7ab width=760}
|
!adf:table {displayMode=fixed isNumberColumnEnabled=true layout=default localId=01a0339e-c34f-7658-9d98-eb059401b7ab width=760}
|
||||||
::::tableRow
|
!adf:tableRow
|
||||||
:::tableHeader {colspan=2 colwidth="[340,420]"}
|
!adf:tableHeader {colspan=2 colwidth="[340,420]"}
|
||||||
Assembly
|
Assembly
|
||||||
:::
|
!adf:/tableHeader
|
||||||
::::
|
!adf:/tableRow
|
||||||
::::tableRow {localId=01a033a9-d034-7466-b916-68643be958ff}
|
!adf:tableRow {localId=01a033a9-d034-7466-b916-68643be958ff}
|
||||||
:::tableCell {background="#deebff" localId=01a03389-c573-72a6-a036-6cd9c6865301 rowspan=2}
|
!adf:tableCell {background="#deebff" localId=01a03389-c573-72a6-a036-6cd9c6865301 rowspan=2}
|
||||||
Bolt M8
|
Bolt M8
|
||||||
:::
|
!adf:/tableCell
|
||||||
:::tableCell {valign=top}
|
!adf:tableCell {valign=top}
|
||||||
40
|
40
|
||||||
:::
|
!adf:/tableCell
|
||||||
::::
|
!adf:/tableRow
|
||||||
::::tableRow
|
!adf:tableRow
|
||||||
:::tableCell
|
!adf:tableCell
|
||||||
60
|
60
|
||||||
:::
|
!adf:/tableCell
|
||||||
::::
|
!adf:/tableRow
|
||||||
:::::
|
!adf:/table
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
:::::table
|
!adf:table
|
||||||
::::tableRow
|
!adf:tableRow
|
||||||
:::tableHeader
|
!adf:tableHeader
|
||||||
Pattern
|
Pattern
|
||||||
:::
|
!adf:/tableHeader
|
||||||
:::tableHeader
|
!adf:tableHeader
|
||||||
Meaning
|
Meaning
|
||||||
:::
|
!adf:/tableHeader
|
||||||
::::
|
!adf:/tableRow
|
||||||
::::tableRow
|
!adf:tableRow
|
||||||
:::tableCell
|
!adf:tableCell
|
||||||
`a|b`
|
`a|b`
|
||||||
:::
|
!adf:/tableCell
|
||||||
:::tableCell
|
!adf:tableCell
|
||||||
Either a or b
|
Either a or b
|
||||||
:::
|
!adf:/tableCell
|
||||||
::::
|
!adf:/tableRow
|
||||||
:::::
|
!adf:/table
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Bolt M8 | Grade `8.8` |
|
| Bolt M8 | Grade `8.8` |
|
||||||
| Nut \| washer | Sold as a pair |
|
| Nut \| washer | Sold as a pair |
|
||||||
| Washer M8 | 100 pcs:hardBreak{}zinc-plated |
|
| Washer M8 | 100 pcs!adf:hardBreak{}zinc-plated |
|
||||||
| :text{text=" "}Spare | |
|
| !adf:text{text=" "}Spare | |
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user