Compare commits

...

331 Commits

Author SHA1 Message Date
Nicholas Reid b8570137b6
Update README.md (#560)
Added Golang library that supports both v1 and v2, and passes kdl-rs and kdl-test.
2026-04-17 12:32:01 -07:00
Brandon Chinn 4e4c0af933
Fix multi-line-string-body grammar (#552)
* Make multi-line-string-body non-greedy

* Don't require string-character after quotes in multiline strings

* Prevent accidentally consuming triple quotes in multi-line-string-body

* Add test cases
2026-03-25 09:59:25 -07:00
Astrusia 568d103308
Added KdlSharp to readme README.md (#551)
since Kadlet is not maintained, I proposed adding KdlSharp for v2 users in a [discussion](https://github.com/kdl-org/kdl/discussions/550)

I also added the requirements in the note (from KdlSharp README.MD). I abbreviated them to fit in the width of the table.

I hope the style is fine
2026-03-23 13:59:14 -07:00
Evgeny 5f73be73c7
Add Ferron to the list of examples (#557) 2026-03-20 15:29:46 -07:00
Brandon Chinn 54a49798d9
Mark kdl-hs as v2 compliant (#555) 2026-02-23 14:30:41 -08:00
Louis Pearson 0ff5a6ffa3
Add Zig support to README compatibility table (#554) 2026-02-10 09:19:04 -08:00
remexre 3b75764880
Assorted spelling fixes. (#548) 2026-01-12 13:41:57 -08:00
Brandon Chinn f238372fc9
Add kdl-hs to Haskell implementations (#547) 2026-01-03 08:43:12 -08:00
Tab Atkins Jr. d8faf22503
Fix link to spec 2025-10-14 16:33:27 -07:00
Adam Naji ebf9ef7649
docs: adds missing Typescript DOM generator (#540) 2025-07-31 09:51:33 -07:00
Kainoa Kanter 5366787152
docs: add link to Zed extension (#539) 2025-07-30 19:30:02 -07:00
Romain Delamare 85930fd8dd
Kdl4J now supports KDL v2 (#538) 2025-07-14 09:01:34 -07:00
lolbinarycat 8e18add9d4
KQL: fix link to KDL grammar (#530) 2025-06-11 09:58:40 -07:00
Tab Atkins Jr. 43d8a5dbf3
lint error 2025-06-04 13:47:41 -07:00
Tab Atkins Jr. 5d82f60407
Disallow -inf from being a signed-ident
Just moving the `- disallowed-keyword-identifiers` up to the parent production so it catches all the ident productions, to make any similar mistakes impossible.
2025-06-04 13:45:30 -07:00
Dion Dokter ab92232126
Fix typo in XML-IN-KDL.md (#524)
* Fix typo in XML-IN-KDL.md

* Update XML-IN-KDL.md

---------

Co-authored-by: Tab Atkins Jr. <jackalmage@gmail.com>
2025-05-17 09:09:04 -07:00
lolbinarycat 5e5920fd7c
Update draft-marchan-kdl2.md (#519)
disallowed-keyword-identifiers was referred to as disallowed-keyword-strings
2025-05-09 13:10:34 -07:00
Tab Atkins Jr. 11615b2807
Clarify what it means for digits to be separated by underscores. (#517) 2025-04-28 12:33:48 -07:00
Tab Atkins Jr. 42ce272508
Actually state in the normative portion how whitespace-only lines are treated. Related to #515 (#516)
* Actually state in the normative portion how whitespace-only lines are treated. Related to #515

* lint
2025-04-28 11:45:55 -07:00
Romain Delamare a88c450d7d
rename test case to better describe error (#509) 2025-02-25 11:21:42 -08:00
Bram Gotink b942867c58
Make whitespace required around query operators (#500) 2025-02-18 15:19:19 -08:00
Bram Gotink ee79f9f755
Escape U+200E and U+200F (#506)
Fixes #502
2025-02-18 15:18:18 -08:00
Lars Willighagen 84911feb11
Remove mandatory node-space before slashdash and children block (#499)
* Remove mandatory node-space before slashdash

Fix #495

* Add tests

* Fix more tests

* Fix tests again
2025-01-28 16:48:09 -08:00
Bram Gotink c54ebd9473
Align test formatting (#501)
Other tests don't have quotes around strings if the string
is a valid identifier, this test is the odd one out.
2025-01-28 16:45:14 -08:00
Lars Willighagen 6c55186c03
Add link to Kate Editor Support (#498) 2025-01-23 12:30:47 -08:00
Kat Marchán 21a9eb3f65
actual tweaks, plus some automatic reformatting (#497) 2025-01-22 22:40:36 -08:00
Kat Marchán aab44fcd1b
minor tweaks to wording/clarifications (#484) 2025-01-22 16:52:12 -08:00
Evgeny d76063e8e9
Exclude hex above max Unicode Scalar Value (#456)
* Exclude hex above max Unicode Scalar Value

simplify surrogate regex to use ranges

* allow leading 0s, but still limit max length to 6

* Add explicit regex-set rules to hex unicode

document {1,3} ranges

* add space-separators between sets

* Make test fail *only* for length limits

Previously it failed due to specifying a codepoint past max *as well*, obscuring the intended fail condition.

---------

Co-authored-by: Tab Atkins Jr. <jackalmage@gmail.com>
2025-01-21 09:16:45 -08:00
Kat Marchán e9e6a844bd
Add Onyx to list of users 2025-01-21 03:03:56 -08:00
Tab Atkins-Bittner 7322f37800 Add the compact form of html-standard.kdl as a secondary benchmarking point. 2025-01-20 17:29:13 -08:00
Kat Marchán 919e154dcd
UTF-8 is a hard requirement, actually (#490) 2025-01-20 04:13:45 -08:00
Kat Marchán 53a884c93d
Create SPEC.md 2025-01-19 09:45:05 -08:00
Tab Atkins Jr. 23159696d1
Add the html standard, in kdl format, as a large-document benchmark. (#488)
* Add the html standard, in kdl format, as a large-document benchmark.

* Explain the purpose of the benchmarks
2025-01-18 08:58:43 -08:00
Clar Fon 82a91697a1
Fix typo: RFC1123 is the RFC that defines requirements for hostnames (#487) 2025-01-18 01:18:17 -08:00
Jeffrey Yasskin 4263a9de3f
Convert the specification into RFC format (#466)
Fixes: https://github.com/kdl-org/kdl/issues/461

* Initial conversion to Internet-Draft.

* Setup repository for draft-marchan-kdl2 using https://github.com/martinthomson/i-d-template

* Remove unnecessary changes.

* Tweak source to make the I-D build.

* Fix zkat's name. Guess at their preferred initials.

* Separate links where linking text equals the anchor.

This works around https://github.com/cabo/kramdown-rfc/issues/249.

* Replace horizontal rules with subsections.

RFCXML v3 doesn't include horizontal rules.

* Use ~~~kdl  instead of `` for strings with significant whitespace.

That compiles to <sourcecode> which preserves sequences of spaces.

* Give breadcrumbs to the RFC format definitions.

* Point contributors to https://author-tools.ietf.org/.

For if installing the dependencies is inconvenient.

* Separate a code block from adjacent text.

* Remove a workflow that overwrites customized files.

* Remove the 'archive' workflow.

* Use "Term ({{term}})" uniformly instead of just when the term matches the anchor.

* Fix the instructions for preserving the RFCXML.

* Remove the default copyright notice until the spec is relicensed.

* Take the IETF licensing details out of CONTRIBUTING.md.
2025-01-17 21:06:17 -08:00
Tab Atkins Jr. 0c2dde6d3c
Support empty multiline strings (#483)
* Support empty multiline strings

Per <https://github.com/kdl-org/kdl/discussions/481>, the grammar doesn't actually allow the first and last newline in a multiline string to be the same (indicating an empty string). This looks like the minimal fix for it.

* Add tests for empty multilines

* remove accidental newline
2025-01-17 16:28:52 -08:00
Bram Gotink 20375a187e
align prose text on initial identifier characters with grammar (#464) 2025-01-17 09:54:19 -08:00
Dani Smith 91cd421988
update SPEC to keep lines lengths short (#470) 2025-01-17 09:52:28 -08:00
Dani Smith 34e4259dfc
Remove Identifier String termination phrase (#485)
Fixes: https://github.com/kdl-org/kdl/issues/480
2025-01-17 09:18:43 -08:00
Evgeny a3b37857e2
Note Sublime Text support of v2 (#474) 2025-01-12 10:15:51 -08:00
Evgeny 9c9d2b2445
test: add a fail-test braces in bare ids (#477)
or a child block without space separator

current test is inadequate as it has extra fail that can mask this one
2025-01-12 09:17:44 -08:00
Dani Smith 39a098237d
identifier strings can technically be terminated by EOF (#469) 2025-01-09 08:56:33 -08:00
Kat Marchán 1147fe965a
kdljs now supports v2 2025-01-08 09:01:30 -08:00
Lars Willighagen 72a3c769d7
Fix q-ws rule in KQL grammar (#463) 2025-01-05 07:35:37 -08:00
Dani Smith 757eb5517a
Update KDL Play link (#462) 2025-01-04 10:00:12 -08:00
Kat Marchán 2843744a87
Add Iron Vault to users list
Idk why I forgot this one haha
2025-01-02 16:56:31 -08:00
Dani Smith 6d2bc50939
Add Dart v2 to README (#458) 2025-01-02 10:48:36 -08:00
Dani Smith 3b19a761ff
Add 128-bit number formats to Schema spec (#459) 2025-01-02 10:41:34 -08:00
eilvelia ce3b2eeb7f
Show ocaml-kdl v2 support (#457) 2024-12-27 16:27:29 -08:00
Dani Smith 353fd85a2b
Show kdl-rb v2 support (#454) 2024-12-24 02:10:42 -08:00
Evgeny 3c1cf4f2a1
test: add a fail-test for escaped non Unicode Scalar Values (#452)
* test: add a fail-test for escaped non Unicode Scalar Values

* test: split multiple codepoints into 1 per file
2024-12-24 00:14:24 -08:00
Evgeny 76dc3e3002
doc: resolve inconsistency in banned chars in escaped form (#450)
Also add it explicitly to the spec grammar to make it clear that escaped forms are also affected
2024-12-23 23:57:10 -08:00
Bram Gotink 646dafcd35
update vertical tab test (#449) 2024-12-23 11:49:12 -08:00
Kat Marchán c930f1d124
I guess I should probably be more honest here 2024-12-22 13:43:51 -08:00
Evgeny 0f77ec4f9f
doc: change Unicode link to a friendly html version (#448)
(version bumped, but the table is the same)

Spec v1 is missing vertical tab, but that's frozen, so only formatting change
2024-12-22 00:55:53 -08:00
Kat Marchán 6ceecd85d6
Release KDL 2.0.0 (#434)
* Release KDL 2.0.0

* fix grammar for multiline quoted strings to allow escaped whitespace on closing line

* Add unicode-space to raw string

* Remove nonexistent equals-sign from the grammar (#435)

* fix multiline string tests

* grammar: fix disallowed-keyword-identifiers and string-character (#436)

* Back out "fix multiline string tests"

This backs out commit 0c5604b462.

* add extra javascript implementation (#437)

* reword interaction multiline + whitespace escape (#439)

* More tests for backslash behaviour (#438)

* More tests for baskslash behaviour

* Incorrect example of escaped final newline

* Test with non-literal indent

* Make line-space a superset of node-space (#440)

* Allow escline everywhere

* escline tests

* Always escape \ inside single quotes in the grammar text (#441)

to match the other uses of it and the metalanguage description below

* Add tests for mandatory whitespace between arguments or properties (#442)

* Add an optional version marker (#444)

* Add version marker to the grammer

* Add version marker to the Changelog

* Update SPEC.md

Co-authored-by: eilvelia <hi@eilvelia.cat>

* add a mandatory newline after the version marker

* add mandatory space between version number

---------

Co-authored-by: eilvelia <hi@eilvelia.cat>

* Fix a changelog line erroneously truncated in #444 (#445)

* fix: move vertical tab to the line-breaking whitespace to match Unicode (#446)

* add vertical tab change test

* final tweaks before release

---------

Co-authored-by: eilvelia <hi@eilvelia.cat>
Co-authored-by: Bram Gotink <bram@gotink.me>
Co-authored-by: Thomas Jollans <tjol@tjol.eu>
Co-authored-by: Evgeny <eugenesvk@users.noreply.github.com>
2024-12-21 18:33:50 -08:00
Kat Marchán 0e58f61b18
Release 2.0.0-draft.8 2024-12-14 17:23:09 -08:00
Tommy Williams edbdab2891
Update README.md (#383)
swap neovim integration link 
from tree-sitter project to the specific language grammar
2024-12-12 14:58:51 -08:00
Thomas Jollans 7aa01a21b7
Clarify spec for whitespace-only lines in multiline strings (#433) 2024-12-12 14:47:39 -08:00
Thomas Jollans b82c924013
More tests for whitespace in multi-line strings (#432)
* More tests for whitespace in multi-line strings

* replace \r\n with \n in slashdash_newline_before_node.kdl
2024-12-12 13:15:04 -08:00
Tab Atkins Jr. d1ceb44f40
Make the raw-string productions non-greedy, and describe the infallibility (#430)
* Make the raw-string productions non-greedy, and describe the infallibility. Closes #415

* More explicitly use and reference a cut point, rather than infallibility.
2024-12-12 11:08:50 -08:00
Kat Marchán 717e86cb1c
went over tests and tweaked a few things (#431) 2024-12-11 19:45:25 -08:00
Tab Atkins Jr. ebef8751c0
fix multiline_string_whitespace_only, closes #429
ws-only lines don't contribute *any* content to the string (beyond their existence as a newline)
2024-12-11 18:16:00 -08:00
Tab Atkins Jr. ca2bd45a66
typo
Accidental lingering `)` in single-line-raw-string-body, with no matching `(` to pair with.
2024-12-11 16:51:38 -08:00
Kat Marchán 1a6b17b0ae
Minor housekeeping around README 2024-12-11 00:24:41 -08:00
Kat Marchán ace7ec7a96
Release 2.0.0-draft.7 2024-12-10 23:31:07 -08:00
Kat Marchán 171bc71f42
Allow node-space after slashdash and add a bunch more slashdash tests (#427)
Fixes: https://github.com/kdl-org/kdl/issues/426
2024-12-10 20:43:58 -08:00
Thomas Jollans 75a0869a6c
Clarify raw single-line string grammar (#425) 2024-12-10 16:45:35 -08:00
Tab Atkins-Bittner 91f7ec05fa Add a lint for test expectations that don't end in a newline. 2024-12-10 16:03:05 -08:00
Tab Atkins Jr. a60d27c99d
KDL documents always end in a newline
In particular, other empty-document tests have an expected result containing one newline, like slashdash_full_node
2024-12-10 15:55:21 -08:00
Kat Marchán ec7d679e88
Add Camping to Used By section 2024-12-10 14:32:50 -08:00
Kat Marchán 4dd6ebbbfe
Add 'Used By' section to README
Fixes: https://github.com/kdl-org/kdl/issues/408
2024-12-09 02:05:45 -08:00
Kat Marchán 373e0ed973
Pull in v1 spec and add some compatibility notes (#424)
Fixes: https://github.com/kdl-org/kdl/issues/420
2024-12-09 01:27:07 -08:00
Thomas Jollans ee41a76357
Additional test cases for slashdash and multi-line strings (#422) 2024-12-08 09:32:21 -08:00
Thomas Jollans 831ecc1d52
Allow quotes in multi-line strings (#419)
Fixes: https://github.com/kdl-org/kdl/issues/415
2024-12-08 01:07:31 -08:00
Tab Atkins Jr. 29ae90e9f5
Indicate expected-fail tests with a _fail suffix. Fixes #365 (#418)
* Indicate expected-fail tests with a _fail suffix. Fixes #365

* Update the README with directions for formatting failing tests

* Add a lint for failing and orphaned tests.
2024-12-06 15:06:28 -08:00
Tab Atkins Jr. bf40df5581
Make multi-line a top-level string type; demote Raw String. (#417) 2024-12-06 15:06:07 -08:00
Kat Marchán eaa6c40693
fix more multiline string tests that were missed before 2024-12-04 13:08:37 -08:00
Kat Marchán 5971e61eda
fix up some multiline string tests 2024-12-04 00:48:43 -08:00
Kat Marchán 4334a6d552
Release 2.0.0 draft 6 2024-12-04 00:04:21 -08:00
Kat Marchán e7b5ec6bf9
unambiguous multiline strings (#414)
Fixes: https://github.com/kdl-org/kdl/issues/413
2024-12-03 23:44:40 -08:00
Kat Marchán e477f32f05
a few clarifications and wording tweaks to the spec 2024-12-03 23:06:58 -08:00
Emi 40aac6602e
Normalize space in expected output of unicode_silly (#412) 2024-12-02 00:06:46 -08:00
Emi 073d07748a
[tests] [bug] test unicode_silly's input data is a .kd file (#410) 2024-12-01 15:26:00 -08:00
Kat Marchán 1f050633ad
slight grammar tweaks 2024-12-01 01:16:06 -08:00
Kat Marchán 8b2a019998
merge kdl-v2 branch into main 2024-11-29 00:11:01 -08:00
Kat Marchán 8aa4c15758
prep readme for merging to main 2024-11-29 00:01:53 -08:00
Kat Marchán 76a1de517b
Release 2.0.0 draft 5 2024-11-28 23:09:31 -08:00
Kat Marchán 90e22bc789
[v2] more predictable slashdash (#407)
Fixes: https://github.com/kdl-org/kdl/issues/401
2024-11-28 22:53:42 -08:00
Kat Marchán 1588b1f5fd
get rid of syntactically significant unicode equals signs (#400)
Fixes: #399
2024-11-28 22:39:19 -08:00
Kat Marchán fa3050ccc0
add 128-bit ints 2024-11-28 00:06:15 -08:00
Kat Marchán 93c4400a96
clarify that numbers don't need to be IEEE 754 floats 2024-11-27 01:02:02 -08:00
Samuel Giddins d8d583a45e
Create test for unterminated_empty_node (#405) 2024-11-07 11:28:06 -08:00
Kat Marchán 1e924bcc7f
clarifications around multiline prefixes 2024-10-03 20:53:01 -07:00
Thomas Jollans bcfb3321c4
Tweak rules for escaped whitespace in multi-line strings (#392)
These rules are a bit more liberal than what was described previously,
but I think they're clearer and more consistent:

 * This way, strings have the (I think intuitive) property that, when
   you 'blindly' remove the whitespace escapes, the meaning is
   unchanged.
 * If you take any valid single-line string and add a newline character
   and some indentation both at the start and the end, the string will
   still be valid (and unchanged) - previously, this was not necessarily
   the case if there were whitespace escapes.
2024-06-13 11:55:44 -07:00
Romain Delamare 6a77436e09
kql: only allow top() at start of selector (#388) 2024-04-17 12:41:50 -07:00
Kat Marchán fa204cec62
unicode was not defined in grammar 2024-04-02 21:36:25 -07:00
Kat Marchán c9134e3c16
change escape resolution order again 2024-04-02 00:58:25 -07:00
Kat Marchán bea0f67685
turn it around: escapes should be resolved _before_ dedenting 2024-04-01 16:53:33 -07:00
Kat Marchán fa9d30388c
remove duplication of keyword-number 2024-04-01 16:48:38 -07:00
Kat Marchán d064bc9026
clarify multi-line strings and escapes interaction 2024-04-01 14:37:52 -07:00
Kat Marchán 281de7e977
review fixes 2024-04-01 14:26:44 -07:00
Dani Smith de1dbd2c33
Add Lua implementation (#385) 2024-03-28 11:39:12 -07:00
Dani Smith 4bec08b70d
add swift and crystal to README (#384) 2024-03-15 21:27:53 -07:00
Kat Marchán d0b30c3f35
Update SPEC.md
Co-authored-by: Bannerets <comonoid@protonmail.com>
2024-03-05 12:47:07 -08:00
Kat Marchán aeb41cc7d7
Update examples/ci.kdl
Co-authored-by: Bannerets <comonoid@protonmail.com>
2024-03-05 12:46:04 -08:00
Kat Marchán 2de2ddc708
Update README.md
Co-authored-by: Bannerets <comonoid@protonmail.com>
2024-03-05 12:45:48 -08:00
Kat Marchán b294e9cb5a
Update README.md
Co-authored-by: Bannerets <comonoid@protonmail.com>
2024-03-05 12:45:30 -08:00
Bram Gotink 9e7b958f0c
Ensure spec allows slashdash right after node separator (#382) 2024-02-18 13:18:50 -08:00
Bram Gotink 9132a96e56
Quote identifiers that contain an equals sign (#381) 2024-02-18 13:15:58 -08:00
Kat Marchán dadcfdf2ae
Update tests/test_cases/expected_kdl/multiline_raw_string_indented.kdl
Co-authored-by: Dani Smith <danini@hey.com>
2024-02-15 12:03:25 -08:00
Kat Marchán 2fcf6d42d3
Update tests/test_cases/expected_kdl/multiline_string_indented.kdl
Co-authored-by: Dani Smith <danini@hey.com>
2024-02-15 12:03:18 -08:00
Kat Marchán 2710c90ff5
facepalm: forgot the full grammar change for float keywords 2024-02-13 00:15:03 -08:00
Kat Marchán e773747b0b
Release 2.0 draft 4 2024-02-12 23:20:55 -08:00
Kat Marchán fa816ca6df
add floats
Fixes: https://github.com/kdl-org/kdl/issues/374
2024-02-12 23:17:52 -08:00
Kat Marchán 631ec14059
allow /- at the very beginning of a document 2024-02-12 23:00:50 -08:00
wackbyte 921211782f
Remove extra indent in CI example (#376) 2024-02-12 10:54:07 -08:00
wackbyte ec7880d4a5
Fix broken formatting in grammar language example (#375) 2024-02-12 10:53:38 -08:00
Kat Marchán 7ab86588c0
iterate a bit on KQL 2024-02-11 21:05:23 -08:00
Kat Marchán abae1f9a39
more fixes 2024-02-08 16:16:42 -08:00
Kat Marchán 793a9d4ce7
normalize literal newlines in multiline strings
Fixes: https://github.com/kdl-org/kdl/issues/360
2024-02-08 11:24:40 -08:00
Kat Marchán f0f9589636
example tweaks 2024-02-08 11:14:54 -08:00
Kat Marchán f81fcfada5
minor reword 2024-02-08 09:47:42 -08:00
Kat Marchán b1163e1f91
more small fixes 2024-02-08 09:35:26 -08:00
Kat Marchán 40d8c83aca
unicode character support clarifications 2024-02-07 16:07:54 -08:00
Kat Marchán f767472cab
small readme improvements 2024-02-07 13:06:09 -08:00
Kat Marchán 2d4bcd0b51
Release 2.0.0 draft 3 2024-02-07 11:38:03 -08:00
Kat Marchán 35ac19b854
fix stray legacy bool in example 2024-02-07 11:36:59 -08:00
Kat Marchán 522ce8591e
clarify multi-line strings further 2024-02-07 11:33:47 -08:00
Kat Marchán 172c67b602
Release 2.0.0 draft 2 2024-02-06 13:56:50 -08:00
Kat Marchán c15b5c2798
make note of .1/+.1 illegality in the changelog 2024-02-06 13:54:46 -08:00
Mika Vilpas cfd86ce70a
docs: add link to neovim integration (#369)
The neovim integration uses https://github.com/nvim-treesitter/nvim-treesitter which currently requires "Neovim 0.9.2 or later (nightly recommended)". See the up to date requirements in the project's readme:
https://github.com/nvim-treesitter/nvim-treesitter?tab=readme-ov-file#requirements

A rough and unmaintained configuration example can be found here: 
https://github.com/kdl-org/kdl/issues/258#issuecomment-1890912634

(It might serve as a good starting point)
2024-01-17 10:19:49 -08:00
Corey Powell 29495006bc
KDL V2 Test Fixes (#368)
* Add newlines to some of the bare ident tests that were missing them

* eof_after_escape.kdl is valid according to spec
2024-01-06 14:50:37 -08:00
Tab Atkins-Bittner af91cc6319 Add tests for .1 and general 'ident ambiguous with a number' cases. 2024-01-04 11:12:10 -08:00
Tab Atkins-Bittner 1d6809ee46 Whoops, missed allowing '+.' 2024-01-03 17:25:34 -08:00
Tab Atkins-Bittner 1f28fb0e83 [editorial] Move keyword production to a better spot. Rephrase bool/keyword to include the # directly. Explicitly spell out the disallowed keywordish idents, and move where they appear. Rename numberish-ident to signed-ident (it's not numberish at all, is the point). 2024-01-03 17:19:03 -08:00
Tab Atkins-Bittner bc2b995bfe Rename/rearrange the string productions to match the spec text better. 2024-01-03 17:14:23 -08:00
Tab Atkins-Bittner 24cd2141d3 Disallow idents like '.1' to avoid footguns 2024-01-03 17:08:49 -08:00
Tab Atkins-Bittner de37e11a29 Comments are now allowed in and around types (along with other types of ws) 2023-12-26 14:58:49 -08:00
Tab Atkins-Bittner c273d249b6 Dang it, forgot to save README when fixing multiline earlier. 2023-12-26 14:41:01 -08:00
Tab Atkins-Bittner 094a615f82 Tests are invalid (contained U+FFFD, not surrogates) and are in general untestable since you can't represent surrogates in UTF-8, which KDL must be encoded in. 2023-12-26 14:36:48 -08:00
Tab Atkins-Bittner 1294f9733d Fix tests about # in an ident string 2023-12-26 14:31:49 -08:00
Tab Atkins-Bittner 935d054d13 Fix more multiline tests 2023-12-26 14:28:25 -08:00
Tab Atkins-Bittner f02ba59c0c Make multi-line ws prefix determined by the last line. 2023-12-26 14:19:45 -08:00
Tab Atkins-Bittner 6d091fd493 Use consistent codepoint spelling 2023-12-26 13:18:01 -08:00
Tab Atkins-Bittner 491cc46f89 Fix the disallowed low ASCIIs 2023-12-26 13:16:55 -08:00
Tab Atkins-Bittner b635470ab2 be more specific 2023-12-26 13:06:22 -08:00
Tab Atkins-Bittner 6d359d2e4c Remove now-irrelevant comment about idents acting like strings (they *are* strings now). 2023-12-26 13:05:10 -08:00
Tab Atkins-Bittner 419995ff19 typos 2023-12-26 13:04:44 -08:00
Tab Atkins-Bittner 057e8c894d Rewrite intro paragraph for strings to make their usage clearer. 2023-12-26 13:04:35 -08:00
Kat Marchán d53d99ff2e
test fixes 2023-12-17 13:37:37 -08:00
Kat Marchán d4333322d9
Add LRM/RLM to the direction control char list 2023-12-17 13:24:00 -08:00
Kat Marchán 511ab6b6ff
missed a spot 2023-12-17 10:01:42 -08:00
Kat Marchán 055de4e1be
better organization of how we talk about identifiers/strings and comments 2023-12-16 21:44:25 -08:00
Kat Marchán 39b9fac0d3
fix stray quote 2023-12-16 20:39:18 -08:00
Kat Marchán 0022536fc7
small rewording 2023-12-16 16:09:57 -08:00
Kat Marchán 90cd0b1bb9
make unicodey equals signs valid property assignment characters 2023-12-16 16:09:13 -08:00
Kat Marchán 50d378f1db
update readme a bit 2023-12-16 15:50:40 -08:00
Kat Marchán b51859edf3
update tests
Fixes: https://github.com/kdl-org/kdl/issues/359
2023-12-16 14:44:32 -08:00
Kat Marchán 56f399bf71
Add \s to the list of escapes 2023-12-14 19:25:12 -08:00
Kat Marchán 9f061537c9
Add explicit attribution for logo 2023-12-14 19:17:41 -08:00
Kat Marchán 817a7dc0ab
fixes from review 2023-12-14 19:12:59 -08:00
Kat Marchán 54df7f0cab
Update README 2023-12-13 00:21:55 -08:00
Kat Marchán a0d5030e3b
Release 2.0 draft 1 2023-12-12 23:49:26 -08:00
Kat Marchán 8de7df6eaa
formatting 2023-12-12 23:49:04 -08:00
Kat Marchán 7790505bf9
Merge branch 'main' into kdl-v2 2023-12-12 23:44:10 -08:00
Kat Marchán fc1b59436a
add support for dedented multi-line strings and raw strings 2023-12-12 23:17:04 -08:00
Kat Marchán 49402ccb7b
allow BOM only in the first unicode scalar in a document 2023-12-12 22:51:52 -08:00
Kat Marchán 13799de32b
Allow whitespace in more places
Fixes: https://github.com/kdl-org/kdl/issues/355
2023-12-12 22:28:52 -08:00
Kat Marchán c8488db13e
Make last semicolon optional for inline nodes
Fixes: https://github.com/kdl-org/kdl/issues/341
2023-12-12 22:21:13 -08:00
Kat Marchán 5a7b339ed4
Constrain code points to unicode scalar values
Fixes: https://github.com/kdl-org/kdl/issues/207
2023-12-12 22:10:26 -08:00
Kat Marchán b42b6c80f0
Clarify that multiline comments are allowed after line continuations, per grammar
Fixes: https://github.com/kdl-org/kdl/issues/322
2023-12-12 21:57:57 -08:00
Kat Marchán 31fd7bd00a
Update JiK and XiK too 2023-12-12 21:43:35 -08:00
Kat Marchán 63feef70fe
Update schema spec 2023-12-12 21:39:21 -08:00
Kat Marchán fada1fc1dd
Update KQL text, too 2023-12-12 21:37:13 -08:00
Kat Marchán 5e89c4550a
Update all examples to use most changes 2023-12-12 21:34:02 -08:00
Kat Marchán 2694146af4
# is just plain illegal now 2023-12-12 21:12:11 -08:00
Kat Marchán 85aa3a09ab
treat bare identifiers and strings in value locations (#358)
Fixes: https://github.com/kdl-org/kdl/issues/339
2023-12-12 21:03:30 -08:00
Kat Marchán e6356d5a03
allow ,<> as identifier characters since they no longer need to be re… (#352)
* fix some confusion in grammar syntax, and actually specify the syntax itself

Fixes: https://github.com/kdl-org/kdl/issues/345

* allow ,<> as identifier characters since they no longer need to be reserved

* fix typo

* disallow more code points and outright ban certain ones from KDL documents altogether (#353)

Fixes: https://github.com/kdl-org/kdl/issues/250

* `r` prefix is no longer required for raw strings (#354)

Fixes: https://github.com/kdl-org/kdl/issues/337
2023-12-12 20:27:37 -08:00
Kat Marchán 99abeef6d3
fix some confusion in grammar syntax, and actually specify the syntax itself (#351)
Fixes: https://github.com/kdl-org/kdl/issues/345
2023-12-12 20:20:15 -08:00
Christopher Durham eb55930264
Update formal grammar for KDL 2.0 (#285)
Fixes: https://github.com/kdl-org/kdl/issues/284

* Update formal grammar

* Update SPEC.md for KDL 2.0 preview

* Update SPEC.md

Co-authored-by: Christopher Durham <cad97@cad97.com>

---------

Co-authored-by: Tab Atkins Jr <jackalmage@gmail.com>
Co-authored-by: Kat Marchán <kzm@zkat.tech>
2023-12-10 17:44:55 -08:00
Kat Marchán ef93a6b10c
wrap comments 2023-10-17 10:00:44 -07:00
Kat Marchán 7b7d57bf29
lead with a more complete example in the readme 2023-10-17 09:55:32 -07:00
sblinch 9f10522717
Add kdl-go to README.md (#336) 2023-10-17 09:23:57 -07:00
Tab Atkins-Bittner 0836df1c19 Restrict idents from looking like raw strings. Closes #200, closes #204, closes #241 2023-10-06 14:32:01 -07:00
Tab Atkins-Bittner 568c096465 Document the vertical tab addition. 2023-10-06 14:30:18 -07:00
Tab Atkins-Bittner 3b39e29fee Add vertical tab to whitespace. Closes #331 2023-10-06 14:13:43 -07:00
Tab Atkins-Bittner 270c60ca9a Revert "Allow single-line comments with nothing after them. Fixes #318"
This reverts commit 652590fad3.
2023-10-06 14:07:29 -07:00
Tab Atkins-Bittner 54f5fc8025 Revert "Add vertical tab to whitespace characters. Fixes #331"
This reverts commit ef1bb689b0.
2023-10-06 14:07:28 -07:00
Tab Atkins-Bittner ef1bb689b0 Add vertical tab to whitespace characters. Fixes #331 2023-10-06 13:58:35 -07:00
Tab Atkins-Bittner 652590fad3 Allow single-line comments with nothing after them. Fixes #318 2023-10-06 13:56:03 -07:00
Jonathan 6fa99c2586
Add link to Go implementation (#334) 2023-09-26 12:18:51 -07:00
Evgeny 11d8e912fc
add Sublime Text support (#326) 2023-07-26 14:34:57 -07:00
Danielle Smith 09801faa93
add playground link to README.md (#332) 2023-06-30 15:06:31 -07:00
Tab Atkins Jr f3e5ff6027
Rearrange the number production to put decimal at the end
While the grammar makes no statements about match order, parsers pretty universally test for decimal last, after the other number productions, because `0b010` (/etc) can look like a `0` followed by garbage. Matching this order can reduce confusion.

Closes #330.
2023-05-30 14:13:46 -07:00
Evgeny a75ca13c15
Fix a typo in SPEC.md (#323) 2023-05-25 12:09:47 -07:00
chee a3d39e7749
Add link to common lisp implementation (#319) 2023-03-15 09:29:32 -07:00
Exidex 6feeccc491
Add Intellij IDEA plugin to README.md (#312) 2022-10-17 15:33:00 -07:00
Patitotective 6bf9b1c588
Update README.md (#311) 2022-10-13 09:13:03 -07:00
Lars Willighagen 0dc4a92a69
Replace use of non-defined 'tag' term (#310)
Fixes: https://github.com/kdl-org/kdl/issues/306

In the specifications of KQL and JiK, replace the
usage of 'tag' with 'type annotation', as that is
the term in the main KDL specification.
2022-10-10 13:25:25 -07:00
Lars Willighagen 06d1d67359
Add draft grammar for KQL 1.0.0 (#303)
* Add draft grammar for KQL 1.0.0

* Change whitespace in KQL grammar

* Update KQL grammar to use new operators
2022-10-09 12:04:10 -07:00
Bannerets 8d252133b7
Mention an OCaml implementation in the README (#307) 2022-10-03 09:14:53 -07:00
Aram Drevekenin 5253595c14
docs(readme): link to vim syntax plugin (#305) 2022-09-29 09:52:25 -07:00
Hannah Kolbeck 6bab316b0f
Remove credit from test suite README (#304) 2022-09-29 09:50:14 -07:00
Benjamin Kane 20d65edb7d
Add links to XML2KDL repo/online editor (#301)
Low effort KDLing should be easy :D
2022-09-23 09:08:39 -07:00
Nathan West 0b99021180
Improvements to string naming consistency (#299)
This PR modifies string descriptions in SPEC.md to use more consistent language throughout, with the primary intention of removing long descriptions like "a property key is either an identifier or a string". There are no semantic changes to KDL here.
2022-09-20 17:29:59 -07:00
Thomas Jollans c8dd45a0f1
Mention ckdl in the README (#296) 2022-09-17 15:18:49 -07:00
Tab Atkins Jr 76d5dd542a
Editorial rephrasing; define empty array/object
Did an editorial pass over the document, rewriting most of the prose slightly.

Caught a place or two that was still referring to tags for object keys.

Sole non-editorial change was adding the final ambiguous case - a completely empty node. These are required to have an `(array)` or `(object)` tag to be valid.
2022-09-02 15:02:05 -07:00
Bram Gotink fb80016011
Make JSON-in-KDL more minimalistic (#293) 2022-09-02 13:54:08 -07:00
Bram Gotink d437cf228b
Add test for empty single-line comment (#292) 2022-09-02 07:37:10 -07:00
Hannah Kolbeck 0a4a14d87a
Add escaped whitespace note to v2 changelog (#291)
* Add escaped whitespace note to v2 changelog

* Make changelog note on escaping whitespace more detailed
2022-09-01 13:05:53 -07:00
Nathan West 825ff2c17d
Add escaped whitespace to KDL strings (#290)
* Add escaped whitespace to KDL spec

* Add test cases for escaped whitespace

* Spelling error
2022-08-31 21:49:01 -07:00
Bram Gotink 337bd1bccf
Update expected output of test with changed input (#289) 2022-08-30 10:44:44 -07:00
Bram Gotink ffeea8e5aa
Use forward slash in solidus-escape test (#288) 2022-08-30 08:11:51 -07:00
Kat Marchán f38edc765d
add failing test for removed solidus escape 2022-08-28 13:28:47 -07:00
Kat Marchán 78a2d5f5ed
Draft changelog 2022-08-28 13:14:37 -07:00
Basile Henry 1bf4d740fa
Allow "empty" single line comments in the spec (#234)
As I read the grammar in the spec, `"//"` wouldn't parse as a single-line-comment as it requires as least one non-newline character after the slashes.
2022-08-28 13:07:17 -07:00
Kat Marchán 2d5e543bbe
KQL: remove map operator and accessors (#222)
Honestly, they're just too implementation-specific
2022-08-28 13:01:53 -07:00
Kat Marchán 69ac280bf0
KQL: require operator and change operator grammar a bit (#221) 2022-08-28 13:01:07 -07:00
Danielle Smith 910f6e90a7
Do not escape / (Solidus, Forwardslash) (#197) 2022-08-28 12:59:26 -07:00
Fabian Cook d9459f67c0
Correct @virtualstate/kdl description (#279) 2022-07-29 19:43:42 -07:00
Fabian Cook 4f739516e6
Add @virtualstate/kdl to implementations (#278) 2022-07-29 09:10:01 -07:00
oledfish e8fe0c38a8
Add .NET library to the implementation list (#277)
As per #51
2022-07-23 17:01:18 -07:00
oledfish 9daa2019f7
Fix RFC typo (#276)
The ``email`` field in Reserved Type Annotations for Strings refers to [RFC 5302](https://datatracker.ietf.org/doc/html/rfc5302), it should be [RFC 5322](https://datatracker.ietf.org/doc/html/rfc5322) instead.
2022-07-22 10:34:21 -07:00
Kat Marchán 81fda2455f
docs: add kaydle to impl list 2022-07-20 09:32:31 -07:00
Bram Gotink b027d3a751
Remove children from node terminals (#275)
The grammar doesn't specify that children count
as node terminator, but the text does.

The following document would be valid per text,
but invalid per spec.

```kdl
node { child {} }
```

Fixes #274
2022-07-11 15:13:05 -07:00
Jelle Besseling fcd489afa6
Add more info about the hyphen character in identifiers (#271) 2022-04-25 10:04:28 -07:00
Sebastian Paarmann 81a58e64ee
Mention multi-line comments in spec prose (#263) 2022-03-29 13:00:29 -07:00
Melody Horn cc1da35435
allow contributor link in `kdl-schema.kdl` (#260) 2022-03-27 22:12:32 -07:00
Melody Horn 168fd6abdc
fix `kdl-schema.kdl` well-formedness (#259) 2022-03-27 11:58:39 -07:00
Tab Atkins Jr 3e915b5be3
Clarify the parsing of hostname and idl-hostname (#248)
Ref: #247
2022-02-19 02:06:54 -08:00
Christopher Durham 8976e2da68
Define `digit` in formal grammar (#236)
`digit` is used as a subtraction in bare-identifier, but never defined.
2022-02-19 02:06:17 -08:00
Tab Atkins Jr 5a566ea5e3
Fix #212 by clarifying left/right (#249) 2022-02-19 02:04:38 -08:00
Paul Colomiets 23bbe1ebec
Add `knuffel` to the list of implementations (#256) 2022-02-07 15:50:39 -08:00
Mahmoud Mazouz f82a106814
Add link to Haskell implementation. (#243) 2021-10-24 17:59:50 -07:00
Tab Atkins Jr a1d85e9fe1
[editorial] tweak node-props-and-args grammar (#240)
* replaces a `foo foo*` with a `foo+`
* switches the name of the production to singular, since it only represents one prop/arg at a time

No normative changes intended.
2021-10-17 08:46:34 -07:00
Matthew Gamble 617ab86e5e
Add link to additional python implementation (#239) 2021-10-17 08:03:59 -07:00
Tab Atkins Jr e5e131920f
Link to new python impl
previous one is (currently, at least) dead
2021-10-08 12:09:09 -07:00
Tab Atkins Jr 05d16e0597
Per #223 discussion, this *should* be a parse error. (#226)
Fixes: #223
2021-10-07 08:01:18 -07:00
Tab Atkins Jr 93cc6724f2
Verify that a slash-dashed prop doesn't shadow a previous prop of the same name (#227) 2021-10-06 15:01:49 -07:00
Tab Atkins Jr 3f293ff01d
Empty children aren't reflected in the data model. (#219)
Fixes: https://github.com/kdl-org/kdl/issues/218
2021-10-05 20:27:28 -07:00
Tab Atkins Jr b22ed4b1b0
Add missing expected file (#217)
Per the grammar (`decimal := integer ('.' [0-9] [0-9_]*)? exponent?`), underscores in the fraction part should be allowed (as in `node 1.0_2`, the contents of the corresponding input file), but there was no expected_kdl file for this test case, indicating it's supposed to be a parse failure.

I'm assuming this was a mistake, since underscores in the fraction part make complete sense (and are allowed in the other two parts of a decimal number).
2021-10-04 17:47:24 -07:00
Danielle Smith 5a2f4969fe
fix: non-decimal test output according to docs (#196) 2021-09-27 17:44:21 -07:00
Danielle Smith 05af2fb657
fix: do not escape solidus (forwardslash) in test (#198) 2021-09-27 17:42:30 -07:00
Christopher Durham 296fe129e1
argument/property ordering clarification (#206) 2021-09-26 22:47:08 -07:00
Devasta 99d9168a4a
Added xml2kdl to the list of implementations. (#201) 2021-09-25 10:27:32 -07:00
Ben Reinhart 24faa6b75c
tests: add more coverage for keywords (#189) 2021-09-20 19:01:48 -07:00
Ben Reinhart 5c4f83b824
Update line continuation wording (#184) 2021-09-19 16:28:25 -07:00
Hannah Kolbeck f59ca2476a
Add type annotation tests from kdl4j and tweak unusual char in quoted id test (#181)
Co-authored-by: Hannah Kolbeck <hannah.kolbeck@streem.com>
2021-09-19 08:11:19 -07:00
Ben Reinhart 8ca18fec0a
tests: ensure output of illegal ident is quoted (#178) 2021-09-17 13:33:56 -07:00
Dave Anderson 0bbe723eb5
tests: adjust bare identifier inputs to match spec. (#168)
/ is not a valid identifier character. This updates
unusual_chars_in_bare_id.kdl to only include unusual but valid
identifier characters, and adds separate invalid input tests
for non-identifier characters.

Fixes #166
2021-09-16 10:46:22 -07:00
Chris Babcock 8ae4ae648e
Preserve duplicate nodes (#167)
Fixes: https://github.com/kdl-org/kdl/issues/165
2021-09-16 01:46:26 -07:00
Ben Reinhart 16269d4325
Prevent markdown from parsing []() as link (#162)
* Use same order from grammar definition
2021-09-15 18:26:50 -07:00
Jihchi Lee a2e53990ed
Fix some typos (#161) 2021-09-15 07:37:53 -07:00
Corey Powell 843beb99a5
Added Elixir implementation to list (#156)
Fixes: #155
2021-09-14 07:48:26 -07:00
Chris Morgan 785abebfc5
fix(spec): Correct bom from U+FFEF to U+FEFF (#153) 2021-09-13 20:17:20 -07:00
Chris Morgan 3df2b719a0
Fix a broken internal link (#152)
blob/main/ was a misapplied GitHubism.
2021-09-13 20:07:46 -07:00
Paul Young 1351f9fa1b
add missing quotation marks (#151) 2021-09-13 19:37:01 -07:00
Kat Marchán 654ab5deb3
1.0.0 2021-09-11 21:10:05 -07:00
Kat Marchán f68137f526
slap a date on it 2021-09-11 21:08:09 -07:00
Kat Marchán 02c40c589d
bump version to 1.0.0 and add example with type annotations 2021-09-11 21:04:22 -07:00
Kat Marchán d24d8551ca
missed some uri -> url changes 2021-09-11 20:51:08 -07:00
Eric Sampson f0bc492021
Add some more reserved type annotations (#134)
I think it would be useful to get these few more common data types into 
For the decimal floating types, I referenced [this protobuf discussion](https://github.com/protocolbuffers/protobuf/pull/7039#issuecomment-679083593) and [this](https://github.com/googleapis/googleapis/blob/master/google/type/decimal.proto)

I'm not sure what to call out for the currency format, I can't find a standard for that yet. There's a [protobuf money type](https://github.com/googleapis/googleapis/blob/master/google/type/money.proto) that's basically a ISO 4217 currency code plus a decimal number, but I don't really want to invent a suggested money format if there's a real one out there somewhere.
For this PR, can we just leave it TBD in order to reserve the type keyword?
2021-09-11 20:46:32 -07:00
Lars Willighagen 0cdda0b711
Disallow ws after (type) in grammar (#138)
Fixes: https://github.com/kdl-org/kdl/issues/131
2021-09-10 17:11:41 -07:00
Kat Marchán 5a13b920c4
use KDL Query for refs (#136) 2021-09-09 19:03:38 -07:00
Lars Willighagen 0e89878072
Add tag syntax to KQL (#137) 2021-09-09 10:03:07 -07:00
Lars Willighagen f242250d22
draft Schema spec for node and value tags (#135) 2021-09-09 07:50:58 -07:00
Tab Atkins Jr f1941b53d3
Allow node names to have type annotations. Bump JiK to take advantage of this. (#132) 2021-09-08 18:03:13 -07:00
Tab Atkins Jr b0eee36df8
Fix leftover contradiction in doctype nodes (#133)
An earlier idea had doctypes and some other weird nodes just encode the entire thing in the node name. I moved away from that, but accidentally left reference to it in the definition of valid nodes.

While I'm here, slightly fix up my wording around "attribute".
2021-09-08 10:41:42 -07:00
Lars Willighagen ede621807e
Fix multi-line-comment grammar (#130)
Fix https://github.com/kdl-org/kdl/issues/128
2021-09-05 12:12:35 +02:00
Jo Liss dec2565a17
fix typos (#129) 2021-09-03 08:02:49 -07:00
Kat Marchán cbb500a4ac
allow /- to cross linespaces (#127)
Ref: https://github.com/kdl-org/kdl/issues/121
2021-09-02 15:29:25 -07:00
Kat Marchán 6b4d0ea030
allow eof termination for single line comments (#126) 2021-09-02 15:25:13 -07:00
Kat Marchán 2e42c4c0ec
Change URIs to URLs for clarity (#125) 2021-09-02 15:10:03 -07:00
Kat Marchán a44fcbb1d4
add type annotation info to spec (#123)
Fixes: https://github.com/kdl-org/kdl/issues/106
2021-09-02 09:23:51 -07:00
Lars Willighagen 80dec07c37
Add schema specs for info and definitions (#120)
Fixes: https://github.com/kdl-org/kdl/issues/113
2021-09-01 22:07:09 -07:00
Kat Marchán 7c54aae64f
actually add child node spec to spec itself
Fixes: https://github.com/kdl-org/kdl/issues/59
2021-08-31 23:08:12 -07:00
Kat Marchán 0a3e498e16
clarify ordering stuff 2021-08-31 23:00:39 -07:00
Kat Marchán e4ad12ecfd
more links to XiK and JiK 2021-08-31 22:41:59 -07:00
Kat Marchán 762d20ed3b
add attribution for test suite 2021-08-31 22:34:29 -07:00
Kat Marchán 83c24e48a4
add a note about what to do if a test fails (or wrongly succeeds) 2021-08-31 22:31:16 -07:00
Kat Marchán fd478c29c7
bring over test suite from kdl4j (#119) 2021-08-31 22:25:11 -07:00
Kat Marchán 129812543f
prevent the three "keywords" from being used as bare identifiers (#117)
Fixes: https://github.com/kdl-org/kdl/issues/114
2021-08-31 21:47:59 -07:00
Kat Marchán 37c0a38baa
allow _ in post-decimal-point section (#118)
Fixes: https://github.com/kdl-org/kdl/issues/69
2021-08-31 20:39:17 -07:00
Kat Marchán 3f739cad42
make / illegal in identifiers
Fixes: https://github.com/kdl-org/kdl/issues/75
2021-08-31 20:09:45 -07:00
Kat Marchán d7089944ac
schema: add base64 format 2021-08-31 19:59:23 -07:00
Kat Marchán 04a84a72ec
link to other specs 2021-08-31 19:38:26 -07:00
Kat Marchán f6a45e1f27
KDL Query Language Spec (#111) 2021-08-31 19:02:34 -07:00
Kat Marchán 34c6592f09
remove () from identifiers so we can use it for KQL (#108) 2021-08-31 17:09:57 -07:00
Kat Marchán d87979f175
KDL schema spec (#104)
Fixes: https://github.com/kdl-org/kdl/issues/83
2021-08-31 12:03:27 -07:00
Tab Atkins Jr 9e35601c91
Partially revert #99 (#100)
6704988633 disallowed identifiers from ever starting with a sign character. This disallowed idents like `-`, or like the CSS `--foo` properties.

This change instead allows an ident to start with a sign character, so long as the *second* character isn't a digit.

I also tweaked the prose definition of identifier to talk about this restriction.
2021-08-24 14:57:03 -07:00
Kat Marchán 6704988633
identifiers should never look like numbers (#99) 2021-08-24 09:10:08 -07:00
Kat Marchán 5883435297
fix(grammar): allow whitespace before a node-terminator (#98)
kudos to @lucretiel for spotting this one.
2021-08-21 18:05:53 -07:00
Tab Atkins Jr 549ba1d2ec
First pass at XiK (#95)
* First pass at XiK

* fix the doctype node

* XML comments use KDL multiline comments, with ! nodes as an alternative.
2021-08-03 16:31:43 -07:00
Danielle Smith d4ae61f4f4
fix: remove deadusername (#94) 2021-07-23 13:10:01 -07:00
Tab Atkins Jr cc48e85f58
Switch literal nodes to `-` (#93)
`-` is slightly easier to type than `_` (no Shift, at least on american keyboards), and it's consistent with the "dummy" node name I'm planning to use for text nodes in XML-in-KDL.

(`_` is a valid XML element name, so I can't use that in XiK.)
2021-07-19 10:30:17 -07:00
Tab Atkins Jr 3e5184d788
Add JiK spec (#92) 2021-07-18 14:11:08 -07:00
Serafina Brocious e7147cf4ac
Fixed inconsistency between spec wording and BNF (#88) 2021-04-18 20:19:34 -07:00
Serafina Brocious 15aff6a309
Added optional sign to all number syntaxes (#87) 2021-04-18 20:19:21 -07:00
Serafina Brocious 00ed4b588b
Added Python implementation. (#86) 2021-04-18 20:18:59 -07:00
Kat Marchán 44c295358e
Use regular short = in readme example
Fixes: #77
2021-01-14 20:55:20 -08:00
Kat Marchán 33f0146eda
Clarify licensing situation 2021-01-14 20:51:58 -08:00
Kat Marchán 9fc879403c
Add PHP to list of impls
Fixes: #65
2021-01-12 21:22:06 -08:00
Hannah Kolbeck a5295f1bb0
Add Java implementation to list in README (#74) 2021-01-12 20:08:57 -08:00
Daniel Smith 9ceb0ed8d4
Possible typo in "Escapes" table (#72)
The maximum unicode code point is `10FFFF` but in the escapes table it states code points can only go up to `10FFF`. I think this is an error, since most emojis are well above that number, and other languages allow escapes up to `10FFFF`
2021-01-11 12:08:03 -08:00
Daniel Smith 1f293c280b
Add forwardlash to escapes table (#73)
I noticed this was a valid escape char in the rust implementation. Not sure if this was intended.
2021-01-11 12:07:28 -08:00
Hannah Kolbeck e8dbd597d7
Change strings in nuget example to raw where needed. (#70) 2021-01-08 21:09:33 -08:00
Hannah Kolbeck 1cf1fd0597
Correct description of the raw string format (#71) 2021-01-08 21:09:11 -08:00
Daniel Smith 4b20446ace
add link to dart version (#63) 2021-01-02 12:42:32 -08:00
Timothy Merritt ba3f464341
Add SVGs for Logo, Logo w/ Tagline (#62)
* (style): Add KDL logo and favicon files

* (style): Add SVGs for Logo, Logo w/ Tagline
2021-01-01 15:03:06 -08:00
Timothy Merritt 51ccbb3236
(style): Add KDL logo and favicon files (#61) 2021-01-01 09:54:49 -08:00
Lars Willighagen 89b52b2145
Fill in string escapes table (#60) 2020-12-29 11:27:37 -08:00
Kat Marchán 0251a090f7
cuddling 2020-12-27 19:24:28 -08:00
Kat Marchán 141b14cb72
this reduplication is silly 2020-12-27 17:58:42 -08:00
Kat Marchán 690de83bb4
add FAQ 2020-12-27 17:24:52 -08:00
Daniel Smith 8d4f3ddcfd
add link to ruby implementation (#58)
Fixes: #53
2020-12-27 09:32:10 -08:00
hclarke 3da011acbc
Update SPEC.md (#57)
this does a few things with identifiers and strings:

- removes `"` from the set of identifier characters, to prevent ambiguity with string
- adds `bare-identifier` and `escaped-string` non-terminals (i think less mixing of terminal/non-terminal is easier to read?)
- moves string ahead of bare-identifier in identifier, for easier implementation with ordered-choice parsers
- moves raw-string into string, so you can have raw-string identifiers
2020-12-26 18:03:32 -08:00
Lars Willighagen f60ba7edc1
Add link to kdljs (#45) 2020-12-22 17:13:56 -08:00
Kat Marchán c6bb3903cf
add javascript impl 2020-12-22 17:07:42 -08:00
hclarke 81fad70856
Fixed escape table formatting (#44) 2020-12-22 14:33:39 -08:00
Kat Marchán e7135dd0dc
add editor support section 2020-12-21 18:36:48 -08:00
Kat Marchán d8ddd5070e
fix url 2020-12-19 23:46:07 -08:00
Kat Marchán 23a419289d
add basic html translation example 2020-12-19 19:58:43 -08:00
Kat Marchán aaa7c97cdf
v1.0.0-pre.1 2020-12-19 12:58:53 -08:00
Kat Marchán b1f00d5d8d
capitalize 2020-12-19 12:58:35 -08:00
Kat Marchán cf341eac91
more blabber 2020-12-18 22:58:09 -08:00
Kat Marchán 60bcfdf926
require terminator after node-children too 2020-12-18 22:56:27 -08:00
Kat Marchán b30b0cf93a
messing with nodes some more 2020-12-18 21:32:40 -08:00
Kat Marchán dfc1441ec9
more node and nodes fixes 2020-12-18 20:06:11 -08:00
Kat Marchán 42672c1701
forgot eof 2020-12-18 19:31:44 -08:00
Kat Marchán b2a4610742
fix slashdash whitespace 2020-12-18 19:15:48 -08:00
625 changed files with 1530260 additions and 499 deletions

8
.editorconfig Normal file
View File

@ -0,0 +1,8 @@
# See http://editorconfig.org
root = true
[*.{md,xml,org}]
charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true

60
.github/workflows/ghpages.yml vendored Normal file
View File

@ -0,0 +1,60 @@
name: "Update Editor's Copy"
on:
push:
paths-ignore:
- README.md
- CONTRIBUTING.md
- LICENSE.md
- .gitignore
pull_request:
paths-ignore:
- README.md
- CONTRIBUTING.md
- LICENSE.md
- .gitignore
jobs:
build:
name: "Update Editor's Copy"
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: "Checkout"
uses: actions/checkout@v4
- name: "Setup"
id: setup
run: date -u "+date=%FT%T" >>"$GITHUB_OUTPUT"
- name: "Caching"
uses: actions/cache@v4
with:
path: |
.refcache
.venv
.gems
node_modules
.targets.mk
key: i-d-${{ steps.setup.outputs.date }}
restore-keys: i-d-
- name: "Build Drafts"
uses: martinthomson/i-d-template@v1
with:
token: ${{ github.token }}
- name: "Update GitHub Pages"
uses: martinthomson/i-d-template@v1
if: ${{ github.event_name == 'push' }}
with:
make: gh-pages
token: ${{ github.token }}
- name: "Archive Built Drafts"
uses: actions/upload-artifact@v4
with:
path: |
draft-*.html
draft-*.txt

25
.github/workflows/lint-tests.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Lint the test files
on:
push:
paths:
- "tests/**"
pull_request:
paths:
- "tests/**"
workflow_dispatch: {}
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Verify failing tests and orphaned tests
run: |
cd tests/test_cases
python ../../.github/workflows/lint-tests/lint.py

50
.github/workflows/lint-tests/lint.py vendored Normal file
View File

@ -0,0 +1,50 @@
from __future__ import annotations
import os
import sys
import typing
def findTestFiles(path) -> typing.Generator[str, None, None]:
for root, _, filenames in os.walk(path):
for filename in filenames:
yield os.path.join(root, filename)
# strip the leading folder name, so they can be directly compared
inputFiles = set(x[len("input")+1:] for x in findTestFiles("input"))
validFiles = set(x[len("expected_kdl")+1:] for x in findTestFiles("expected_kdl"))
invalidFiles = inputFiles - validFiles
orphanedFiles = validFiles - inputFiles
SUCCESS = True
# Check for any expected_kdl files without a corresponding input file.
if orphanedFiles:
SUCCESS = False
print("ERROR: There are outputs in /expected_kdl without corresponding tests in /input:\n" + "\n".join([" "+x for x in orphanedFiles]))
# Check for any input files lacking an expected_kdl file
# (aka inputs expected to generate a parse error)
# that don't have a _fail suffix.
misnamedFiles: list[str] = []
for filepath in invalidFiles:
basepath, ext = os.path.splitext(filepath)
if not basepath.endswith("_fail"):
misnamedFiles.append(filepath)
if misnamedFiles:
SUCCESS = False
print("ERROR: There are tests in /input without corresponding outputs in /expected_kdl, but they don't have a _fail suffix:\n" + "\n".join([" "+x for x in misnamedFiles]))
# Check for any expected_kdl files that don't end in a newline.
noNewlineFiles: list[str] = []
for filepath in validFiles:
with open("expected_kdl/" + filepath, "r", encoding="utf-8") as fh:
text = fh.read()
if not text.endswith("\n"):
noNewlineFiles.append(filepath)
if noNewlineFiles:
SUCCESS = False
print("ERROR: There are outputs in /expected_kdl that don't end with a newline:\n" + "\n".join([" "+x for x in noNewlineFiles]))
if not SUCCESS:
sys.exit(1)

57
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,57 @@
name: "Publish New Draft Version"
on:
push:
tags:
- "draft-*"
workflow_dispatch:
inputs:
email:
description: "Submitter email"
default: ""
type: string
jobs:
build:
name: "Publish New Draft Version"
runs-on: ubuntu-latest
steps:
- name: "Checkout"
uses: actions/checkout@v4
# See https://github.com/actions/checkout/issues/290
- name: "Get Tag Annotations"
run: git fetch -f origin ${{ github.ref }}:${{ github.ref }}
- name: "Setup"
id: setup
run: date -u "+date=%FT%T" >>"$GITHUB_OUTPUT"
- name: "Caching"
uses: actions/cache@v4
with:
path: |
.refcache
.venv
.gems
node_modules
.targets.mk
key: i-d-${{ steps.setup.outputs.date }}
restore-keys: i-d-
- name: "Build Drafts"
uses: martinthomson/i-d-template@v1
with:
token: ${{ github.token }}
- name: "Upload to Datatracker"
uses: martinthomson/i-d-template@v1
with:
make: upload
env:
UPLOAD_EMAIL: ${{ inputs.email }}
- name: "Archive Submitted Drafts"
uses: actions/upload-artifact@v4
with:
path: "versioned/draft-*-[0-9][0-9].*"

23
.gitignore vendored
View File

@ -1,2 +1,25 @@
/target
Cargo.lock
*.html
*.pdf
*.redxml
*.swp
*.txt
*.upload
*~
.tags
/*-[0-9][0-9].xml
/.*.mk
/.gems/
/.refcache
/.venv/
/.vscode/
/lib
/node_modules/
/versioned/
Gemfile.lock
archive.json
draft-marchan-kdl2.xml
package-lock.json
report.xml
!requirements.txt

4
.note.xml Normal file
View File

@ -0,0 +1,4 @@
<note title="Discussion Venues" removeInRFC="true">
<t>Source for this draft and an issue tracker can be found at
<eref target="https://github.com/kdl-org/kdl"/>.</t>
</note>

144
CHANGELOG.md Normal file
View File

@ -0,0 +1,144 @@
# KDL Changelog
## 2.0.0 (2024-12-21)
### Grammar
* Solidus/Forward slash (`/`) is no longer an escaped character.
* Space (`U+0020`) can now be written into quoted strings with the `\s`
escape.
* Single line comments (`//`) can now be immediately followed by a newline.
* All literal whitespace following a `\` in a string is now discarded.
* Vertical tabs (`U+000B`) are now considered to be newlines.
* The grammar syntax itself has been described, and some confusing definitions
in the grammar have been fixed accordingly (mostly related to escaped
characters).
* `,`, `<`, and `>` are now legal identifier characters. They were previously
reserved for KQL but this is no longer necessary.
* Code points under `0x20` (except newline and whitespace code points), code
points above `0x10FFFF`, Delete control character (`0x7F`), and the [unicode
"direction control"
characters](https://www.w3.org/International/questions/qa-bidi-unicode-controls)
are now completely banned from appearing literally in KDL documents. They
can now only be represented in regular strings, and there's no facilities to
represent them in raw strings. This should be considered a security
improvement.
* Raw strings no longer require an `r` prefix: they are now specified by using
`#""#`.
* Raw string productions are now explicitly non-greedy (and "fallible").
* Line continuations can be followed by an EOF now, instead of requiring a
newline (or comment). `node \<EOF>` is now a legal KDL document.
* `#` is no longer a legal identifier character.
* `null`, `true`, and `false` are now `#null`, `#true`, and `#false`. Using
the unprefixed versions of these values is a syntax error.
* The spec prose has more explicitly stated that whitespace and newlines are
not valid identifier characters, even though the grammar already expressed
this.
* Bare identifiers can now be used as values in Arguments and Properties, and are interpreted as string values.
* The spec prose now more explicitly states that strings and raw strings can
be used as type annotations.
* Removed a statement in the spec prose that said "It is reasonable for an
implementation to ignore null values altogether when deserializing". This is
no longer encouraged or desired.
* Code points have been constrained to [Unicode Scalar
Values](https://unicode.org/glossary/#unicode_scalar_value) only, including
values used in string escapes (`\u{}`). All KDL documents and string values
should be valid UTF-8 now, as was intended.
* The last node in a child block no longer needs to be terminated with `;`,
even if the closing `}` is on the same line, so this is now a legal node:
`node{foo;bar;baz}`
* More places allow whitespace (node-spaces, specifically) now. With great
power comes great responsibility:
* Inside `(foo)` annotations (so, `( foo )` would be legal (`( f oo )` would
not be, since it has two identifiers))
* Between annotations and the thing they're annotating (`(blah) node (thing)
1 y= (who) 2`)
* Around `=` for props (`x = 1`)
* The BOM is now only allowed as the first character in a document. It was
previously treated as generic whitespace.
* Multi-line strings must now use `"""` as delimiters. The opening delimiter must be immediately followed by a newline, and the closing delimiter must be on its own line, prefixed by optional whitespace.
* Multi-line strings are now automatically dedented, according to the common
whitespace matching the whitespace prefix of the closing line.
* `.1`, `+.1` etc are no longer valid identifiers, to prevent confusion and
conflicts with numbers.
* Multi-line strings' literal Newline sequences are now normalized to single
`LF`s.
* `#inf`, `#-inf`, and `#nan` have been added in order to properly support
IEEE floats for implementations that choose to represent their decimals that
way.
* Correspondingly, the identifiers `inf`, `-inf`, and `nan` are now syntax
errors.
* `u128` and `i128` have been added as well-known number type annotations.
* Slashdash (`/-`) -compatible locations adjusted to be more clear and
intuitive. They can now be used in exactly three different places: before nodes,
before entire entries, or before entire child blocks.
* Furthermore, The ordering of slashdashed elements has been restricted such
that a slashdashed child block cannot go before an entry (including slashdashed
entries).
* Optional version marker `/- kdl-version 2` (or `1`) as the first line in a document, optionally preceded by the BOM.
### KQL
> [!INFO] Note: these are provided for convenience, but as of the 2.0.0 KDL spec release,
> KQL itself is not finalized and should be considered a separate specification,
> alongside the Schema spec and others.
* There's now a _required_ descendant selector (`>>`), instead of using plain
spaces for that purpose.
* The "any sibling" selector is now `++` instead of `~`, for consistency with
the new descendant selector.
* Some parsing logic around the grammar has changed.
* Multi- and single-line comments are now supported, as well as line
continuations with `\`.
* Map operators have been removed entirely.
---
## 2.0.0 Draft Changelogs
### 2.0.0-draft.8 (2024-12-14)
* Some details have been clarified around the treatment of whitespace in
multiline strings.
* `raw-string` productions have been updated to be explicitly non-greedy and
"fallible".
* Some tests have been added, others adjusted, some removed, after a cleanup pass.
### 2.0.0-draft.7 (2024-12-10)
* `node-space` is now allowed as whitespace after a `slashdash`, meaning line
continuations will work now.
* One or two consecutive double-quotes are now allowed in the bodies of
multi-line quoted strings, without needing to be escaped.
* Grammar has been fixed to disallow raw strings like `#"""#`, which are now
properly treated as invalid multi-line raw strings (instead of the equivalent of
`"\""`).
* Test suite has been updated to include a `_fail` suffix in all test cases
which are expected to fail.
* A slew of additional slashdash and multi-line string compliance tests have
been added. Have fun. :)
* The organization of string types in the spec prose has been updated to a
hopefully more helpful structure.
### 2.0.0-draft.6 (2024-12-04)
* Multiline strings, both Raw and Quoted, must now use `"""` instead of a single `"`. Using `"""` for a single-line string is a syntax error.
* Fixed an issue with the `unicode_silly` test case.
* Some rewordings and clarification in the spec prose.
* Slight grammar tweak where the pre-terminator `node-space*` for `node` and `final-node` have been moved into `base-node`.
### 2.0.0-draft.5 (2024-11-28)
* Equals signs other than `=` are no longer supported in properties.
* 128-bit integer type annotations have been added to the list of "well-known"
type annotations.
* Multiline string escape rules have been tweaked significantly.
* `\s` is now a valid escape within a string, representing a space character.
* Slashdash (`/-`)-compatible locations and related grammar adjusted to be more
clear and intuitive. This includes some changes relating to whitespace,
including comments and newlines, which are breaking changes.
* Various updates to test suite to reflect changes.

22
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,22 @@
# Contributing
## Mechanics
Contributions can be made by creating pull requests.
The GitHub interface supports creating pull requests using the Edit (✏) button.
## Building the Specification
The specification is written in
[kramdown-rfc](https://github.com/cabo/kramdown-rfc/wiki/Syntax2), which
compiles via [RFCXML](https://authors.ietf.org/rfcxml-vocabulary) to text and
HTML.
You can build the formatted versions or the intermediate RFCXML file using
https://author-tools.ietf.org/ or locally by running `make`. To preserve the
intermediate RFCXML form in a local build, run `make draft-marchan-kdl2.xml`
once.
Command line usage requires that you have the necessary software installed. See
[the instructions](https://github.com/martinthomson/i-d-template/blob/main/doc/SETUP.md).

161
JSON-IN-KDL.md Normal file
View File

@ -0,0 +1,161 @@
JSON-in-KDL (JiK)
=================
This specification describes a canonical way to losslessly encode [JSON](https://json.org) in [KDL](https://kdl.dev). While this isn't a very useful thing to want to do on its own, it's occasionally useful when using a KDL toolchain while speaking with a JSON-consuming or -emitting service.
This is version 4.0.0 of JiK.
JSON-in-KDL (JiK from now on) is a kdl microsyntax consisting of named nodes that represent objects, arrays, or literal values.
----
There are two ways to write a JSON literal into JiK:
* As a node with any nodename and a single argument, like `- #true` (for the JSON `true`) or `foo 5` (for the JSON `5`).
* When nested in arrays or objects, literals can usually be written as arguments (for array nodes) or properties (for object nodes). See below for details.
----
JSON arrays are represented in JiK as a node with any nodename, with zero or more arguments and/or zero or more children with `-` nodenames.
Arguments can encode literals - for example, the JSON `[1, 2, 3]` can be written in JiK as `- 1 2 3`.
Children can encode literals and/or nested arrays and objects. For example, the JSON `[1, [true, false], 3]` can be written in JiK as:
```kdl
- {
- 1
- #true #false
- 3
}
```
The arguments and/or children, taken in order, represent the items of the array.
Arguments and children can be mixed, if desired. The preceding example could also be written as:
```kdl
- 1 {
- #true #false
- 3
}
```
Two otherwise-ambiguous cases must be manually annotated with an `(array)` type annotation:
* A single-element array (such as `[1]`) written using arguments (as `- 1`) would be ambiguous with a literal node.
To indicate this is an array, it must be written as `(array)- 1`
(Or rewritten to use child nodes, like `- { - 1 }`.)
* An empty array (JSON `[]`) must use the `(array)` type annotation, like `(array)-`.
The `(array)` type annotation can be used on any other valid array node if desired, but has no effect in such cases.
----
JSON objects are represented in JiK as a node with any nodename, with zero or more properties and/or zero or more children with any nodenames.
Properties can encode literals - for example, the JSON `{"foo": 1, "bar": true}` can be written in JiK as `- foo=1 bar=#true`.
Children can encode literals and/or nested arrays and objects,
using the nodename for the item's key.
For example, the JSON `{"foo": 1, "bar": [2, {"baz": 3}], "qux":4}` can be written in JiK as:
```kdl
- {
foo 1
bar 2 {
- baz=3
}
qux 4
}
```
As with arrays, child nodes and properties can be mixed, so the preceding example could have been written as:
```kdl
- foo=1 {
bar 2 {
- baz=3
}
qux 4
}
```
Or, so long as the exact order of properties isn't meaningful (it's not *meant* to be in JSON),
*all* the literal-valued keys can be pulled up into properties,
leaving children nodes solely for nested arrays and objects:
```kdl
- foo=1 qux=4 {
bar 2 {
- baz=3
}
}
```
The properties and/or children of the node represent the items of the object,
with the property names and child nodenames as each item's key.
All "keys" in an object node must be unique.
As with arrays, there are two ambiguous cases that must be manually annotated with the `(object)` type annotation:
* An object containing a single item whose key is "-" (like `{"-": 1}`) written using children (like `- { - 1 }`)
would be ambiguous with an array node.
To indicate this is an object, it must be written as `(object)- { - 1 }`.
(Or, if the sole item's value is a literal, as in this example,
it can be rewritten to use properties, as `- -=1`.)
* An empty object (JSON `{}`) must use the `(object)` type annotation, like `(object)-`.
As with array nodes, `(object)` can be used on any valid object node if desired.
----
Converting JiK back to JSON is a trivial process: literal nodes are encoded as their literal value; array nodes are encoded as their items, comma-separated and surrounded with `[]`; object nodes are encoded as their key/value pairs, comma-separated and surrounded with `{}`.
Only valid JiK nodes can be encoded to JSON; if a JiK document contains an invalid node, the entire document must fail to encode, rather than "guessing" at the intent. As well, a JiK document must contain only a single top-level node to be valid, unless the output is intended to be a JSON stream, in which case arbitrary numbers of nodes are allowed, each a separate JSON value.
* A literal node is valid if it contains a single unnamed argument.
* An array node is valid if it contains only unnamed arguments and/or child nodes named "-". If it contains no arguments and no child nodes, its nodename *must* have the `(array)` type annotation.
* An object node is valid if it contains only named properties and/or child nodes. Additionally, all "keys" must be unique within the node, whether they're encoded as property names or child node names. If it contains no properties and no child nodes, its nodename *must* have the `(object)` type annotation.
----
Note that, outside of array/object items, the nodename is not meaningful in JiK.
For simplicity, this document uses `-` for all such nodenames
(and it is recommended that an automated JSON-to-KDL converter do the same),
but this means it is possible to write a JiK object as meaningful KDL
and embed it within a larger KDL document.
Here's a fictitious example describing an HTTP request with a JSON body,
where the `body` node is an embedded JiK node
that nevertheless reads as fairly natural KDL.
```kdl
request "/api/cart" method="PUT" {
body {
items {
- id=1234 amount=1
- id=2341 amount=2 {
options {
color "red"
size "XXL"
}
}
}
}
}
```
The `body` node represents the JSON object
```json
{
"items": [
{"id": 1234, "amount": 1},
{"id": 2341, "amount": 2, "options": {"color": "red", "size": "XXL"}}
]
}
```

15
Makefile Normal file
View File

@ -0,0 +1,15 @@
LIBDIR := lib
include $(LIBDIR)/main.mk
$(LIBDIR)/main.mk:
ifneq (,$(shell grep "path *= *$(LIBDIR)" .gitmodules 2>/dev/null))
git submodule sync
git submodule update --init
else
ifneq (,$(wildcard $(ID_TEMPLATE_HOME)))
ln -s "$(ID_TEMPLATE_HOME)" $(LIBDIR)
else
git clone -q --depth 10 -b main \
https://github.com/martinthomson/i-d-template $(LIBDIR)
endif
endif

131
QUERY-SPEC.md Normal file
View File

@ -0,0 +1,131 @@
# KDL Query Language Spec
The KDL Query Language is a small language specially tailored for querying KDL
documents to extract nodes and even specific data. It is loosely based on CSS
selectors for familiarity and ease of use. Think of it as CSS Selectors or
XPath, but for KDL!
This document describes KQL `next`. It is unreleased.
## Selectors
Selectors use selection operators to filter nodes that will be returned by an
API using KQL. The main differences between this and CSS selectors are the
lack of `*` (use `[]` instead), the specific syntax for descendants and siblings, and the specific syntax for
[matchers](#matchers) (the stuff between `[` and `]`), which is similar, but not identical to CSS.
* `a > b`: Selects any `b` element that is a direct child of an `a` element.
* `a >> b`: Selects any `b` element that is a _descendant_ of an `a` element.
* `a >> b || a >> c`: Selects all `b` and `c` elements that are descendants of an `a` element. Any selector may be on either side of the `||`. Multiple `||` are supported.
* `a + b`: Selects any `b` element that is placed immediately after a sibling `a` element.
* `a ++ b`: Selects any `b` element that follows an `a` element as a sibling, either immediately or later.
* `[accessor()]`: Selects any element, filtered by [an accessor](#accessors). (`accessor()` is a placeholder, not an actual accessor)
* `a[accessor()]`: Selects any `a` element, filtered by an accessor.
* `[]`: Selects any element.
## Matchers
Matchers are used to filter nodes by their various attributes (such as values,
properties, node names, etc). With the exception of `top()` and `()`, they are all
used inside a `[]` selector. Some matchers are unary, but most of them involve
binary operators.
The `top()` matcher can only be used as the first matcher of a selector. This means
that it cannot be the right operand of the `>`, `>>`, `+`, or `++` operators. As `||`
combines selectors, the `top()` can appear just after it. For instance,
`a > b || top() > b` is valid, but `a > top()` is not.
* `top()`: Returns all toplevel children of the current document.
* `top() > []`: Equivalent to `top()` on its own.
* `(foo)`: Selects any element whose type annotation is `foo`.
* `()`: Selects any element with any type annotation.
* `[val()]`: Selects any element with a value.
* `[val(1)]`: Selects any element with a second value.
* `[prop(foo)]`: Selects any element with a property named `foo`.
* `[prop]`: Selects any element with a property named `prop`.
Attribute matchers support certain binary operators:
* `[val() = 1]`: Selects any element whose first value is 1.
* `[prop(name) = 1]`: Selects any element with a property `name` whose value is 1.
* `[name = 1]`: Equivalent to the above.
* `[name() = hi]`: Selects any element whose _node name_ is "hi". Equivalent to just `hi`, but more useful when using string operators.
* `[tag() = hi]`: Selects any element whose tag is "hi". Equivalent to just `(hi)`, but more useful when using string operators.
* `[val() != 1]`: Selects any element whose first value exists, and is not 1.
The following operators work with any `val()` or `prop()` values.
If the value is not of the same type, the operator will always fail ("1" is
never coerced to 1, and there is no "universal" ordering across all types.):
* `[val() > 1]`: Selects any element whose first value is greater than 1.
* `[val() >= 1]`: Selects any element whose first value is greater than or equal to 1.
* `[val() < 1]`: Selects any element whose first value is less than 1.
* `[val() <= 1]`: Selects any element whose first value is less than or equal to 1.
The following operators work only with string `val()`, `prop()`, `tag()`, or `name()` values.
If the value is not a string, the matcher will always fail:
* `[val() ^= foo]`: Selects any element whose first value starts with "foo".
* `[val() $= foo]`: Selects any element whose first value ends with "foo".
* `[val() *= foo]`: Selects any element whose first value contains "foo".
The following operators work only with `val()` or `prop()` values. If the value
is not one of those, the matcher will always fail:
* `[val() = (foo)]`: Selects any element whose type annotation is `foo`.
## Examples
Given this document:
```kdl
package {
name foo
version "1.0.0"
dependencies platform=windows {
winapi "1.0.0" path="./crates/my-winapi-fork"
}
dependencies {
miette "2.0.0" dev=#true integrity=(sri)sha512-deadbeef
}
}
```
Then the following queries are valid:
* `package >> name`
* -> fetches the `name` node itself
* `top() > package >> name`
* -> fetches the `name` node, guaranteeing that `package` is in the document root.
* `dependencies`
* -> deep-fetches both `dependencies` nodes
* `dependencies[platform]`
* -> fetches any dependencies nodes with a `platform` prop (just the one, in this case)
* `dependencies[prop(platform)]`
* -> Identical to the above. Plain identifiers are equivalent to `prop(<identifier>)`.
* `dependencies > []`
* -> fetches all direct-child nodes of any `dependencies` nodes in the
document. In this case, it will fetch both `miette` and `winapi` nodes.
## Full Grammar
Rules that are not defined in this grammar are prefixed with `$`, see [the KDL
grammar](https://kdl.dev/spec/#name-full-grammar) for
what they expand to.
```
query-str := $bom? query
query := selector q-ws+ "||" q-ws+ query | selector
selector := filter q-ws+ selector-operator q-ws+ selector-subsequent | filter
selector-subsequent := matchers q-ws+ selector-operator q-ws+ selector-subsequent | matchers
selector-operator := ">>" | ">" | "++" | "+"
filter := "top(" q-ws* ")" | matchers
matchers := type-matcher $string? accessor-matcher* | $string accessor-matcher* | accessor-matcher+
type-matcher := "(" q-ws* ")" | $type
accessor-matcher := "[" q-ws* (comparison | accessor)? q-ws* "]"
comparison := accessor q-ws+ matcher-operator q-ws+ ($type | $string | $number | $keyword)
accessor := "val(" q-ws* $integer q-ws* ")" | "prop(" q-ws* $string q-ws* ")" | "name(" q-ws* ")" | "tag(" q-ws* ")" | "values(" q-ws* ")" | "props(" q-ws* ")" | $string
matcher-operator := "=" | "!=" | ">" | "<" | ">=" | "<=" | "^=" | "$=" | "*="
q-ws := $node-space
```

437
README.md
View File

@ -1,39 +1,166 @@
# KDL - The KDL Document Language
# The KDL Document Language
kdl is a document language with xml-like semantics that looks like you're
invoking a bunch of CLI commands!
KDL is a small, pleasant document language with XML-like node semantics that
looks like you're invoking a bunch of CLI commands! It's meant to be used both
as a serialization format and a configuration language, much like JSON, YAML, or
XML. It looks like this:
It's meant to be used both as a serialization format and a configuration
language, and is relatively light on syntax compared to XML.
```kdl
package {
name my-pkg
version "1.2.3"
There's a living [specification](SPEC.md), as well as
[implementations](#implementations). The language is based on
[SDLang](https://sdlang.org), with a number of modifications and
clarifications on its syntax and behavior.
dependencies {
// Nodes can have standalone values as well as
// key/value pairs.
lodash "^3.2.1" optional=#true alias=underscore
}
scripts {
// "Raw" and dedented multi-line strings are supported.
message """
hello
world
"""
build #"""
echo "foo"
node -c "console.log('hello, world!');"
echo "foo" > some-file.txt
"""#
}
// `\` breaks up a single node across multiple lines.
the-matrix 1 2 3 \
4 5 6 \
7 8 9
// "Slashdash" comments operate at the node level,
// with just `/-`.
/-this-is-commented {
this entire node {
is gone
}
}
}
```
For more details, see the [overview below](#overview).
There's a living [specification](https://kdl.dev/spec/), as well as various
[implementations](#implementations). You can also check out the [FAQ](#faq) to
answer all your burning questions!
The current version of the KDL spec is
[KDL 2.0.0](https://kdl-org.github.io/kdl/#go.draft-marchan-kdl2.html). For legacy KDL,
please refer to the [KDL 1.0.0
spec](https://github.com/kdl-org/kdl/blob/2.0.0/SPEC_v1.md). All users are
encouraged to migrate. [Migration is forward-and-backward-compatible and
safe](https://kdl-org.github.io/kdl/#go.draft-marchan-kdl2.html#compatibility), and can
be automated.
In addition to a spec for KDL itself, there are specifications for [a KDL Query
Language](QUERY-SPEC.md) based on CSS selectors, and [a KDL Schema
Language](SCHEMA-SPEC.md) loosely based on JSON Schema.
The language is based on [SDLang](https://sdlang.org), with a [number of
modifications and clarifications on its syntax and behavior](#why-not-sdlang).
We are grateful for their work as an inspiration to ours.
[Play with it in your browser!](https://kdl.dev/play/)
## Design and Discussion
kdl is still extremely new, and discussion about the format should happen over
on the [discussions page](https://github.com/kdoclang/kdl/discussions). Feel free
to jump in and give us your 2 cents!
KDL 2.0.0 has been finalized, and no further changes are expected. For questions
about KDL and discussions, please see the [discussions
page](https://github.com/kdl-org/kdl/discussions). For minor editorial fixes or
critical spec errata, please feel free to [file an
issue](https://github.com/kdl-org/kdl/issues).
## Design Principles
## Used By
1. Maintainability
1. Flexibility
1. Cognitive simplicity and Learnability
1. Ease of de/serialization
1. Ease of implementation
A lot of folks have started picking up KDL for both personal projects, and
larger open source, and even proprietary projects! This section includes a list
of some examples of KDL in the wild (either v1, v2, or both):
* [Zellij](https://zellij.dev) - Terminal workspace/multiplexer
* [Niri](https://github.com/YaLTeR/niri) - Scrollable-tiling window manager for Wayland
* [Bikeshed](https://github.com/speced/bikeshed) ([here](https://github.com/speced/bikeshed-boilerplate/blob/main/boilerplate/doctypes.kdl) and [here](https://github.com/speced/bikeshed-data/blob/main/data/manifest.txt)) - Specification pre-processor used by CSS, C++, WHATWG, various W3C working groups, and others.
* [orogene](https://orogene.dev) - Lightning-fast JavaScript package manager
* [Onyx](https://onyxlang.io/) - An efficient, procedural, and pragmatic programming language that compiles to WASM. Used for package manifests.
* [Pop!_OS/System76 Scheduler](https://github.com/pop-os/system76-scheduler) - Scheduling service which optimizes Linux's CPU scheduler and makes it go faster.
* [ImStyle](https://patitotective.github.io/ImStyle/) - ImGui application styling with Nim and KDL
* [fmod-rs](https://github.com/CAD97/fmod-rs) - Rust bindings to FMOD Core and FMOD Studio
* [mise](https://mise.jdx.dev/) - dev tools, env vars, task runner
* [Camping](https://github.com/camping/camping) - Ruby web microframework
* [Iron Vault](https://ironvault.quest) - VTT (Virtual Tabletop) plugin for Obsidian for the Ironsworn family of games
* [Microsoft TypeScript DOM Generator](https://github.com/microsoft/TypeScript-DOM-lib-generator) - Tool for generating DOM-related TypeScript and JavaScript library files
* [Ferron](https://ferron.sh/) - A fast, memory-safe web server written in Rust
* You?
## Implementations
* Rust: [kdl-rs](https://github.com/kdl-org/kdl-rs)
> [!INFO] There are two major versions of KDL. Different libraries may support one or the
> other, or even provide a "hybrid" mode where both versions are attempted, since
> there's no data ambiguity between v1 and v2 documents.
| Language | Implementation | v1 | v2 | Notes |
|---|---|---|---|---|
| C | [ckdl](https://github.com/tjol/ckdl) | ✅ | ✅ | |
| C#/.NET | [Kadlet](https://github.com/oledfish/Kadlet) | ✅ | ✖️ | |
| C#/.NET | [KadSharp](https://github.com/AndreyAkinshin/KdlSharp) | ✅ | ✅ | .NET Std: 2.1+, .NET 6+, .NET FW 4.7.2+, Mono, Xamarin |
| C++ | [kdlpp](https://github.com/tjol/ckdl) | ✅ | ✅ | part of ckdl, requires C++20 |
| Common Lisp | [kdlcl](https://github.com/chee/kdlcl) | ✅ | ✖️ | |
| Crystal | [kdl-cr](https://github.com/danini-the-panini/kdl-cr) | ✅ | ✖️ | |
| Dart | [kdl-dart](https://github.com/danini-the-panini/kdl-dart) | ✅ | ✅ | |
| Elixir | [kuddle](https://github.com/IceDragon200/kuddle) | ✅ | ✅ | |
| Go | [gokdl](https://github.com/lunjon/gokdl) | ✅ | ✖️ | |
| Go | [kdl-go](https://github.com/sblinch/kdl-go) | ✅ | ✖️ | |
| Go | [gokdl2](https://github.com/njreid/gokdl2) | ✅ | ✅ | Friendly errors & arena allocator |
| Haskell | [Hustle](https://github.com/fuzzypixelz/Hustle) | ✅ | ✖️ | |
| Haskell | [kdl-hs](https://github.com/brandonchinn178/kdl-hs) | ✅ | ✅ | Format/comment-preserving parser |
| Java | [kdl4j](https://github.com/kdl-org/kdl4j) | ✅ | ✅ | |
| JavaScript | [@bgotink/kdl](https://github.com/bgotink/kdl) | ✅ | ✅ | Format/comment-preserving parser |
| JavaScript | [@virtualstate/kdl](https://github.com/virtualstate/kdl) | ✅ | ✖️ | query only, JSX based |
| JavaScript | [kdljs](https://github.com/kdl-org/kdljs) | ✅ | ✅ | |
| Lua | [kdlua](https://github.com/danini-the-panini/kdlua) | ✅ | ✖️ | |
| Nim | [kdl-nim](https://github.com/Patitotective/kdl-nim) | ✅ | ✖️ | |
| OCaml | [ocaml-kdl](https://github.com/eilvelia/ocaml-kdl) | ✅ | ✅ | |
| PHP | [kdl-php](https://github.com/kdl-org/kdl-php) | ✅ | ✖️ | |
| Python | [ckdl](https://github.com/tjol/ckdl) | ✅ | ✅ | |
| Python | [cuddle](https://github.com/djmattyg007/python-cuddle) | ✅ | ✖️ | |
| Python | [kdl-py](https://github.com/tabatkins/kdlpy) | ✅ | ✅ | |
| Ruby | [kdl-rb](https://github.com/danini-the-panini/kdl-rb) | ✅ | ✅ | |
| Rust | [kdl-rs](https://github.com/kdl-org/kdl-rs) | ✅ | ✅ | Format/comment-preserving parser |
| Rust | [knus](https://crates.io/crates/knus/) | ✅ | ✖️ | Serde-_style_ derive macros (not actual Serde) |
| Swift | [kdl-swift](https://github.com/danini-the-panini/kdl-swift) | ✅ | ✖️ | |
| XSLT | [xml2kdl](https://github.com/Devasta/XML2KDL) | ✅ | ✖️ | |
| Zig | [zig-kdl](https://codeberg.org/desttinghim/zig-kdl) | ✅ | ✅ | Format/comment-preserving parser |
## Compatibility Test Suite
There is a [compatibility test suite](tests/README.md) available for KDL
implementors to check that their implementations are actually spec-compatible.
The implementations above are not guaranteed to pass this test suite in its
entirety, but in the future, may be required to in order to be included here.
## Editor Support
* [Intellij IDEA](https://plugins.jetbrains.com/plugin/20136-kdl-document-language)
* [Sublime Text](https://packagecontrol.io/packages/KDL)\*
* [TreeSitter](https://github.com/tree-sitter-grammars/tree-sitter-kdl) (neovim, among others)
* [VS Code](https://marketplace.visualstudio.com/items?itemName=kdl-org.kdl&ssr=false#review-details)\*
* [vim](https://github.com/imsnif/kdl.vim)
* [Kate](https://github.com/larsgw/katepart-kdl)\*
* [Zed](https://zed.dev/extensions/kdl)
\* Supports KDL 2.0.0
## Overview
### Basics
A KDL node is a node name, followed by zero or more "arguments", and
A KDL node is a node name string, followed by zero or more "arguments", and
children.
```kdl
@ -46,10 +173,10 @@ You can also have multiple values in a single node!
bookmarks 12 15 188 1234
```
Nodes can have properties.
Nodes can have properties, with string keys.
```kdl
author "Alex Monad" email="alex@example.com" active=true
author "Alex Monad" email=alex@example.com active=#true
```
And they can have nested child nodes, too!
@ -67,46 +194,77 @@ Nodes without children are terminated by a newline, a semicolon, or the end of
a file stream:
```kdl
node1; node2; node3;
node1; node2; node3
```
### Values
KDL supports 4 data types:
* Strings: `"hello world"`
* Numbers: `123.45`
* Booleans: `true` and `false`
* Null: `null`
* Strings: `unquoted`, `"hello world"`, or `#"hello world"#`
* Numbers: `123.45`, `0xdeadbeef`, `#inf`, `#-inf`, `#nan`
* Booleans: `#true` and `#false`
* Null: `#null`
#### Strings
It supports two different formats for string input: escaped and raw.
It supports three different formats for string input: unquoted, quoted, and raw.
```kdl
node "this\nhas\tescapes"
other r"C:\Users\zkat\"
```
Both types of string can be multiline as-is, without a different syntax:
```kdl
string "my
multiline
value"
node1 this-is-a-string
node2 "this\nhas\tescapes"
node3 #"C:\Users\zkat\raw\string"#
```
And for raw strings, you can add any number of # after the r and the last " to
disambiguate literal " characters:
You don't have to quote strings unless any the following apply:
* The string contains whitespace.
* The string contains any of `[]{}()\/#";=`.
* The string is one of `true`, `false`, `null`, `inf`, `-inf`, or `nan`.
* The strings starts with a digit, or `+`/`-`/`.`/`-.`,`+.` and a digit.
(aka "looks like a number")
In essence, if it can get confused for other KDL or KQL syntax, it needs
quotes.
Both types of quoted string can be written across multiple lines by using triple
quotes (`"""`) followed immediately by a newline. Additionally, common
indentation shared with the line containing the closing quotes will be
stripped/dedented:
```kdl
other-raw r#"hello"world"#
string """
my
multiline
value
"""
```
Raw strings, which do not support `\` escapes and can be used when you want
certain kinds of strings to look nicer without having to escape a lot:
```kdl
exec #"""
echo "foo"
echo "bar"
cd C:\path\to\dir
"""#
regex #"\d{3} "[^/"]+""#
```
You can add any number of `#`s before and after the opening and
closing `#` to disambiguate literal closing `#"` sequences:
```kdl
other-raw ##"hello#"world"##
```
#### Numbers
There's 4 ways to represent numbers in KDL. KDL does not prescribe any
representation for these numbers, and it's entirely up to individual
implementations whether to represent all numbers with a single type, or to
have different representations for different forms.
There are 4 ways to represent numbers in KDL, plus 3 float keywords. KDL does
not prescribe any representation for these numbers, and it's entirely up to
individual implementations whether to represent all numbers with a single type,
or to have different representations for different forms.
KDL has regular decimal-radix numbers, with optional decimal part, as well as
an optional exponent.
@ -124,6 +282,13 @@ my-octal 0o755
my-binary 0b10101101
```
If you're intending to represent IEEE 754 floats, there are three special
keywords you can use:
```kdl
special-floats #inf #-inf #nan
```
Finally, all numbers can have underscores to help readability:
```kdl
@ -142,7 +307,7 @@ comments can be nested.
C style multiline
*/
tag /*foo=true*/ bar=false
tag /*foo=#true*/ bar=#false
/*/*
hello
@ -150,20 +315,36 @@ hello
```
On top of that, KDL supports `/-` "slashdash" comments, which can be used to
comment out individual nodes, arguments, or children:
comment out individual nodes, entries, or child blocks:
```kdl
// This entire node and its children are all commented out.
/-mynode "foo" key=1 {
/-mynode foo key=1 {
a
b
c
}
mynode /-"commented" "not commented" /-key="value" /-{
mynode /-commented "not commented" /-key=value /-{
a
b
}
// The above is equivalent to:
mynode "not commented"
```
### Type Annotations
KDL supports type annotations on both values and nodes. These can be
arbitrary, but can be used by individual implementations or use-cases to
constrain KDL's basic types. A number of type names are also reserved to have
specific meanings.
```kdl
numbers (u8)10 (i32)20 myfloat=(f32)1.5 {
strings (uuid)"123e4567-e89b-12d3-a456-426614174000" (date)"2021-02-03" filter=(regex)#"$\d+"#
(author)person name=Alex
}
```
### More Details
@ -175,24 +356,166 @@ title \
// Files must be utf8 encoded!
smile "😁"
smile 😁
// Instead of anonymous nodes, nodes and properties can be wrapped
// in "" for arbitrary node names.
"!@#$@$%Q#$%~@!40" "1.2.3" "!!!!!"=true
// Node names and property keys are just strings, so you can write them like
// quoted or raw strings, too!
"illegal(){}[]/\\=#;identifier" #"1.2.3"# "#false"=#true
// The following is a legal bare identifier:
foo123~!@#$%^&*.:'|/?+ "weeee"
// Identifiers are very flexible. The following is a legal bare identifier:
-<123~!$@%^&*,.:'`|?+>
// And you can also use unicode!
ノード お名前"☜(゚ヮ゚☜)"
// And you can also use non-ASCII unicode!
ノード お名前=ฅ^•ﻌ•^ฅ
// kdl specifically allows properties and values to be
// interspersed with each other, much like CLI commands.
foo bar=true "baz" quux=false 1 2 3
foo bar=#true baz quux=#false 1 2 3
```
## Design Principles
1. Human Maintainability
1. Flexibility
1. Cognitive Simplicity and Learnability
1. Ease of de/serialization
1. Ease of implementation
## Compatibility with JSON and XML
There are two specifications for writing KDL that can be losslessly translated
between it and JSON or XML. These specifications define a stricter _subset_ of
KDL that, even if not entirely idiomatic, is still valid and fits into the
data models of the other two languages:
* [JSON in KDL](JSON-IN-KDL.md)
* [XML in KDL](XML-IN-KDL.md)
## FAQ
#### How do you pronounce KDL?
Same as "cuddle".
#### Why yet another document language?
Because nothing out there felt quite right. The closest one I found was
SDLang, but that had some design choices I disagreed with.
<a name="why-not-sdlang"></a>
#### Ok, then, why not SDLang?
SDLang is an excellent base, but I wanted some details ironed out, and some
things removed that only really made sense for SDLang's current use-cases, including
some restrictions about data representation. KDL is very similar in many ways, except:
* The grammar and expected semantics are [well-defined and specified](https://kdl-org.github.io/kdl/#go.draft-marchan-kdl2.html).
This was the original impetus for working on KDL, followed by details that
seemed like they could be improved.
* There is only one "number" type. KDL does not prescribe representations, but
does have keywords for NaN, infinity, and negative infinity if decimal numbers
are intended to be represented as IEEE754 floats.
* Slashdash (`/-`) comments are great and useful!
* Quoteless "identifier" strings (e.g. `node foo=bar`, vs `node foo="bar"`).
* KDL does not have first-class date or binary data types. Instead, it
supports arbitrary type annotations for any custom data type you might need:
`(date)"2021-02-03"`, `(binary)"deadbeefbadc0ffee"`.
* Values and properties can be interspersed with each other, rather than one
having to follow the other. It was not clear whether this was actually allowed in SDLang.
* Multi-line strings are supported using `"""<newline>` and their lines are automatically
"dedented" to match their closing quotes' indentation level.
* Raw strings are written with `#` (`#"foo\bar"#`), instead of backticks. This,
while more verbose, allows embedding of languages, especially scripting
languages, that use this syntax on a regular basis, without additional escaping
(e.g. bash and JavaScript).
* KDL identifiers can use a wide range of UTF-8 and are much more lax about
valid characters than SDLang.
* KDL does not support "anonymous" nodes. Instead, any string can be used as a
node name. For lists of arbitrary values, there is a convention of naming the nodes
simply `-`.
* Namespaces are not supported, but `:` is a legal identifier character, and applications
can choose to implement namespaces as they see fit.
* KDL supports arbitrary identifiers for node names and attribute
names, meaning you can use arbitrary strings for those: `"123" "value"=1` is
a valid node, for example. This makes it easier to use KDL for
representing arbitrary key/value pairs using child nodes.
#### Have you seen that one XKCD comic about standards?
Yes. I have. Please stop linking me to it.
#### What about YAML?
YAML is a great, widespread language. Unlike KDL, which is node-based (like
XML or HTML), it's based on map and array data structures, which can provide
an easier serialization experience in some cases.
At the same time, YAML can be ambiguous about what types the data written into
it is. There's also a persistent issue where very large YAML files become
unmanageable, especially due to the significant indentation feature.
KDL is designed to avoid these particular pitfalls by always being explicit
about types, and having clearly-delimited scope (and the ability to
auto-indent/auto-format). Syntax errors are easier to catch, and large files
are (hopefully!) much more manageable.
#### What about JSON?
JSON is a great serialization language, but it can be very difficult to use as
a human configuration language. This is largely due to its very specific, very
strict syntax, as well as its lack of support for comments.
KDL, on the other hand, has great comment support, and has a much more
forgiving syntax without being so flexible as to allow certain classes of
unfortunate mistakes. It also has much more flexibility around how to
represent data.
If you need to interoperate with a service that consumes or emits JSON, or for
some other reason have need to write "JSON in KDL", [we have JiK, an official
microsyntax for losslessly encoding JSON](JSON-IN-KDL.md).
#### What about TOML?
It nests very poorly. It doesn't fare well with large files. Also, I felt some
discomfort [continuing to use and promote something by its
creator](https://en.wikipedia.org/wiki/Tom_Preston-Werner#Resignation_from_GitHub).
#### What about XML?
XML is actually pretty fantastic, and has long been a standard for data
exchange across many industries. At the same time, XML is known to be very
verbose, and editing it involves writing (and updating) matching tags. Another
large pitfall with XML is its lack of direct support for arbitrary string
key/value pairs, so what would be a simple `foo: x` in some languages has to
be represented as `<entry name="foo" value="x" />` or something similar. XML
also functions great as a **markup** language. That is, it is easy to
intersperse with text, like HTML.
KDL, just like XML, is a node/element-based language, but with much more
lightweight syntax. It also adds the ability to apply anonymous values
directly to a node, rather than as children. That is, `nodename 1 2 3` instead
of `<element><child>1</child><child>2</child>(etc)</element>`. This can make
it much more manageable and readable as a human configuration language, and is
also less verbose when exchanging documents across APIs!
Finally, KDL is **not** a markup language. XML or HTML do a much better job of
"marking up" a text document with special tags, although KDL can still be
useful for templating engines that want to be more strict about text
fragments.
If you need to interoperate with a service that consumes or emits XML, or for
some other reason have need to write "XML in KDL", [we have XiK, an official
microsyntax for losslessly encoding XML](XML-IN-KDL.md).
## License
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.
This license applies to the text and assets _in this repository_.
Implementations of this specification are not "derivative works", and thus are
not bound by the restrictions of CC-BY-SA.
The KDL logo design and files were generously contributed by Timothy Merritt
([@timmybytes](https://github.com/timmybytes)), and are also available under
the same license.

347
SCHEMA-SPEC.md Normal file
View File

@ -0,0 +1,347 @@
# KDL Schema Specification
The KDL Schema specification describes a schema language for use with KDL,
written in KDL itself. A schema language allows users to describe and
constrain the allowed semantics of a KDL document. This can be used for many
purposes: documentation for users, automated verification, or even automated
generation of bindings!
This document describes KDL Schema version `1.0.0`. It was released on September 11, 2021.
## The Formal Schema
For the full KDL Schema schema itself, see
[examples/kdl-schema.kdl](./examples/kdl-schema.kdl).
## Definition
### `document` node
This is the toplevel node in a KDL Schema. It is required, and there must be
exactly one, at the very toplevel of a document.
#### Values
None.
#### Properties
None.
#### Children
* [`info`](#info-node) - one info node for that describes the schema itself.
* [`node`](#node-node) - zero or more toplevel nodes for the KDL document this schema describes.
* [`definitions`](#definitions-node) (optional): Definitions of nodes, values, props, and children block to reference in the toplevel nodes.
* `node-names` (optional): [Validations](#validation-nodes) to apply to the _names_ of child nodes.
* `other-nodes-allowed` (optional): Whether to allow nodes other than the ones explicitly listed here. Defaults to `#false`.
* [`tag`](#tag-node) - zero or more toplevel tags for nodes in the KDL document that this schema describes.
* `tag-names` (optional): [Validations](#validation-nodes) to apply to the _names_ of tags of child nodes.
* `other-tags-allowed` (optional): Whether to allow node tags other than the ones explicitly listed here. Defaults to `#false`.
### `info` node
The `info` node describes the schema itself.
#### Values
None.
#### Properties
None.
#### Children
* [`title`](#title-node) (optional): zero or more titles
* [`description`](#description-node) (optional): zero or more descriptions
* [`author`](#author-and-contributor-nodes) (optional): zero or more authors
* [`contributor`](#author-and-contributor-nodes) (optional): zero or more contributors
* [`link`](#link-node) (optional): zero or more URLs
* [`license`](#license-node) (optional): zero or more licenses
* [`published`](#published-and-modified-nodes) (optional): a publication date
* [`modified`](#published-and-modified-nodes) (optional): a modification date
* [`version`](#version-node) (optional): a [SemVer](https://semver.org/) version number
### `title` node
The title of the schema or the format it describes.
#### Values
* Title
#### Properties
* `lang` (optional): An IETF BCP 47 language tag
### `description` node
A description of the schema or the format it describes.
#### Values
* Description
#### Properties
* `lang` (optional): An IETF BCP 47 language tag
### `author` and `contributor` nodes
Author(s) of the schema.
#### Values
* Author name
#### Properties
* `orcid` (optional): The [ORCID](https://orcid.org/) of the author.
#### Children
* [`link`](#link-node) (optional): zero or more URLs
### `link` node
Links to the schema itself, and to sources about the schema.
#### Values
* URI/IRI - A URI/IRI that the link points to
#### Properties
* `rel`: what the link is for (`self` or `documentation`)
* `lang` (optional): An IETF BCP 47 language tag
### `license` node
The license(s) that the schema is licensed under.
#### Values
* License name - Name of the used license
#### Properties
* `spdx` (optional): an [SPDX license identifier](https://spdx.dev/ids/)
#### Children
* [`link`](#link-node): one or more URLs
### `published` and `modified` nodes
When the schema was published or last modified respectively.
#### Values
* Publication or modification date - As a ISO8601 date
#### Properties
* `time` (optional): an ISO8601 Time to accompany the date
### `version` nodes
The version number of this version of the schema.
#### Values
* Version - Semver version specification
### `node` node
The `node` node describes node instances in a document. These may either be at
the toplevel of the document, or they may be nested inside a children block in
another node.
#### Values
* Node name (optional) - A string name for the node. If present, the node's rules/validations will apply only to children with this node name. Otherwise, the rules will apply to _all_ child nodes, regardless of whether they're named or not.
#### Properties
* `description` (optional): An informational description of the purpose of this node.
* `id` (optional): A globally unique identifier for this node.
* `ref` (optional): A [KDL Query](./QUERY-SPEC.md) string relative to the root of the document. If present, all properties, values, and children defined in the target node will be copied to this node, replacing any conflicts.
#### Children
* `min` (optional): Minimum number of this kind of node (or any node, if the name is missing) allowed in the parent's children block.
* `max` (optional): Maximum number of this kind of node (or any node, if the name is missing) allowed in the parent's children block.
* `prop-names` (optional): [Validations](#validation-nodes) to apply to the _names_ of properties.
* `other-props-allowed` (optional): Whether to allow props other than the ones explicitly listed here. Defaults to `false`.
* `tag`: [Validations](#validation-nodes) to apply to the tag of the node.
* [`prop`](#prop-node) - zero or more properties for this node.
* [`value`](#value-node) - zero or more values for this node.
* [`children`](#children-node) - zero or more children for this node.
### `tag` node
The `tag` describes the tags allowed in a children block or toplevel document.
#### Values
* Tag name (optional) - A tag for the node. If present, the node's rules/validations will apply only to children with this tag. Otherwise, the rules will apply to _all_ child nodes with tags.
#### Properties
* `description` (optional): An informational description of the purpose of this node.
* `id` (optional): A globally unique identifier for this node.
* `ref` (optional): A [KDL Query](./QUERY-SPEC.md) string relative to the root of the document. If present, all properties, values, and children defined in the target node will be copied to this node, replacing any conflicts.
#### Children
* [`node`](#node-node) - zero or more toplevel nodes that this tag is allowed to be on.
* `node-names` (optional): [Validations](#validation-nodes) to apply to the _names_ of nodes with this tag.
* `other-nodes-allowed` (optional): Whether to allow nodes other than the ones explicitly listed here. Defaults to `false`.
### `prop` node
Represents a property of a node, which is a key/value pair in KDL.
#### Values
* `key` (optional) - String key for the property. If this value is missing, the `prop` node's attributes will apply to all properties of its parent.
#### Properties
* `description` (optional): An informational description of the purpose of this property.
* `id` (optional): A globally unique identifier for this property.
* `ref` (optional): A [KDL Query](./QUERY-SPEC.md) string relative to the root of the document. If present, all properties defined in the target property will be copied to this property, replacing any conflicts.
#### Children
* `required` (optional): A boolean value indicating whether this property is required.
* Any [validation node](#validation-nodes).
### `value` node
Used to describe one or more values for a KDL node.
#### Values
None.
#### Properties
* `description` (optional): An informational description of the purpose of this value.
* `id` (optional): A globally unique identifier for this value.
* `ref` (optional): A [KDL Query](./QUERY-SPEC.md) string relative to the root of the document. If present, all values defined in the target value will be copied to this value, replacing any conflicts.
#### Children
* `min` (optional): Minimum number of values allowed.
* `max` (optional): Maximum number of values allowed.
* Any [validation node](#validation-nodes).
### `children` node
Denotes KDL node children.
#### Values
None.
#### Properties
* `description` (optional): An informational description of the purpose of this children block.
* `id` (optional): A globally unique identifier for this children block.
* `ref` (optional): A [KDL Query](./QUERY-SPEC.md) string relative to the root of the document. If present, all children defined in the target children block will be copied to this children block, replacing any conflicts.
#### Children
* [`node`](#node-node) - zero or more child nodes.
* `node-names` (optional): [Validations](#validation-nodes) to apply to the _names_ of child nodes.
* `other-nodes-allowed` (optional): Whether to allow nodes other than the ones explicitly listed here. Defaults to `false`.
### Validation Nodes
The following nodes are shared validations between props and values, and can
be used as children to either definition. They are also used to verify node
and property names when the `node-names` or `prop-names` options are activated.
#### Generic validations
* `tag`: [Validations](#validation-nodes) to apply to the tag of the value.
* `type`: A string denoting the type of the property value.
* `enum`: A specific list of allowed values for this property. May be heterogeneous as long as it agrees with the `type`, if specified.
#### String validations
* `pattern`: Regex pattern or patterns to test prop values against. Specific regex syntax may be implementation-dependent.
* `min-length`: Minimum length, if a string.
* `max-length`: Maximum length, if a string.
* `format`: Intended data format, if the value is a string. Reserved values are:
* `date-time`: ISO8601 date/time format.
* `time`: "Time" section of ISO8601.
* `date`: "Date" section of ISO8601.
* `duration`: ISO8601 duration format.
* `decimal`: IEEE 754-2008 decimal string format.
* `currency`: ISO 4217 currency code.
* `country-2`: ISO 3166-1 alpha-2 country code.
* `country-3`: ISO 3166-1 alpha-3 country code.
* `country-subdivision`: ISO 3166-2 country subdivision code.
* `email`: RFC5302 email address.
* `idn-email`: RFC6531 internationalized email address.
* `hostname`: RFC1123 internet hostname.
* `idn-hostname`: RFC5890 internationalized internet hostname.
* `ipv4`: RFC2673 dotted-quad IPv4 address.
* `ipv6`: RFC2373 IPv6 address.
* `url`: RFC3986 URI.
* `url-reference`: RFC3986 URI Reference.
* `irl`: RFC3987 Internationalized Resource Identifier.
* `irl-reference`: RFC3987 Internationalized Resource Identifier Reference.
* `url-template`: RFC6570 URI Template.
* `uuid`: RFC4122 UUID.
* `regex`: Regular expression. Specific patterns may be implementation-dependent.
* `base64`: A Base64-encoded string, denoting arbitrary binary data.
* `kdl-query`: A [KDL Query](./QUERY-SPEC.md) string.
#### Number validations
* `%`: Only used for numeric values. Constrains them to be multiples of the given number(s).
* `>`: Greater than.
* `>=`: Greater than or equal to.
* `<`: Less than.
* `<=`: Less than or equal to.
* `format`: Intended data format for numeric values. Reserved values are:
* `i8`: 8-bit signed integer
* `i16`: 16-bit signed integer
* `i32`: 32-bit signed integer
* `i64`: 64-bit signed integer
* `i128`: 128-bit signed integer
* `u8`: 8-bit unsigned integer
* `u16`: 16-bit unsigned integer
* `u32`: 32-bit unsigned integer
* `u64`: 64-bit unsigned integer
* `u128`: 128-bit unsigned integer
* `isize`: Platform-dependent signed integer
* `usize`: Platform-dependent unsigned integer
* `f32`: IEEE 754 single (32-bit) precision floating point number
* `f64`: IEEE 754 double (64-bit) precision floating point number
* `decimal64`: IEEE 754-2008 64-bit decimal floating point number
* `decimal128`: IEEE 754-2008 128-bit decimal floating point number
### `definitions` node
Definitions to reference in parts of the top-level `node`s.
#### Values
None.
#### Properties
None.
#### Children
* [`node`](#node-node) - zero or more node definitions.
* [`tag`](#tag-node) - zero or more toplevel tags for nodes in the KDL document that this schema describes.
* [`prop`](#prop-node) - zero or more property definitions.
* [`value`](#value-node) - zero or more value definitions.
* [`children`](#children-node) - zero or more definitions of children blocks.

346
SPEC.md
View File

@ -1,345 +1 @@
# KDL Spec
This is the semi-formal specification for KDL, including the intended data
model and the grammar.
This document describes KDL version `1.0.0-pre.0`.
## Introduction
KDL is a node-oriented document language. Its niche and purpose overlaps with
XML, and as do many of its semantics. You can use KDL both as a configuration
language, and a data exchange or storage format, if you so choose.
## Components
### Document
The toplevel concept of KDL is a Document. A Document is composed of zero or
more [Nodes](#node), separated by newlines and whitespace, and eventually
terminated by an EOF.
All KDL documents should be UTF-8 encoded and conform to the specifications in
this document.
#### Example
The following is a document composed of two toplevel nodes:
```kdl
foo {
bar
}
baz
```
### Node
Being a node-oriented language means that the real core component of any KDL
document is the "node". Every node must have a name, which is either a legal
[Identifier](#identifier), or a quoted [String](#string).
Following the name are zero or more [Arguments](#argument) or
[Properties](#property), separated by either [whitespace](#whitespace) or [a
slash-escaped line continuation](#line-continuation). Arguments and Properties
may be interspersed in any order, much like is common with positional
arguments vs options in command line tools.
Arguments are ordered relative to each other and that order must be preserved
in order to maintain the semantics.
By contrast, Property order _SHOULD NOT_ matter to implementations.
[Children](#children-block) should be used if an order-sensitive key/value
data structure must be represented in KDL.
Nodes _MAY_ be prefixed with `/-` to "comment out" the entire node, including
its properties, arguments, and children, and make it act as plain whitespace,
even if it spreads across multiple lines.
Finally, a node is terminated by either a [Newline](#newline), a [Children
Block](#children-block), a semicolon (`;`) or the end of the file/stream (an
`EOF`).
#### Example
```kdl
foo 1 key="val" 3 {
bar
baz
}
```
### Identifier
A bare Identifier is composed of any unicode codepoint other than [non-initial
characters](#non-inidital-characters), followed by any number of unicode
codepoints other than [non-identifier characters](#non-identifier-characters).
Identifiers are terminated by [Whitespace](#whitespace) or
[Newlines](#newline).
### Non-initial characters
The following characters cannot be the first character in a bare
[Identifier](#identifier):
* Any decimal digit (0-9)
* Any [non-identifier characters](#non-identifier-characters)
### Non-identifier characters
The following characters cannot be used anywhere in a bare
[Identifier](#identifier):
* Any codepoint with hexadecimal value `0x20` or below.
* Any codepoint with hexadecimal value higher than `0x10FFFF`.
* Any of "\\<>{};[]=,"
### Line Continuation
Line continuations allow [Nodes](#node) to be spread across multiple lines.
A line continuation is one or more [whitespace](#whitespace) characters,
followed by a `\` character. This character can then be followed by more
[whitespace](#whitespace) and must be terminated by a [Newline](#newline)
(including the Newline that is part of single-line comments).
Following a line continuation, processing of a Node can continue as usual.
#### Example
```kdl
my-node 1 2 \ // comments are ok after \
3 4 // This is the actual end of the Node.
```
### Property
A Property is a key/value pair attached to a [Node](#node). A Property is
composed of an [Identifier](#identifier) or a [String](#string), followed
immediately by a `=`, and then a [Value](#value).
Properties should be interpreted left-to-right, with rightmost properties with
identical names overriding earlier properties. That is:
```
node a=1 a=2
```
In this example, the node's `a` value must be `2`, not `1`.
No other guarantees about order should be expected by implementers.
Deserialized representations may iterate over properties in any order and
still be spec-compliant.
Properties _MAY_ be prefixed with `/-` to "comment out" the entire token and
make it act as plain whitespace, even if it spreads across multiple lines.
### Argument
An Argument is a bare [Value](#value) attached to a [Node](#node), with no
associated key. It shares the same space as [Properties](#properties).
A Node may have any number of Arguments, which should be evaluated left to
right. KDL implementations _MUST_ preserve the order of Arguments relative to
each other (not counting Properties).
Arguments _MAY_ be prefixed with `/-` to "comment out" the entire token and
make it act as plain whitespace, even if it spreads across multiple lines.
### Example
```kdl
my-node 1 2 3 "a" "b" "c"
```
### Value
A value is either: a [String](#string), a [Raw String](#raw-string), a
[Number](#number), a [Boolean](#boolean), or [Null](#null)
Values _MUST_ be either [Arguments](#argument) or values of
[Properties](#property).
### String
Strings in KDL represent textual [Values](#value). They are delimited by `"`
on either side of any number of literal string characters except unescaped
`"` and `\`. This includes literal [Newline](#newline) characters, which means a
String Value can encompass multiple lines without behaving like a Newline for
[Node](#node) parsing purposes.
Strings _MUST_ be represented as UTF-8 values.
In addition to literal code points, a number of "escapes" are supported.
"Escapes" are the character `\` followed by another character, and are
interpreted as described in the following table:
| Name | Escape | Code Pt |
| TODO | `\n` | TODO |
| TODO | `\r` | TODO |
| TODO | `\t` | TODO |
| TODO | `\\` | TODO |
| TODO | `\"` | TODO |
| TODO | `\b` | TODO |
| TODO | `\f` | TODO |
| TODO | `\u{(0-6 hex chars)}` | Code point described by hex characters, up to `10FFF` |
### Raw String
Raw Strings in KDL are much like [Strings](#string), except they do not
support `\`-escapes. They otherwise share the same properties as far as
literal [Newline](#newline) characters go, and the requirement of UTF-8
representation.
Raw String literals are represented as `r"`, followed by zero or more `#`
characters, followed by any number of UTF-8 literals. The string is then
closed by a `"` followed by a _matching_ number of `#` characters. This means
that the string sequence `"` or `"#` and such must not match the closing `"`
with the same or more `#` characters as the opening `r"`.
#### Example
```kdl
my-string r#"hello\n\r\asd"world"#
```
### Number
Numbers in KDL represent numerical [Values](#value). There is no logical
distinction in KDL between real numbers, integers, and floating point numbers.
It's up to individual implementations to determine how to represent KDL
numbers.
There are four syntaxes for Numbers: Decimal, Hexadecimal, Octal, and Binary.
* Binary numbers start with `0b` and only allow `0` and `1` as digits, which may be separated by `_`. They represent numbers in radix 2.
* Octal numbers start with `0o` and only allow digits between `0` and `7`, which may be separated by `_`. They represent numbers in radix 8.
* Hexadecimal numbers start with `0x` and allow digits between `0` and `9`, as well as letters `A` through `F`, in either lower or upper case, which may be separated by `_`. They represent numbers in radix 16.
* Decimal numbers are a bit more special:
* They may optionally start with one of `-` or `+`, which determine whether they'll be positive or negative.
* They have no radix prefix.
* They use digits `0` through `9`.
* They may optionally include a decimal separator `.`, followed by more digits.
* They may optionally be followed by `E` or `e`, an optional `-` or `+`, and more digits, to represent an exponent value.
### Boolean
A boolean [Value](#value) is either the symbol `true` or `false`. These
_SHOULD_ be represented by implementation as boolean logical values, or some
approximation thereof.
#### Example
```kdl
my-node true value=false
```
### Null
The symbol `null` represents a null [Value](#value). It's up to the
implementation to decide how to represent this, but it generally signals the
"absence" of a value. It is reasonable for an implementation to ignore null
values altogether when deserializing.
#### Example
```kdl
my-node null key=null
```
### Whitespace
The following characters should be treated as non-[Newline](#newline) [white
space](https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt):
| Name | Code Pt |
|----------------------|---------|
| Character Tabulation | `U+0009` |
| Space | `U+0020` |
| No-Break Space | `U+00A0` |
| Ogham Space Mark | `U+1680` |
| En Quad | `U+2000` |
| Em Quad | `U+2001` |
| En Space | `U+2002` |
| Em Space | `U+2003` |
| Three-Per-Em Space | `U+2004` |
| Four-Per-Em Space | `U+2005` |
| Six-Per-Em Space | `U+2006` |
| Figure Space | `U+2007` |
| Punctuation Space | `U+2008` |
| Thin Space | `U+2009` |
| Hair Space | `U+200A` |
| Narrow No-Break Space| `U+202F` |
| Medium Mathematical Space | `U+205F` |
| Ideographic Space | `U+3000` |
### Newline
The following characters [should be treated as new
lines](https://www.unicode.org/versions/Unicode13.0.0/ch05.pdf):
| Acronym | Name | Code Pt |
|---------|-----------------|---------|
| CR | Carriage Return | `U+000D` |
| LF | Line Feed | `U+000A` |
| CRLF | Carriage Return and Line Feed | `U+000D` + `U+000A` |
| NEL | Next Line | `U+0085` |
| FF | Form Feed | `U+000C` |
| LS | Line Separator | `U+2028` |
| PS | Paragraph Separator | `U+2029` |
Note that for the purpose of new lines, CRLF is considered _a single newline_.
## Full Grammar
```
nodes := linespace* (node nodes?)? linespace*
node := '/-'? ws* identifier (node-space node-props-and-args)* (node-terminator | (node-space node-children))
node-props-and-args := '/-'? ws* (prop | value)
node-children := '/-'? ws* '{' nodes '}'
node-space := ws* escline ws* | ws+
node-terminator := single-line-comment | newline | ';'
identifier := (identifier-char - digit - [<>]) identifier-char* | string
identifier-char := unicode - digit - linespace - [\{}<>;[]=,]
prop := identifier '=' value
value := string | raw_string | number | boolean | 'null'
string := '"' character* '"'
character := '\' escape | [^\"]
escape := ["\\/bfnrt] | 'u{' hex-digit{1, 6} '}'
hex-digit := [0-9a-fA-F]
raw-string := 'r' raw-string-hash
raw-string-hash := '#' raw-string-hash '#' | raw-string-quotes
raw-string-quotes := '"' .* '"'
number := decimal | hex | octal | binary
decimal := integer ('.' [0-9]+)? exponent?
exponent := ('e' | 'E') integer
integer := sign? [0-9] [0-9_]*
sign := '+' | '-'
hex := '0x' hex-digit (hex-digit | '_')*
octal := '0o' [0-7] [0-7_]*
binary := '0b' ('0' | '1') ('0' | '1' | '_')*
boolean := 'true' | 'false'
escline := '\\' ws* (single-line-comment | newline)
linespace := newline | ws | single-line-comment
newline := See Table (All line-break white_space)
ws := bom | unicode-space | multi-line-comment
bom := '\u{FFEF}'
unicode-space := See Table (All White_Space unicode characters which are not `newline`)
single-line-comment := '//' ^newline+ newline
multi-line-comment := '/*' (commented-block | multi-line-comment) '*/'
commented-block := ('*' [^\/] | [^*])*
```
The v2 specification has been moved [here](draft-marchan-kdl2.md).

544
SPEC_v1.md Normal file
View File

@ -0,0 +1,544 @@
# KDL v1 Spec
This is the semi-formal specification for the legacy version of KDL, including
the intended data model and the grammar.
This document describes KDL version `1.0.0`. It was released on September 11, 2021.
Information in this spec is intended as both an accessible historical record,
and a reference for KDL implementors who are interested in supporting both major
versions of the language.
The v1 spec will not receive further updates outside of minor, inconsequential
rewordings or other superficial fixes and is considered a "legacy" version.
## Compatibility
KDL v2 is designed such that for any given KDL document in either v1 or v2, the
parse will either fail completely, or, if the parse succeeds, the data
represented by a v1 or v2 parser will be identical. This means that it's safe to
use a fallback parsing strategy in order to support both v1 and v2
simultaneously. For example, `node "foo"` is a valid node in both versions, and
should be represented identically by parsers.
KDL v2 is designed such that for any given KDL document written as KDL
1.0 or [KDL 2.0](https://kdl-org.github.io/kdl/#go.draft-marchan-kdl2.html),
the parse will either fail completely, or, if the
parse succeeds, the data represented by a v1 or v2 parser will be identical.
This means that it's safe to use a fallback parsing strategy in order to support
both v1 and v2 simultaneously. For example, `node "foo"` is a valid node in both
versions, and should be represented identically by parsers.
A version marker `/- kdl-version 1` (or `2`) _MAY_ be added to the beginning of
a KDL document, optionally preceded by the BOM, and parsers _MAY_ use that as a
hint as to which version to parse the document as.
## Introduction
KDL is a node-oriented document language. Its niche and purpose overlaps with
XML, and as do many of its semantics. You can use KDL both as a configuration
language, and a data exchange or storage format, if you so choose.
The bulk of this document is dedicated to a long-form description of all
[Components](#components) of a KDL document. There is also a much more terse
[Grammar](#full-grammar) at the end of the document that covers most of the
rules, with some semantic exceptions involving the data model.
KDL is designed to be easy to read _and_ easy to implement.
In this document, references to "left" or "right" refer to directions in the
*data stream* towards the beginning or end, respectively; in other words,
the directions if the data stream were only ASCII text. They do not refer
to the writing direction of text, which can flow in either direction,
depending on the characters used.
## Components
### Document
The toplevel concept of KDL is a Document. A Document is composed of zero or
more [Nodes](#node), separated by newlines and whitespace, and eventually
terminated by an EOF.
All KDL documents should be UTF-8 encoded and conform to the specifications in
this document.
#### Example
The following is a document composed of two toplevel nodes:
```kdl
foo {
bar
}
baz
```
### Node
Being a node-oriented language means that the real core component of any KDL
document is the "node". Every node must have a name, which is an
[Identifier](#identifier).
The name may be preceded by a [Type Annotation](#type-annotation) to further
clarify its type, particularly in relation to its parent node. (For example,
clarifying that a particular `date` child node is for the _publication_ date,
rather than the last-modified date, with `(published)date`.)
Following the name are zero or more [Arguments](#argument) or
[Properties](#property), separated by either [whitespace](#whitespace) or [a
slash-escaped line continuation](#line-continuation). Arguments and Properties
may be interspersed in any order, much like is common with positional
arguments vs options in command line tools.
[Children](#children-block) can be placed after the name and the optional
Arguments and Properties, possibly separated by either whitespace or a
slash-escaped line continuation.
Arguments are ordered relative to each other (but not relative to Properties)
and that order must be preserved in order to maintain the semantics.
By contrast, Property order _SHOULD NOT_ matter to implementations.
[Children](#children-block) should be used if an order-sensitive key/value
data structure must be represented in KDL.
Nodes _MAY_ be prefixed with `/-` to "comment out" the entire node, including
its properties, arguments, and children, and make it act as plain whitespace,
even if it spreads across multiple lines.
Finally, a node is terminated by either a [Newline](#newline), a semicolon (`;`)
or the end of the file/stream (an `EOF`).
#### Example
```kdl
foo 1 key="val" 3 {
bar
(role)baz 1 2
}
```
### Identifier
An Identifier is either a [Bare Identifier](#bare-identifier), which is an
unquoted string like `node` or `item`, or a [String](#string), which is quoted,
like `"node"` or `"two words"`. There's no semantic difference between the
kinds of identifier; this simply allows for the use of quotes to have unusual
identifiers that are inexpressible as bare identifiers.
### Bare Identifier
A Bare Identifier is composed of any Unicode codepoint other than [non-initial
characters](#non-initial-characters), followed by any number of Unicode
codepoints other than [non-identifier characters](#non-identifier-characters),
so long as this doesn't produce something confusable for a [Number](#number),
[Boolean](#boolean), or [Null](#null). For example, both a [Number](#number)
and an Identifier can start with `-`, but when an Identifier starts with `-`
the second character cannot be a digit. This is precisely specified in the
[Full Grammar](#full-grammar) below.
Identifiers are terminated by [Whitespace](#whitespace) or
[Newlines](#newline).
### Non-initial characters
The following characters cannot be the first character in a
[Bare Identifier](#identifier):
* Any decimal digit (0-9)
* Any [non-identifier characters](#non-identifier-characters)
Be aware that the `-` character can only be used as an initial
character if the second character is not a digit. This allows
identifiers to look like `--this`, and removes the ambiguity
of having an identifier look like a negative number.
### Non-identifier characters
The following characters cannot be used anywhere in a [Bare Identifier](#identifier):
* Any codepoint with hexadecimal value `0x20` or below.
* Any codepoint with hexadecimal value higher than `0x10FFFF`.
* Any of `\/(){}<>;[]=,"`
### Line Continuation
Line continuations allow [Nodes](#node) to be spread across multiple lines.
A line continuation is a `\` character followed by zero or more whitespace
characters and an optional single-line comment. It must be terminated by a
[Newline](#newline) (including the Newline that is part of single-line comments).
Following a line continuation, processing of a Node can continue as usual.
#### Example
```kdl
my-node 1 2 \ // comments are ok after \
3 4 // This is the actual end of the Node.
```
### Property
A Property is a key/value pair attached to a [Node](#node). A Property is
composed of an [Identifier](#identifier), followed immediately by a `=`, and then a [Value](#value).
Properties should be interpreted left-to-right, with rightmost properties with
identical names overriding earlier properties. That is:
```kdl
node a=1 a=2
```
In this example, the node's `a` value must be `2`, not `1`.
No other guarantees about order should be expected by implementers.
Deserialized representations may iterate over properties in any order and
still be spec-compliant.
Properties _MAY_ be prefixed with `/-` to "comment out" the entire token and
make it act as plain whitespace, even if it spreads across multiple lines.
### Argument
An Argument is a bare [Value](#value) attached to a [Node](#node), with no
associated key. It shares the same space as [Properties](#properties), and may be interleaved with them.
A Node may have any number of Arguments, which should be evaluated left to
right. KDL implementations _MUST_ preserve the order of Arguments relative to
each other (not counting Properties).
Arguments _MAY_ be prefixed with `/-` to "comment out" the entire token and
make it act as plain whitespace, even if it spreads across multiple lines.
#### Example
```kdl
my-node 1 2 3 "a" "b" "c"
```
### Children Block
A children block is a block of [Nodes](#node), surrounded by `{` and `}`. They
are an optional part of nodes, and create a hierarchy of KDL nodes.
Regular node termination rules apply, which means multiple nodes can be
included in a single-line children block, as long as they're all terminated by
`;`.
#### Example
```kdl
parent {
child1
child2
}
parent { child1; child2; }
```
### Value
A value is either: a [String](#string), a [Number](#number), a
[Boolean](#boolean), or [Null](#null).
Values _MUST_ be either [Arguments](#argument) or values of
[Properties](#property).
Values (both as arguments and as properties) _MAY_ be prefixed by a single
[Type Annotation](#type-annotation).
### Type Annotation
A type annotation is a prefix to any [Node Name](#node) or [Value](#value) that
includes a _suggestion_ of what type the value is _intended_ to be treated as,
or as a _context-specific elaboration_ of the more generic type the node name
indicates.
Type annotations are written as a set of `(` and `)` with an
[Identifier](#identifier) in it. Any valid identifier is considered a valid
type annotation. There must be no whitespace between a type annotation and its
associated Node Name or Value.
KDL does not specify any restrictions on what implementations might do with
these annotations. They are free to ignore them, or use them to make decisions
about how to interpret a value.
Additionally, the following type annotations MAY be recognized by KDL parsers
and, if used, SHOULD interpret these types as follows:
#### Reserved Type Annotations for Numbers Without Decimals:
Signed integers of various sizes (the number is the bit size):
* `i8`
* `i16`
* `i32`
* `i64`
Unsigned integers of various sizes (the number is the bit size):
* `u8`
* `u16`
* `u32`
* `u64`
Platform-dependent integer types, both signed and unsigned:
* `isize`
* `usize`
#### Reserved Type Annotations for Numbers With Decimals:
IEEE 754 floating point numbers, both single (32) and double (64) precision:
* `f32`
* `f64`
IEEE 754-2008 decimal floating point numbers
* `decimal64`
* `decimal128`
#### Reserved Type Annotations for Strings:
* `date-time`: ISO8601 date/time format.
* `time`: "Time" section of ISO8601.
* `date`: "Date" section of ISO8601.
* `duration`: ISO8601 duration format.
* `decimal`: IEEE 754-2008 decimal string format.
* `currency`: ISO 4217 currency code.
* `country-2`: ISO 3166-1 alpha-2 country code.
* `country-3`: ISO 3166-1 alpha-3 country code.
* `country-subdivision`: ISO 3166-2 country subdivision code.
* `email`: RFC5322 email address.
* `idn-email`: RFC6531 internationalized email address.
* `hostname`: RFC1123 internet hostname (only ASCII segments)
* `idn-hostname`: RFC5890 internationalized internet hostname (only `xn--`-prefixed ASCII "punycode" segments, or non-ASCII segments)
* `ipv4`: RFC2673 dotted-quad IPv4 address.
* `ipv6`: RFC2373 IPv6 address.
* `url`: RFC3986 URI.
* `url-reference`: RFC3986 URI Reference.
* `irl`: RFC3987 Internationalized Resource Identifier.
* `irl-reference`: RFC3987 Internationalized Resource Identifier Reference.
* `url-template`: RFC6570 URI Template.
* `uuid`: RFC4122 UUID.
* `regex`: Regular expression. Specific patterns may be implementation-dependent.
* `base64`: A Base64-encoded string, denoting arbitrary binary data.
#### Examples
```kdl
node (u8)123
node prop=(regex)".*"
(published)date "1970-01-01"
(contributor)person name="Foo McBar"
```
### String
Strings in KDL represent textual [Values](#value), or unusual identifiers. A
String is either a [Quoted String](#quoted-string) or a
[Raw String](#raw-string). Quoted Strings may include escaped characters, while
Raw Strings always contain only the literal characters that are present.
### Quoted String
A Quoted String is delimited by `"` on either side of any number of literal
string characters except unescaped `"` and `\`. This includes literal
[Newline](#newline) characters, which means a String Value can encompass
multiple lines without behaving like a Newline for [Node](#node) parsing
purposes.
Strings _MUST_ be represented as UTF-8 values.
In addition to literal code points, a number of "escapes" are supported.
"Escapes" are the character `\` followed by another character, and are
interpreted as described in the following table:
| Name | Escape | Code Pt |
|-------------------------------|--------|----------|
| Line Feed | `\n` | `U+000A` |
| Carriage Return | `\r` | `U+000D` |
| Character Tabulation (Tab) | `\t` | `U+0009` |
| Reverse Solidus (Backslash) | `\\` | `U+005C` |
| Solidus (Forwardslash) | `\/` | `U+002F` |
| Quotation Mark (Double Quote) | `\"` | `U+0022` |
| Backspace | `\b` | `U+0008` |
| Form Feed | `\f` | `U+000C` |
| Unicode Escape | `\u{(1-6 hex chars)}` | Code point described by hex characters, up to `10FFFF` |
### Raw String
Raw Strings in KDL are much like [Quoted Strings](#quoted-string), except they
do not support `\`-escapes. They otherwise share the same properties as far as
literal [Newline](#newline) characters go, and the requirement of UTF-8
representation.
Raw String literals are represented as `r`, followed by zero or more `#`
characters, followed by `"`, followed by any number of UTF-8 literals. The
string is then closed by a `"` followed by a _matching_ number of `#`
characters. This allows them to contain raw `"` or `#` characters; only the
precise terminator (resembling `"##`, for example) ends the raw string. This
means that the string sequence `"` or `"#` and such must not match the closing
`"` with the same or more `#` characters as the opening `r`.
#### Example
```kdl
just-escapes r"\n will be literal"
quotes-and-escapes r#"hello\n\r\asd"world"#
```
### Number
Numbers in KDL represent numerical [Values](#value). There is no logical distinction in KDL
between real numbers, integers, and floating point numbers. It's up to
individual implementations to determine how to represent KDL numbers.
There are four syntaxes for Numbers: Decimal, Hexadecimal, Octal, and Binary.
* All numbers may optionally start with one of `-` or `+`, which determine whether they'll be positive or negative.
* Binary numbers start with `0b` and only allow `0` and `1` as digits, which may be separated by `_`. They represent numbers in radix 2.
* Octal numbers start with `0o` and only allow digits between `0` and `7`, which may be separated by `_`. They represent numbers in radix 8.
* Hexadecimal numbers start with `0x` and allow digits between `0` and `9`, as well as letters `A` through `F`, in either lower or upper case, which may be separated by `_`. They represent numbers in radix 16.
* Decimal numbers are a bit more special:
* They have no radix prefix.
* They use digits `0` through `9`, which may be separated by `_`.
* They may optionally include a decimal separator `.`, followed by more digits, which may again be separated by `_`.
* They may optionally be followed by `E` or `e`, an optional `-` or `+`, and more digits, to represent an exponent value.
### Boolean
A boolean [Value](#value) is either the symbol `true` or `false`. These
_SHOULD_ be represented by implementation as boolean logical values, or some
approximation thereof.
#### Example
```kdl
my-node true value=false
```
### Null
The symbol `null` represents a null [Value](#value). It's up to the
implementation to decide how to represent this, but it generally signals the
"absence" of a value. It is reasonable for an implementation to ignore null
values altogether when deserializing.
#### Example
```kdl
my-node null key=null
```
### Whitespace
The following characters should be treated as non-[Newline](#newline) [white
space](https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt):
| Name | Code Pt |
|----------------------|---------|
| Character Tabulation | `U+0009` |
| Space | `U+0020` |
| No-Break Space | `U+00A0` |
| Ogham Space Mark | `U+1680` |
| En Quad | `U+2000` |
| Em Quad | `U+2001` |
| En Space | `U+2002` |
| Em Space | `U+2003` |
| Three-Per-Em Space | `U+2004` |
| Four-Per-Em Space | `U+2005` |
| Six-Per-Em Space | `U+2006` |
| Figure Space | `U+2007` |
| Punctuation Space | `U+2008` |
| Thin Space | `U+2009` |
| Hair Space | `U+200A` |
| Narrow No-Break Space| `U+202F` |
| Medium Mathematical Space | `U+205F` |
| Ideographic Space | `U+3000` |
#### Multi-line comments
In addition to single-line comments using `//`, comments can also be started
with `/*` and ended with `*/`. These comments can span multiple lines. They
are allowed in all positions where [Whitespace](#whitespace) is allowed and
can be nested.
### Newline
The following characters [should be treated as new
lines](https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-5/#G41643):
| Acronym | Name | Code Pt |
|---------|-----------------|---------|
| CRLF | Carriage Return and Line Feed | `U+000D` + `U+000A` |
| CR | Carriage Return | `U+000D` |
| LF | Line Feed | `U+000A` |
| NEL | Next Line | `U+0085` |
| FF | Form Feed | `U+000C` |
| LS | Line Separator | `U+2028` |
| PS | Paragraph Separator | `U+2029` |
Note that for the purpose of new lines, CRLF is considered _a single newline_. `VT` `Vertical tab` `U+000B` was mistakenly excluded, but the v1 spec if frozen, so it's left unchanged.
## Full Grammar
```
nodes := linespace* (node nodes?)? linespace*
node := ('/-' node-space*)? type? identifier (node-space+ node-prop-or-arg)* (node-space* node-children ws*)? node-space* node-terminator
node-prop-or-arg := ('/-' node-space*)? (prop | value)
node-children := ('/-' node-space*)? '{' nodes '}'
node-space := ws* escline ws* | ws+
node-terminator := single-line-comment | newline | ';' | eof
identifier := string | bare-identifier
bare-identifier := ((identifier-char - digit - sign) identifier-char* | sign ((identifier-char - digit) identifier-char*)?) - keyword
identifier-char := unicode - linespace - [\/(){}<>;[]=,"]
keyword := boolean | 'null'
prop := identifier '=' value
value := type? (string | number | keyword)
type := '(' identifier ')'
string := raw-string | escaped-string
escaped-string := '"' character* '"'
character := '\' escape | [^\"]
escape := ["\\/bfnrt] | 'u{' hex-digit{1, 6} '}'
hex-digit := [0-9a-fA-F]
raw-string := 'r' raw-string-hash
raw-string-hash := '#' raw-string-hash '#' | raw-string-quotes
raw-string-quotes := '"' .* '"'
number := hex | octal | binary | decimal
decimal := sign? integer ('.' integer)? exponent?
exponent := ('e' | 'E') sign? integer
integer := digit (digit | '_')*
digit := [0-9]
sign := '+' | '-'
hex := sign? '0x' hex-digit (hex-digit | '_')*
octal := sign? '0o' [0-7] [0-7_]*
binary := sign? '0b' ('0' | '1') ('0' | '1' | '_')*
boolean := 'true' | 'false'
escline := '\\' ws* (single-line-comment | newline)
linespace := newline | ws | single-line-comment
newline := See Table (All line-break white_space)
ws := bom | unicode-space | multi-line-comment
bom := '\u{FEFF}'
unicode-space := See Table (All White_Space unicode characters which are not `newline`)
single-line-comment := '//' ^newline+ (newline | eof)
multi-line-comment := '/*' commented-block
commented-block := '*/' | (multi-line-comment | '*' | '/' | [^*/]+) commented-block
```

81
XML-IN-KDL.md Normal file
View File

@ -0,0 +1,81 @@
XML-in-KDL (XiK)
================
This specification describes a canonical way to losslessly encode XML in [KDL](https://kdl.dev). While this isn't a very useful thing to want to do on its own, it's occasionally useful when using a KDL toolchain while speaking with an XML-consuming or -emitting service.
This is version 1.0.0 of XiK.
XML-in-KDL (XiK from now on) is a KDL microsyntax for losslessly encoding XML into a KDL document. XML and KDL, luckily, have *very similar* data models (KDL is *almost* a superset of XML), so it's quite straightforward to encode most XML documents into KDL.
See [the website example](examples/website.kdl) for an example of this grammar in use to encode an HTML document. See [XML2KDL](https://github.com/Devasta/XML2KDL) (third party) to encode your XML in KDL (especially [their online editor](https://xsltfiddle.liberty-development.net/bET2rY5)).
XML has several types of nodes, corresponding to certain KDL constructs:
* Elements, which have an element name, zero or more attribute, and zero or more children. These are encoded directly as KDL nodes, using the nodename, properties, and children nodes.
* Raw text. In "pure" XML dialects, where raw text only appears as the sole child of an element (never mixed with other elements as siblings), this is generally encoded as a final string argument in a KDL node; in "mixed" XML dialects, it can be encoded as a special KDL node with the name `-`.
* Comments are encoded as KDL block comments. (Or as an actual node type, for some use-cases.)
* Processing Instructions. These are encoded similarly to elements if their contents are sufficiently structured, with a `?` in front of their node name. If they're not sufficiently structured, their contents are just strings.
* Doctypes. These are encoded like unstructured PIs, just with the node name `!doctype`.
----
XML elements and KDL nodes have a direct correspondence. In XiK, an XML element is encoded in KDL by:
* making the element name the KDL node name
* making the attributes into KDL properties
* making the child nodes as KDL child nodes
For example, the XML `<element foo="bar"><child baz="quux" /></element>` is encoded into XiK as `element foo=bar { child baz=quux }`.
XML namespaces are encoded the same as XML: the node name simply contains a `:` character. Note that KDL identifier syntax allows `:` directly in an ident, so a name like `xml:space` or `xlink:href` is a valid node or property name.
----
Raw text contents of an element can be encoded in two possible ways.
If the element contains *only* text, it should be encoded as a final string unnamed argument. For example, the XML `<a href="http://example.com">here's a link</a>` can be encoded as `a href="http://example.com" "here's a link"`.
If the element contains mixed text and element children, the text can be encoded as a KDL node with the name `-` with a single string unnamed argument. For example, the XML `<span>some <b>bold</b> text</span>` can be encoded as `span { - "some "; b bold; - " text" }`.
An element that contains only text *is allowed to* encode it as `-` children. For example, `<span>foo</span>` *may* be encoded as `span { - foo }` instead of `span foo`. However, an element cannot mix the "final string attribute" with child nodes; `span foo { b bar }` is an **invalid** encoding of `<span>foo<b>bar</b></span>`. (It must be encoded as `span { - foo; b bar }`.)
CDATA sections are not preserved in this encoding, as they are merely a source convenience so you don't have to escape a bunch of characters. They are encoded as normal textual contents would be.
-----
Comments are encoded as KDL multiline comments. For example, `<!-- comment! -->` is encoded as `/* comment! */`.
If you are using a KDL toolchain that discards comments, and you *specifically* want to reflect the comment into XML, comments can be encoded as a special node name `!`, with a single unnamed string argument containing the comment's value (everything between the `<!--` and the `-->`). For example, `<!-- comment! -->` is encoded as the node `! " comment! "`.
----
Processing instructions and XML declarations (nodes that look like `<?foo ... ?>`) are encoded as nodes, with their name being the PI name preceded by a `?`. For example, an XML declaration (written like `<?xml ... ?>`) has the node name `?xml`.
The contents of a PI are technically completely unstructured. However, in practice most PIs' contents look like start-tag attributes. If this is the case, they should be encoded as properties on the node, with string values. For example, `<?xml version="1.0"?>` is encoded as `?xml version="1.0"`.
If the contents of a PI do *not* look like attributes, then instead the entire contents (from the end of the whitespace following the PI name, to the closing `?>` characters) are encoded as a single unnamed string value. For example, the preceding XML declaration *could* be alternately encoded as `?xml #"version="1.0""#` (but shouldn't be).
(Note that XML declarations are not needed when writing XiK directly; the version is always 1.0, and the encoding is always UTF-8 since it's KDL.)
----
Doctypes (nodes that look like `<!DOCTYPE ...>`) are encoded similarly to unstructured Processing Instructions. They have a node name of `!doctype`, and the entire contents of the node, from the end of the whitespace following the "DOCTYPE" to the closing `>`, are encoded as a single unnamed string value. For example, the HTML doctype `<!DOCTYPE html>` is encoded as `!doctype html`, while the XHTML 1 Strict doctype would be encoded as `!doctype #"html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd""#`
----
Converting XiK back to XML is a trivial process:
* Element nodes are emitted as XML start tags, with the appropriate element name and attributes, followed by their contents emitted in order, followed by the appropriate end tag. If there are no contents, they should be emitted as a self-closing tag.
* Raw text is escaped appropriately when emitted. At the converter's discretion, CDATA segments can be used to encode any segment of raw text, as they deem fit. (This can be heuristic, based on the density of escapes required; or specialized to an output language, like always encoding the contents of HTML `script` and `style` elements with CDATA; or via any other criteria.)
* Comments are emitted as their contents (if a KDL comment) or their unnamed string value (if a `!` node) surrounded by `<!--` and `-->`, escaped as appropriate.
* PIs are emitted as a `<` followed by their node name, then a space, then either their attributes escaped as appropriate (if "structured") or the contents of their string value (if "unstructured"), and finally a `?>`.
* Doctypes are emitted as `<!DOCTYPE `, followed by the contents of their string value escaped as appropriate, and finally a `>`.
Only valid XiK nodes can be encoded to XML; if a XiK document contains an invalid node, the entire document must fail to encode, rather than "guessing" at the intent. A XiK node is valid if the XML element it represents is well-formed, and it has the correct KDL structure:
* Element nodes must contain any number of properties with string values, and either a single unnamed string argument as its final value, *or* any number of child nodes.
* Comment nodes must contain a single unnamed string argument and nothing else.
* "Structured" PI nodes must contain any number of properties with string values, and nothing else. "Unstructured" PI nodes must contain a single unnamed string argument and nothing else.
* Doctype nodes must contain a single unnamed string argument and nothing else.
The XiK document must also represent a well-formed XML document in its overall structure - for example, it can only contain a single top-level element node, all namespaces must be declared before they are used, etc.

1110
draft-marchan-kdl2.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
package {
name "kdl"
name kdl
version "0.0.0"
description "kat's document language"
description "The kdl document language"
authors "Kat Marchán <kzm@zkat.tech>"
license-file "LICENSE.md"
license-file LICENSE.md
edition "2018"
}

View File

@ -1,47 +1,52 @@
// This example is a GitHub Action if it used KDL syntax.
// See .github/workflows/ci.yml for the file this was based on.
name "CI"
name CI
on "push" "pull_request"
on push pull_request
env {
RUSTFLAGS "-Dwarnings"
RUSTFLAGS -Dwarnings
}
jobs {
fmt_and_docs "Check fmt & build docs" {
runs-on "ubuntu-latest"
runs-on ubuntu-latest
steps {
step uses="actions/checkout@v1"
step "Install Rust" uses="actions-rs/toolchain@v1" {
profile "minimal"
toolchain "stable"
components "rustfmt"
override true
profile minimal
toolchain stable
components rustfmt
override #true
}
step "rustfmt" run="cargo fmt --all -- --check"
step "docs" run="cargo doc --no-deps"
step rustfmt { run cargo fmt --all -- --check }
step docs { run cargo doc --no-deps }
}
}
build_and_test "Build & Test" {
runs-on "${{ matrix.os }}"
strategy {
matrix {
rust "1.46.0" "stable"
os "ubuntu-latest" "macOS-latest" "windows-latest"
rust "1.46.0" stable
os ubuntu-latest macOS-latest windows-latest
}
}
steps {
step uses="actions/checkout@v1"
step "Install Rust" uses="actions-rs/toolchain@v1" {
profile "minimal"
profile minimal
toolchain "${{ matrix.rust }}"
components "clippy"
override true
components clippy
override #true
}
step "Clippy" run="cargo clippy --all -- -D warnings"
step "Run tests" run="cargo test --all --verbose"
step Clippy { run cargo clippy --all -- -D warnings }
step "Run tests" { run cargo test --all --verbose }
step "Other Stuff" run="""
echo foo
echo bar
echo baz
"""
}
}
}

376
examples/kdl-schema.kdl Normal file
View File

@ -0,0 +1,376 @@
document {
info {
title "KDL Schema" lang=en
description "KDL Schema KDL schema in KDL" lang=en
author "Kat Marchán" {
link "https://github.com/zkat" rel=self
}
contributor "Lars Willighagen" {
link "https://github.com/larsgw" rel=self
}
link "https://github.com/zkat/kdl" rel=documentation
license "Creative Commons Attribution-ShareAlike 4.0 International License" spdx=CC-BY-SA-4.0 {
link "https://creativecommons.org/licenses/by-sa/4.0/" lang=en
}
published "2021-08-31"
modified "2021-09-01"
}
node document {
min 1
max 1
children id=node-children {
node node-names id=node-names-node description="Validations to apply specifically to arbitrary node names" {
children ref=#"[id="validations"]"#
}
node other-nodes-allowed id=other-nodes-allowed-node description="Whether to allow child nodes other than the ones explicitly listed. Defaults to '#false'." {
max 1
value {
min 1
max 1
type boolean
}
}
node tag-names description="Validations to apply specifically to arbitrary type tag names" {
children ref=#"[id="validations"]"#
}
node other-tags-allowed description="Whether to allow child node tags other than the ones explicitly listed. Defaults to '#false'." {
max 1
value {
min 1
max 1
type boolean
}
}
node info description="A child node that describes the schema itself." {
children {
node title description="The title of the schema or the format it describes" {
value description="The title text" {
type string
min 1
max 1
}
prop lang id=info-lang description="The language of the text" {
type string
}
}
node description description="A description of the schema or the format it describes" {
value description="The description text" {
type string
min 1
max 1
}
prop ref=#"[id="info-lang"]"#
}
node author description="Author of the schema" {
value id=info-person-name description="Person name" {
type string
min 1
max 1
}
prop orcid id=info-orcid description="The ORCID of the person" {
type string
pattern #"\d{4}-\d{4}-\d{4}-\d{4}"#
}
children {
node ref=#"[id="info-link"]"#
}
}
node contributor description="Contributor to the schema" {
value ref=#"[id="info-person-name"]"#
prop ref=#"[id="info-orcid"]"#
children {
node ref=#"[id="info-link"]"#
}
}
node link id=info-link description="Links to itself, and to sources describing it" {
value description="A URL that the link points to" {
type string
format url irl
min 1
max 1
}
prop rel description="The relation between the current entity and the URL" {
type string
enum self documentation
}
prop ref=#"[id="info-lang"]"#
}
node license description="The license(s) that the schema is licensed under" {
value description="Name of the used license" {
type string
min 1
max 1
}
prop spdx description="An SPDX license identifier" {
type string
}
children {
node ref=#"[id="info-link"]"#
}
}
node published description="When the schema was published" {
value description="Publication date" {
type string
format date
min 1
max 1
}
prop time id=info-time description="A time to accompany the date" {
type string
format time
}
}
node modified description="When the schema was last modified" {
value description="Modification date" {
type string
format date
min 1
max 1
}
prop ref=#"[id="info-time"]"#
}
node version description="The version number of this version of the schema" {
value description="Semver version number" {
type string
pattern #"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$"#
min 1
max 1
}
}
}
}
node tag id=tag-node description="A tag belonging to a child node of `document` or another node." {
value description="The name of the tag. If a tag name is not supplied, the node rules apply to _all_ nodes belonging to the parent." {
type string
max 1
}
prop description description="A description of this node's purpose." {
type string
}
prop id description="A globally-unique ID for this node." {
type string
}
prop ref description="A globally unique reference to another node." {
type string
format kdl-query
}
children {
node ref=#"[id="node-names-node"]"#
node ref=#"[id="other-nodes-allowed-node"]"#
node ref=#"[id="node-node"]"#
}
}
node node id=node-node description="A child node belonging either to `document` or to another `node`. Nodes may be anonymous." {
value description="The name of the node. If a node name is not supplied, the node rules apply to _all_ nodes belonging to the parent." {
type string
max 1
}
prop description description="A description of this node's purpose." {
type string
}
prop id description="A globally-unique ID for this node." {
type string
}
prop ref description="A globally unique reference to another node." {
type string
format kdl-query
}
children {
node prop-names description="Validations to apply specifically to arbitrary property names" {
children ref=#"[id="validations"]"#
}
node other-props-allowed description="Whether to allow properties other than the ones explicitly listed. Defaults to '#false'." {
max 1
value {
min 1
max 1
type boolean
}
}
node min description="minimum number of instances of this node in its parent's children." {
max 1
value {
min 1
max 1
type number
}
}
node max description="maximum number of instances of this node in its parent's children." {
max 1
value {
min 1
max 1
type number
}
}
node ref=#"[id="value-tag-node"]"#
node prop id="prop-node" description="A node property key/value pair." {
value description="The property key." {
type string
}
prop id description="A globally-unique ID of this property." {
type string
}
prop ref description="A globally unique reference to another property node." {
type string
format kdl-query
}
prop description description="A description of this property's purpose." {
type string
}
children description="Property-specific validations." {
node required description="Whether this property is required if its parent is present." {
max 1
value {
min 1
max 1
type boolean
}
}
}
children id=validations description="General value validations." {
node tag id=value-tag-node description="The tags associated with this value" {
max 1
children ref=#"[id="validations"]"#
}
node type description="The type for this prop's value." {
max 1
value {
min 1
type string
}
}
node enum description="An enumeration of possible values" {
max 1
value description="Enumeration choices" {
min 1
}
}
node pattern description="PCRE (Regex) pattern or patterns to test prop values against." {
value {
min 1
type string
}
}
node min-length description="Minimum length of prop value, if it's a string." {
max 1
value {
min 1
type number
}
}
node max-length description="Maximum length of prop value, if it's a string." {
max 1
value {
min 1
type number
}
}
node format description="Intended data format." {
max 1
value {
min 1
type string
// https://json-schema.org/understanding-json-schema/reference/string.html#format
enum date-time date time duration decimal currency country-2 country-3 country-subdivision email idn-email hostname idn-hostname ipv4 ipv6 url url-reference irl irl-reference url-template regex uuid kdl-query i8 i16 i32 i64 u8 u16 u32 u64 isize usize f32 f64 decimal64 decimal128
}
}
node % description="Only used for numeric values. Constrains them to be multiples of the given number(s)" {
max 1
value {
min 1
type number
}
}
node > description="Only used for numeric values. Constrains them to be greater than the given number(s)" {
max 1
value {
min 1
max 1
type number
}
}
node ">=" description="Only used for numeric values. Constrains them to be greater than or equal to the given number(s)" {
max 1
value {
min 1
max 1
type number
}
}
node < description="Only used for numeric values. Constrains them to be less than the given number(s)" {
max 1
value {
min 1
max 1
type number
}
}
node "<=" description="Only used for numeric values. Constrains them to be less than or equal to the given number(s)" {
max 1
value {
min 1
max 1
type number
}
}
}
}
node value id=value-node description="one or more direct node values" {
prop id description="A globally-unique ID of this value." {
type string
}
prop ref description="A globally unique reference to another value node." {
type string
format kdl-query
}
prop description description="A description of this property's purpose." {
type string
}
children ref=#"[id="validations"]"#
children description="Node value-specific validations" {
node min description="minimum number of values for this node." {
max 1
value {
min 1
max 1
type number
}
}
node max description="maximum number of values for this node." {
max 1
value {
min 1
max 1
type number
}
}
}
}
node children id=children-node {
prop id description="A globally-unique ID of this children node." {
type string
}
prop ref description="A globally unique reference to another children node." {
type string
format kdl-query
}
prop description description="A description of this these children's purpose." {
type string
}
children ref=#"[id="node-children"]"#
}
}
}
node definitions description="Definitions to reference in parts of the top-level nodes" {
children {
node ref=#"[id="node-node"]"#
node ref=#"[id="value-node"]"#
node ref=#"[id="prop-node"]"#
node ref=#"[id="children-node"]"#
node ref=#"[id="tag-node"]"#
}
}
}
}
}

View File

@ -1,48 +1,48 @@
// Based on https://github.com/NuGet/NuGet.Client/blob/dev/src/NuGet.Clients/NuGet.CommandLine/NuGet.CommandLine.csproj
Project {
PropertyGroup {
IsCommandLinePackage true
IsCommandLinePackage #true
}
Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'README.md'))\build\common.props"
Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk"
Import Project="ilmerge.props"
Import Project=#"$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'README.md'))\build\common.props"#
Import Project=Sdk.props Sdk=Microsoft.NET.Sdk
Import Project=ilmerge.props
PropertyGroup {
RootNamespace "NuGet.CommandLine"
AssemblyName "NuGet"
RootNamespace NuGet.CommandLine
AssemblyName NuGet
AssemblyTitle "NuGet Command Line"
PackageId "NuGet.CommandLine"
PackageId NuGet.CommandLine
TargetFramework "$(NETFXTargetFramework)"
GenerateDocumentationFile false
GenerateDocumentationFile #false
Description "NuGet Command Line Interface."
ApplicationManifest "app.manifest"
Shipping true
OutputType "Exe"
ComVisible false
ApplicationManifest app.manifest
Shipping #true
OutputType Exe
ComVisible #false
// Pack properties
PackProject true
IncludeBuildOutput false
PackProject #true
IncludeBuildOutput #false
TargetsForTfmSpecificContentInPackage "$(TargetsForTfmSpecificContentInPackage)" "CreateCommandlineNupkg"
SuppressDependenciesWhenPacking true
DevelopmentDependency true
PackageRequireLicenseAcceptance false
UsePublicApiAnalyzer false
SuppressDependenciesWhenPacking #true
DevelopmentDependency #true
PackageRequireLicenseAcceptance #false
UsePublicApiAnalyzer #false
}
Target Name="CreateCommandlineNupkg" {
Target Name=CreateCommandlineNupkg {
ItemGroup {
TfmSpecificPackageFile Include="$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe" {
TfmSpecificPackageFile Include=#"$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe"# {
PackagePath "tools/"
}
TfmSpecificPackageFile Include="$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.pdb" {
TfmSpecificPackageFile Include=#"$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.pdb"# {
PackagePath "tools/"
}
}
}
ItemGroup Condition="$(DefineConstants.Contains(SIGNED_BUILD))" {
AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" {
AssemblyAttribute Include=System.Runtime.CompilerServices.InternalsVisibleTo {
_Parameter1 "NuGet.CommandLine.FuncTest, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293"
}
AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" {
@ -51,81 +51,81 @@ Project {
}
ItemGroup Condition="!$(DefineConstants.Contains(SIGNED_BUILD))" {
AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" {
_Parameter1 "NuGet.CommandLine.FuncTest"
AssemblyAttribute Include=System.Runtime.CompilerServices.InternalsVisibleTo {
_Parameter1 NuGet.CommandLine.FuncTest
}
AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" {
_Parameter1 "NuGet.CommandLine.Test"
AssemblyAttribute Include=System.Runtime.CompilerServices.InternalsVisibleTo {
_Parameter1 NuGet.CommandLine.Test
}
}
ItemGroup Condition="$(DefineConstants.Contains(SIGNED_BUILD))" {
AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" {
AssemblyAttribute Include=System.Runtime.CompilerServices.InternalsVisibleTo {
_Parameter1 "NuGet.CommandLine.Test, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293"
}
}
ItemGroup Condition="!$(DefineConstants.Contains(SIGNED_BUILD))" {
AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo" {
_Parameter1 "NuGet.CommandLine.Test"
AssemblyAttribute Include=System.Runtime.CompilerServices.InternalsVisibleTo {
_Parameter1 NuGet.CommandLine.Test
}
}
ItemGroup {
Reference Include="Microsoft.Build.Utilities.v4.0"
Reference Include="Microsoft.CSharp"
Reference Include="System"
Reference Include="System.ComponentModel.Composition"
Reference Include="System.ComponentModel.Composition.Registration"
Reference Include="System.ComponentModel.DataAnnotations"
Reference Include="System.IO.Compression"
Reference Include="System.Net.Http"
Reference Include="System.Xml"
Reference Include="System.Xml.Linq"
Reference Include="NuGet.Core" {
HintPath "$(SolutionPackagesFolder)nuget.core\2.14.0-rtm-832\lib\net40-Client\NuGet.Core.dll"
Aliases "CoreV2"
Reference Include=Microsoft.Build.Utilities.v4.0
Reference Include=Microsoft.CSharp
Reference Include=System
Reference Include=System.ComponentModel.Composition
Reference Include=System.ComponentModel.Composition.Registration
Reference Include=System.ComponentModel.DataAnnotations
Reference Include=System.IO.Compression
Reference Include=System.Net.Http
Reference Include=System.Xml
Reference Include=System.Xml.Linq
Reference Include=NuGet.Core {
HintPath #"$(SolutionPackagesFolder)nuget.core\2.14.0-rtm-832\lib\net40-Client\NuGet.Core.dll"#
Aliases CoreV2
}
}
ItemGroup {
PackageReference Include="Microsoft.VisualStudio.Setup.Configuration.Interop"
ProjectReference Include="$(NuGetCoreSrcDirectory)NuGet.PackageManagement\NuGet.PackageManagement.csproj"
ProjectReference Include="$(NuGetCoreSrcDirectory)NuGet.Build.Tasks\NuGet.Build.Tasks.csproj"
PackageReference Include=Microsoft.VisualStudio.Setup.Configuration.Interop
ProjectReference Include=#"$(NuGetCoreSrcDirectory)NuGet.PackageManagement\NuGet.PackageManagement.csproj"#
ProjectReference Include=#"$(NuGetCoreSrcDirectory)NuGet.Build.Tasks\NuGet.Build.Tasks.csproj"#
}
ItemGroup {
EmbeddedResource Update="NuGetCommand.resx" {
Generator "ResXFileCodeGenerator"
LastGenOutput "NuGetCommand.Designer.cs"
EmbeddedResource Update=NuGetCommand.resx {
Generator ResXFileCodeGenerator
LastGenOutput NuGetCommand.Designer.cs
}
Compile Update="NuGetCommand.Designer.cs" {
DesignTime true
AutoGen true
DependentUpon "NuGetCommand.resx"
Compile Update=NuGetCommand.Designer.cs {
DesignTime #true
AutoGen #true
DependentUpon NuGetCommand.resx
}
EmbeddedResource Update="NuGetResources.resx" {
EmbeddedResource Update=NuGetResources.resx {
// Strings are shared by other projects, use public strings.
Generator "PublicResXFileCodeGenerator"
LastGenOutput "NuGetResources.Designer.cs"
Generator PublicResXFileCodeGenerator
LastGenOutput NuGetResources.Designer.cs
}
Compile Update="NuGetResources.Designer.cs" {
DesignTime true
AutoGen true
DependentUpon "NuGetResources.resx"
Compile Update=NuGetResources.Designer.cs {
DesignTime #true
AutoGen #true
DependentUpon NuGetResources.resx
}
}
ItemGroup {
EmbeddedResource Include="$(NuGetCoreSrcDirectory)NuGet.Build.Tasks\NuGet.targets" {
Link "NuGet.targets"
SubType "Designer"
EmbeddedResource Include=#"$(NuGetCoreSrcDirectory)NuGet.Build.Tasks\NuGet.targets"# {
Link NuGet.targets
SubType Designer
}
}
// Since we are moving some code and strings from NuGet.CommandLine to NuGet.Commands, we opted to go through normal localization process (build .resources.dll) and then add them to the ILMerged nuget.exe
// This will also be called from CI build, after assemblies are localized, since our test infra takes nuget.exe before Localization
Target Name="ILMergeNuGetExe" \
AfterTargets="Build" \
Target Name=ILMergeNuGetExe \
AfterTargets=Build \
Condition="'$(BuildingInsideVisualStudio)' != 'true' and '$(SkipILMergeOfNuGetExe)' != 'true'" \
{
PropertyGroup {
@ -133,9 +133,9 @@ Project {
ExpectedLocalizedArtifactCount 0 Condition="'$(ExpectedLocalizedArtifactCount)' == ''"
}
ItemGroup {
BuildArtifacts Include="$(OutputPath)\*.dll" Exclude="@(MergeExclude)"
BuildArtifacts Include=#"$(OutputPath)\*.dll"# Exclude="@(MergeExclude)"
// NuGet.exe needs all NuGet.Commands.resources.dll merged in
LocalizedArtifacts Include="$(ArtifactsDirectory)\NuGet.Commands\**\$(NETFXTargetFramework)\**\*.resources.dll"
LocalizedArtifacts Include=#"$(ArtifactsDirectory)\NuGet.Commands\**\$(NETFXTargetFramework)\**\*.resources.dll"#
}
Error Text="Build dependencies are inconsistent with mergeinclude specified in ilmerge.props" \
Condition="'@(BuildArtifacts-&gt;Count())' != '@(MergeInclude-&gt;Count())'"
@ -143,36 +143,36 @@ Project {
Condition="'@(LocalizedArtifacts-&gt;Count())' != '$(ExpectedLocalizedArtifactCount)'"
PropertyGroup {
PathToBuiltNuGetExe "$(OutputPath)NuGet.exe"
IlmergeCommand "$(ILMergeExePath) /lib:$(OutputPath) /out:$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe @(MergeAllowDup -> '/allowdup:%(Identity)', ' ') /log:$(OutputPath)IlMergeLog.txt"
IlmergeCommand #"$(ILMergeExePath) /lib:$(OutputPath) /out:$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe @(MergeAllowDup -> '/allowdup:%(Identity)', ' ') /log:$(OutputPath)IlMergeLog.txt"#
IlmergeCommand Condition="Exists($(MS_PFX_PATH))" "$(IlmergeCommand) /delaysign /keyfile:$(MS_PFX_PATH)"
// LocalizedArtifacts need fullpath, since there will be duplicate file names
IlmergeCommand "$(IlmergeCommand) $(PathToBuiltNuGetExe) @(BuildArtifacts->'%(filename)%(extension)', ' ') @(LocalizedArtifacts->'%(fullpath)', ' ')"
}
MakeDir Directories="$(ArtifactsDirectory)$(VsixOutputDirName)"
Exec Command="$(IlmergeCommand)" ContinueOnError="false"
Exec Command="$(IlmergeCommand)" ContinueOnError=#false
}
Import Project="$(BuildCommonDirectory)common.targets"
Import Project="$(BuildCommonDirectory)embedinterop.targets"
// Do nothing. This basically strips away the framework assemblies from the resulting nuspec.
Target Name="_GetFrameworkAssemblyReferences" DependsOnTargets="ResolveReferences"
Target Name=_GetFrameworkAssemblyReferences DependsOnTargets=ResolveReferences
Target Name="GetSigningInputs" Returns="@(DllsToSign)" {
Target Name=GetSigningInputs Returns="@(DllsToSign)" {
ItemGroup {
DllsToSign Include="$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe" {
StrongName "MsSharedLib72"
Authenticode "Microsoft400"
DllsToSign Include=#"$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe"# {
StrongName MsSharedLib72
Authenticode Microsoft400
}
}
}
Target Name="GetSymbolsToIndex" Returns="@(SymbolsToIndex)" {
Target Name=GetSymbolsToIndex Returns="@(SymbolsToIndex)" {
ItemGroup {
SymbolsToIndex Include="$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe"
SymbolsToIndex Include="$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.pdb"
SymbolsToIndex Include=#"$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.exe"#
SymbolsToIndex Include=#"$(ArtifactsDirectory)$(VsixOutputDirName)\NuGet.pdb"#
}
}
Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk"
Import Project=Sdk.targets Sdk=Microsoft.NET.Sdk
}

47
examples/website.kdl Normal file
View File

@ -0,0 +1,47 @@
!doctype html
html lang=en {
head {
meta charset=utf-8
meta name=viewport content="width=device-width, initial-scale=1.0"
meta \
name=description \
content="kdl is a document language, mostly based on SDLang, with xml-like semantics that looks like you're invoking a bunch of CLI commands!"
title "kdl - The KDL Document Language"
link rel=stylesheet href="/styles/global.css"
}
body {
main {
header class="py-10 bg-gray-300" {
h1 class="text-4xl text-center" "kdl - The KDL Document Language"
}
section class=kdl-section id=description {
p {
- "kdl is a document language, mostly based on "
a href="https://sdlang.org" "SDLang"
- " with xml-like semantics that looks like you're invoking a bunch of CLI commands"
}
p "It's meant to be used both as a serialization format and a configuration language, and is relatively light on syntax compared to XML."
}
section class=kdl-section id=design-and-discussion {
h2 "Design and Discussion"
p {
- "kdl is still extremely new, and discussion about the format should happen over on the "
a href="https://github.com/kdoclang/kdl/discussions" {
- "discussions"
}
- " page in the Github repo. Feel free to jump in and give us your 2 cents!"
}
}
section class=kdl-section id=design-principles {
h2 "Design Principles"
ol {
li Maintainability
li Flexibility
li "Cognitive simplicity and Learnability"
li "Ease of de/serialization"
li "Ease of implementation"
}
}
}
}
}

11
graphics/KDL_Logo.svg Normal file
View File

@ -0,0 +1,11 @@
<svg width="1280" height="640" viewBox="0 0 1280 640" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M950.308 526.179C934.186 527.184 921.529 523.63 912.339 515.518C903.149 507.405 898.039 495.091 897.01 478.575L877.388 163.592C876.384 147.469 880.306 134.395 889.156 124.369C898.374 113.926 911.242 108.19 927.758 107.161C944.667 106.107 958.343 110.19 968.787 119.408C979.205 128.234 984.917 140.708 985.922 156.83L1003.23 434.653L1138.9 426.201C1173.11 424.07 1191.13 437.751 1192.97 467.244C1193.9 482.187 1190.26 493.467 1182.05 501.084C1174.23 508.677 1161.67 513.012 1144.37 514.09L950.308 526.179Z" fill="#B094FF"/>
<path d="M889.156 124.369L866.665 104.516L866.665 104.516L889.156 124.369ZM968.787 119.408L948.933 141.9L949.163 142.102L949.396 142.3L968.787 119.408ZM1003.23 434.653L973.287 436.518L975.152 466.46L1005.09 464.595L1003.23 434.653ZM1182.05 501.084L1161.65 479.091L1161.39 479.325L1161.15 479.564L1182.05 501.084ZM948.443 496.237C937.643 496.91 933.703 494.36 932.192 493.026L892.486 538.009C909.355 552.9 930.728 557.457 952.174 556.121L948.443 496.237ZM932.192 493.026C930.817 491.812 927.665 488.143 926.952 476.71L867.068 480.44C868.414 502.039 875.481 522.998 892.486 538.009L932.192 493.026ZM926.952 476.71L907.33 161.726L847.446 165.457L867.068 480.44L926.952 476.71ZM907.33 161.726C906.71 151.781 909.127 147.077 911.647 144.222L866.665 104.516C851.485 121.712 846.057 143.157 847.446 165.457L907.33 161.726ZM911.647 144.222C914.625 140.849 919.446 137.737 929.623 137.103L925.892 77.2188C903.038 78.6426 882.124 87.0029 866.665 104.516L911.647 144.222ZM929.623 137.103C940.421 136.43 945.702 139.047 948.933 141.9L988.64 96.9173C970.985 81.3328 948.913 75.7847 925.892 77.2188L929.623 137.103ZM949.396 142.3C952.447 144.884 955.382 149.111 955.98 158.696L1015.86 154.965C1014.45 132.305 1005.96 111.584 988.177 96.5169L949.396 142.3ZM955.98 158.696L973.287 436.518L1033.17 432.788L1015.86 154.965L955.98 158.696ZM1005.09 464.595L1140.76 456.143L1137.03 396.259L1001.36 404.711L1005.09 464.595ZM1140.76 456.143C1154.25 455.303 1158.97 458.023 1159.94 458.76C1160.01 458.816 1162.47 460.233 1163.03 469.109L1222.91 465.378C1221.63 444.762 1214.16 424.591 1196.21 410.967C1179.16 398.023 1157.75 394.968 1137.03 396.259L1140.76 456.143ZM1163.03 469.109C1163.32 473.78 1162.8 476.435 1162.39 477.699C1162.05 478.747 1161.77 478.98 1161.65 479.091L1202.45 523.077C1219.31 507.436 1224.2 486.075 1222.91 465.378L1163.03 469.109ZM1161.15 479.564C1160.75 479.954 1156.65 483.267 1142.51 484.148L1146.24 544.032C1166.7 542.757 1187.72 537.4 1202.95 522.604L1161.15 479.564ZM1142.51 484.148L948.443 496.237L952.174 556.121L1146.24 544.032L1142.51 484.148Z" fill="#B094FF"/>
<path d="M950.371 525.177C934.248 526.182 921.591 522.628 912.401 514.516C903.211 506.403 898.101 494.089 897.073 477.573L877.45 162.59C876.446 146.467 880.368 133.393 889.218 123.367C898.437 112.924 911.304 107.188 927.82 106.159C944.729 105.105 958.405 109.188 968.849 118.406C979.268 127.232 984.979 139.706 985.984 155.829L1003.29 433.651L1138.96 425.199C1173.17 423.068 1191.19 436.749 1193.03 466.242C1193.96 481.185 1190.32 492.465 1182.11 500.082C1174.3 507.675 1161.74 512.01 1144.43 513.088L950.371 525.177Z" fill="#EDD7FF"/>
<path d="M495.312 505.602C479.399 502.826 467.917 496.424 460.868 486.395C453.818 476.367 451.681 463.396 454.457 447.482L508.789 136C511.565 120.086 517.967 108.605 527.996 101.555C538.025 94.5054 550.996 92.3686 566.909 95.1444L684.516 115.659C729.928 123.58 767.48 138.729 797.173 161.106C827.321 183.163 848.454 211.046 860.572 244.756C872.689 278.466 875.058 316.474 867.679 358.781C860.231 401.477 845.066 436.827 822.184 464.831C799.757 492.515 770.626 511.631 734.79 522.178C699.343 532.792 658.719 534.105 612.919 526.116L495.312 505.602ZM620.38 438.629C660.359 445.602 691.938 441.112 715.118 425.158C738.754 408.884 754.093 380.563 761.134 340.197C768.176 299.83 763.297 268.183 746.499 245.256C730.089 222.396 701.895 207.479 661.917 200.505L609.518 191.365L567.981 429.489L620.38 438.629Z" fill="#94E5FF"/>
<path d="M797.173 161.106L779.117 185.065L779.287 185.193L779.459 185.319L797.173 161.106ZM822.184 464.831L798.953 445.849L798.913 445.898L798.873 445.947L822.184 464.831ZM734.79 522.178L726.32 493.398L726.252 493.418L726.184 493.439L734.79 522.178ZM715.118 425.158L732.127 449.871L732.132 449.867L715.118 425.158ZM746.499 245.256L722.128 262.75L722.213 262.868L722.299 262.986L746.499 245.256ZM609.518 191.365L614.673 161.812L585.119 156.657L579.964 186.21L609.518 191.365ZM567.981 429.489L538.428 424.334L533.273 453.888L562.826 459.043L567.981 429.489ZM500.468 476.048C489.808 474.189 486.569 470.791 485.41 469.143L436.325 503.648C449.265 522.056 468.99 531.463 490.157 535.156L500.468 476.048ZM485.41 469.143C484.252 467.494 482.151 463.297 484.011 452.637L424.903 442.327C421.211 463.494 423.384 485.239 436.325 503.648L485.41 469.143ZM484.011 452.637L538.343 141.155L479.236 130.845L424.903 442.327L484.011 452.637ZM538.343 141.155C540.203 130.495 543.6 127.257 545.248 126.098L510.744 77.0121C492.335 89.9524 482.928 109.677 479.236 130.845L538.343 141.155ZM545.248 126.098C546.897 124.939 551.095 122.839 561.754 124.698L572.065 65.5907C550.897 61.8983 529.152 64.0719 510.744 77.0121L545.248 126.098ZM561.754 124.698L679.361 145.213L689.671 86.105L572.065 65.5907L561.754 124.698ZM679.361 145.213C721.192 152.509 754.023 166.153 779.117 185.065L815.228 137.148C780.937 111.305 738.664 94.651 689.671 86.105L679.361 145.213ZM779.459 185.319C804.996 204.002 822.337 227.077 832.34 254.904L888.803 234.608C874.571 195.016 849.646 162.325 814.887 136.894L779.459 185.319ZM832.34 254.904C842.377 282.824 844.788 315.428 838.125 353.626L897.232 363.937C905.329 317.52 903.002 274.108 888.803 234.608L832.34 254.904ZM838.125 353.626C831.387 392.252 817.985 422.557 798.953 445.849L845.414 483.813C872.147 451.097 889.075 410.701 897.232 363.937L838.125 353.626ZM798.873 445.947C780.467 468.667 756.619 484.481 726.32 493.398L743.261 550.957C784.632 538.781 819.046 516.363 845.494 483.715L798.873 445.947ZM726.184 493.439C696.195 502.419 660.434 503.951 618.074 496.562L607.764 555.67C657.004 564.259 702.491 563.166 743.396 550.917L726.184 493.439ZM618.074 496.562L500.468 476.048L490.157 535.156L607.764 555.67L618.074 496.562ZM615.225 468.183C659.518 475.909 700.09 471.921 732.127 449.871L698.11 400.446C683.786 410.304 661.2 415.296 625.535 409.075L615.225 468.183ZM732.132 449.867C764.809 427.367 782.861 390.224 790.688 345.352L731.581 335.042C725.325 370.902 712.7 390.4 698.105 400.449L732.132 449.867ZM790.688 345.352C798.506 300.532 794.115 259.485 770.699 227.525L722.299 262.986C732.48 276.881 737.845 299.129 731.581 335.042L790.688 345.352ZM770.87 227.761C748.19 196.167 711.364 178.678 667.072 170.952L656.762 230.059C692.426 236.28 711.988 248.625 722.128 262.75L770.87 227.761ZM667.072 170.952L614.673 161.812L604.363 220.919L656.762 230.059L667.072 170.952ZM579.964 186.21L538.428 424.334L597.535 434.644L639.072 196.521L579.964 186.21ZM562.826 459.043L615.225 468.183L625.535 409.075L573.137 399.935L562.826 459.043Z" fill="#94E5FF"/>
<path d="M494.312 505.602C478.399 502.826 466.917 496.424 459.868 486.395C452.818 476.367 450.681 463.396 453.457 447.482L507.789 136C510.565 120.086 516.967 108.605 526.996 101.555C537.025 94.5054 549.996 92.3686 565.909 95.1444L683.516 115.659C728.928 123.58 766.48 138.729 796.173 161.106C826.321 183.163 847.454 211.046 859.572 244.756C871.689 278.466 874.058 316.474 866.679 358.781C859.231 401.477 844.066 436.827 821.184 464.831C798.757 492.515 769.626 511.631 733.79 522.178C698.343 532.792 657.719 534.105 611.919 526.116L494.312 505.602ZM619.38 438.629C659.359 445.602 690.938 441.112 714.118 425.158C737.754 408.884 753.093 380.563 760.134 340.197C767.176 299.83 762.297 268.183 745.499 245.256C729.089 222.396 700.895 207.479 660.917 200.505L608.518 191.365L566.981 429.489L619.38 438.629Z" fill="#D7F8FF"/>
<path d="M477.854 417.186C488.866 426.169 494.901 437.14 495.96 450.099C497.019 463.058 493.041 474.847 484.026 485.466C475.011 496.086 463.827 501.941 450.476 503.032C435.946 504.219 422.081 499.027 408.881 487.455L226.952 329.173L238.31 468.186C239.658 484.679 235.824 498.235 226.809 508.854C217.762 519.081 204.795 524.884 187.91 526.264C171.416 527.612 157.876 523.974 147.289 515.352C137.062 506.304 131.275 493.534 129.927 477.041L104.179 161.906C102.863 145.806 106.533 132.659 115.188 122.464C124.203 111.844 136.957 105.861 153.45 104.513C170.336 103.134 184.088 106.951 194.708 115.967C205.295 124.589 211.246 136.95 212.562 153.051L223.15 282.639L375.049 102.417C384.393 90.9806 395.544 84.7327 408.503 83.6739C421.462 82.6151 433.251 86.5933 443.87 95.6084C454.458 104.231 460.281 115.022 461.339 127.98C462.398 140.939 457.683 153.381 447.193 165.307L336.114 293.57L477.854 417.186Z" fill="#FFB2B2"/>
<path d="M477.854 417.186L458.135 439.795L458.508 440.12L458.891 440.433L477.854 417.186ZM484.026 485.466L461.155 466.051L461.155 466.051L484.026 485.466ZM408.881 487.455L428.657 464.896L428.615 464.859L428.572 464.822L408.881 487.455ZM226.952 329.173L246.643 306.54L191.051 258.173L197.052 331.616L226.952 329.173ZM226.809 508.854L249.278 528.732L249.481 528.503L249.679 528.27L226.809 508.854ZM147.289 515.352L127.411 537.821L127.87 538.227L128.344 538.613L147.289 515.352ZM115.188 122.464L92.3173 103.049L92.3173 103.049L115.188 122.464ZM194.708 115.967L175.292 138.837L175.526 139.035L175.763 139.228L194.708 115.967ZM223.15 282.639L193.25 285.082L199.177 357.631L246.089 301.973L223.15 282.639ZM375.049 102.417L397.988 121.752L398.136 121.576L398.282 121.398L375.049 102.417ZM443.87 95.6084L424.455 118.479L424.688 118.677L424.926 118.87L443.87 95.6084ZM447.193 165.307L424.667 145.494L424.591 145.58L424.515 145.668L447.193 165.307ZM336.114 293.57L313.436 273.93L293.865 296.529L316.396 316.179L336.114 293.57ZM458.891 440.433C464.231 444.789 465.731 448.518 466.06 452.542L525.861 447.656C524.072 425.762 513.501 407.55 496.817 393.94L458.891 440.433ZM466.06 452.542C466.421 456.965 465.428 461.018 461.155 466.051L506.896 504.881C520.654 488.676 527.617 469.15 525.861 447.656L466.06 452.542ZM461.155 466.051C457.061 470.875 453.108 472.717 448.033 473.131L452.919 532.932C474.546 531.165 492.961 521.297 506.896 504.881L461.155 466.051ZM448.033 473.131C443.216 473.525 437.089 472.288 428.657 464.896L389.105 510.014C407.073 525.765 428.676 534.913 452.919 532.932L448.033 473.131ZM428.572 464.822L246.643 306.54L207.261 351.806L389.19 510.088L428.572 464.822ZM197.052 331.616L208.41 470.629L268.211 465.743L256.852 326.73L197.052 331.616ZM208.41 470.629C209.24 480.792 206.851 486.008 203.939 489.439L249.679 528.27C264.797 510.461 270.075 488.565 268.211 465.743L208.41 470.629ZM204.34 488.976C201.592 492.083 196.589 495.455 185.466 496.364L190.353 556.164C213.001 554.314 233.932 546.079 249.278 528.732L204.34 488.976ZM185.466 496.364C174.958 497.222 169.59 494.823 166.234 492.09L128.344 538.613C146.163 553.125 167.875 558.001 190.353 556.164L185.466 496.364ZM167.167 492.882C163.925 490.014 160.686 485.107 159.828 474.598L100.027 479.484C101.864 501.962 110.2 522.595 127.411 537.821L167.167 492.882ZM159.828 474.598L134.079 159.463L74.2786 164.349L100.027 479.484L159.828 474.598ZM134.079 159.463C133.268 149.532 135.593 144.782 138.058 141.879L92.3173 103.049C77.4725 120.535 72.4591 142.081 74.2786 164.349L134.079 159.463ZM138.058 141.879C140.97 138.449 145.73 135.244 155.893 134.414L151.007 74.613C128.184 76.4778 107.435 85.2404 92.3173 103.049L138.058 141.879ZM155.893 134.414C166.676 133.533 172.006 136.047 175.292 138.837L214.123 93.0963C196.17 77.8557 173.995 72.7347 151.007 74.613L155.893 134.414ZM175.763 139.228C178.862 141.752 181.879 145.922 182.661 155.494L242.462 150.608C240.613 127.979 231.727 107.426 213.652 92.705L175.763 139.228ZM182.661 155.494L193.25 285.082L253.05 280.196L242.462 150.608L182.661 155.494ZM246.089 301.973L397.988 121.752L352.11 83.0834L200.211 263.305L246.089 301.973ZM398.282 121.398C403.235 115.335 407.247 113.876 410.946 113.574L406.06 53.7736C383.841 55.589 365.551 66.6259 351.817 83.4371L398.282 121.398ZM410.946 113.574C415.369 113.213 419.422 114.206 424.455 118.479L463.285 72.7382C447.08 58.9805 427.554 52.0173 406.06 53.7736L410.946 113.574ZM424.926 118.87C429.535 122.624 431.082 126.053 431.439 130.423L491.24 125.537C489.479 103.99 479.38 85.8379 462.815 72.3468L424.926 118.87ZM431.439 130.423C431.693 133.529 431.056 138.23 424.667 145.494L469.719 185.121C484.31 168.533 493.104 148.349 491.24 125.537L431.439 130.423ZM424.515 145.668L313.436 273.93L358.792 313.21L469.871 184.947L424.515 145.668ZM316.396 316.179L458.135 439.795L497.572 394.577L355.833 270.961L316.396 316.179Z" fill="#FFB3B3"/>
<path d="M477.854 417.186C488.866 426.169 494.901 437.14 495.96 450.099C497.019 463.058 493.041 474.847 484.026 485.466C475.011 496.086 463.827 501.941 450.476 503.032C435.946 504.219 422.081 499.027 408.881 487.455L226.952 329.173L238.31 468.186C239.658 484.679 235.824 498.235 226.809 508.854C217.762 519.081 204.795 524.884 187.91 526.264C171.416 527.612 157.876 523.974 147.289 515.352C137.062 506.304 131.275 493.534 129.927 477.041L104.179 161.906C102.863 145.806 106.533 132.659 115.188 122.464C124.203 111.844 136.957 105.861 153.45 104.513C170.336 103.134 184.088 106.951 194.708 115.967C205.295 124.589 211.246 136.95 212.562 153.051L223.15 282.639L375.049 102.417C384.393 90.9806 395.544 84.7327 408.503 83.6739C421.462 82.6151 433.251 86.5933 443.87 95.6084C454.458 104.231 460.281 115.022 461.339 127.98C462.398 140.939 457.683 153.381 447.193 165.307L336.114 293.57L477.854 417.186Z" fill="#FFE5D7"/>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
graphics/Styles.pdf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#da532c</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,31 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="260.000000pt" height="260.000000pt" viewBox="0 0 260.000000 260.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,260.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1100 1797 c-19 -5 -41 -14 -48 -20 -20 -16 -42 -64 -52 -110 -7 -36
-8 -38 -9 -12 -1 40 -33 91 -73 116 -25 15 -45 19 -83 16 -55 -5 -65 -14 -218
-195 -42 -51 -77 -87 -77 -80 -3 62 -13 129 -26 158 -39 92 -170 111 -246 36
-40 -41 -43 -72 -23 -286 6 -71 11 -131 20 -255 9 -120 14 -162 21 -192 30
-118 218 -133 275 -22 17 34 19 52 14 124 -6 86 -4 95 19 73 24 -24 143 -128
200 -174 46 -39 66 -48 106 -52 35 -3 57 0 74 11 13 9 35 14 48 12 12 -3 48
-9 78 -15 30 -5 82 -14 115 -20 61 -11 170 -14 215 -5 69 13 87 19 115 34 53
29 107 74 136 114 l28 39 7 -43 c5 -28 18 -55 40 -78 l32 -36 94 1 c106 0 315
12 369 20 20 3 51 18 69 33 27 22 33 36 37 77 6 62 -14 107 -60 131 -32 16
-46 17 -241 10 l-49 -2 -2 45 c-2 25 -5 83 -9 130 -3 47 -8 134 -12 194 -3 60
-10 121 -16 135 -31 85 -144 119 -224 70 -40 -24 -64 -74 -64 -131 -1 -33 -3
-39 -10 -26 -18 29 -130 97 -194 117 -55 17 -140 34 -296 60 -25 4 -61 3 -80
-2z m-114 -209 c-3 -18 -8 -46 -10 -63 -7 -46 -38 -218 -41 -235 -2 -8 -4 -23
-4 -32 -1 -24 -11 -22 -47 10 -17 15 -48 42 -69 60 l-37 33 28 32 c16 17 31
34 35 37 30 28 139 166 139 177 0 7 3 13 6 13 3 0 4 -15 0 -32z m429 -112 c57
-37 72 -106 46 -203 -23 -83 -72 -114 -170 -107 -62 4 -74 10 -67 32 3 10 8
35 11 57 2 22 7 51 10 65 2 14 7 41 10 60 4 19 10 52 14 73 5 20 7 37 4 37 -3
0 0 6 6 14 10 12 19 12 62 1 28 -8 61 -21 74 -29z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,19 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

60
tests/README.md Normal file
View File

@ -0,0 +1,60 @@
# Full Document Test Cases
The `input` folder contains test cases for KDL parsers. The `expected_kdl`
folder contains files with the same name as those in `input` with the expected
output after being run through the parser and printed out again.
If a testcase is intended to fail parsing,
the `input` file _MUST_ have a `_fail` suffix,
and there must be no corresponding file in `expected_kdl`.
## Translation Rules
By necessity, the files in `expected_kdl` are not identical to their
corresponding inputs. They are instead pretty-printed according to the
following rules:
* All comments removed
* Extra empty lines removed except for a newline after the last node
* All nodes should be reformatted without escaped newlines
* Node fields should be `identifier <values> <properties> <children only if non-empty>`
* All values and all children must be in the same order as they were defined.
* Properties must be in _alphabetical order_ and separated by a single space.
* All strings must be represented as regular strings, with appropriate escapes
for invalid bare characters. That means that raw strings must be converted
to plain strings, and escaped.
* Any literal newlines or other ascii escape characters in escaped strings
replaced with their escape sequences.
* All identifiers must be unquoted unless they _must_ be quoted. That means
`"foo"` becomes `foo`, and `"foo bar"` stays that way.
* Any duplicate properties must be removed, with only the rightmost one
remaining. This also means duplicate properties must be allowed.
* 4 space indents
* All numbers must be converted to their simplest decimal representation. That
means that hex, octal, and binary must all be converted to decimals. All
floats must be represented using `E` notation, with a single digit left of
the decimal point if the float is less than 1. While parsers are required to
_consume_ different number syntaxes, they are under no obligation to
represent numbers in any particular way.
Data may be manipulated as you wish in order to output the expected KDL. This
test suite verifies the ability to **parse**, not specific quirks about
internal representations.
## What to do if a test fails for you
This test suite was originally designed for a pre-1.0 version of the KDL
specification. If you encounter a failure, it's likely that the test suite
will need to be updated, rather than your parser itself. This test suite is
NOT AUTHORITATIVE. If this test suite disagrees with the KDL spec in any way,
the most desirable resolution is to send a PR to this repository to fix the
test itself. Likewise, if you think a test succeeded but should not have,
please send a PR.
If you think the disagreement is due to a genuine error or oversight in the
KDL specification, please open an issue explaining the matter and the change
will be considered for the next version of the KDL spec.
# Benchmarks
The `benchmarks` folder contains some large or gnarly documents intended to be used to stress-test your parser and help with profiling. They are intentionally not part of the testsuite, and just provided for your own personal benefit.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
node "\"\\\b\f\n\r\t "

View File

@ -0,0 +1,3 @@
node arg prop=val {
inner_node
}

View File

@ -0,0 +1 @@
node arg arg=val

View File

@ -0,0 +1 @@
node a

View File

@ -0,0 +1 @@
node (type)#false

View File

@ -0,0 +1 @@
node (type)2.5

View File

@ -0,0 +1 @@
node (type)16

View File

@ -0,0 +1 @@
node (type)#null

View File

@ -0,0 +1 @@
node (type)str

View File

@ -0,0 +1 @@
node (type)str

View File

@ -0,0 +1 @@
node (type)#true

View File

@ -0,0 +1 @@
node (type)arg

View File

@ -0,0 +1 @@
node (type)0

View File

@ -0,0 +1 @@
node

View File

@ -0,0 +1 @@
😁 happy!

View File

@ -0,0 +1 @@
node .

View File

@ -0,0 +1 @@
node +

View File

@ -0,0 +1 @@
node +.

View File

@ -0,0 +1 @@
node 2

View File

@ -0,0 +1 @@
node 2

View File

@ -0,0 +1 @@
node 2

View File

@ -0,0 +1 @@
node ("")10

View File

@ -0,0 +1 @@
("")node

View File

@ -0,0 +1 @@
node key=("")#true

View File

@ -0,0 +1 @@
node arg

View File

@ -0,0 +1 @@
node arg

View File

@ -0,0 +1 @@
node

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@
node arg

View File

@ -0,0 +1 @@
node #false #true

View File

@ -0,0 +1 @@
node prop1=#true prop2=#false

View File

@ -0,0 +1,3 @@
foo123 {
bar
}

View File

@ -0,0 +1 @@
foo123<bar>foo weeee

View File

@ -0,0 +1 @@
foo123,bar weeee

View File

@ -0,0 +1 @@
node (type)10

View File

@ -0,0 +1 @@
(type)node

View File

@ -0,0 +1 @@
node key=(type)10

View File

@ -0,0 +1,2 @@
node1
node2

View File

@ -0,0 +1 @@
node (type)10

View File

@ -0,0 +1 @@
(type)node

View File

@ -0,0 +1 @@
node key=(type)10

View File

@ -0,0 +1 @@
node arg2

View File

@ -0,0 +1 @@
node arg

View File

@ -0,0 +1 @@
node_2

View File

@ -0,0 +1 @@
node_2

View File

@ -0,0 +1 @@
node arg

View File

@ -0,0 +1,2 @@
node1
node2

View File

@ -0,0 +1 @@
node --

View File

@ -0,0 +1 @@
node 😀

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@
node

View File

@ -0,0 +1 @@
node

View File

@ -0,0 +1 @@
node

View File

@ -0,0 +1 @@
node

View File

@ -0,0 +1 @@
node

Some files were not shown because too many files have changed in this diff Show More