From fee226a41b9090779ee8269e3a227d19fdcfc63f Mon Sep 17 00:00:00 2001 From: Antonio Gamiz Date: Fri, 31 Jul 2020 09:26:43 +0200 Subject: [PATCH 1/2] Add first draft of URL specification, refs #93 --- solutions/documentation/url-specification.md | 160 +++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 solutions/documentation/url-specification.md diff --git a/solutions/documentation/url-specification.md b/solutions/documentation/url-specification.md new file mode 100644 index 0000000..592ad31 --- /dev/null +++ b/solutions/documentation/url-specification.md @@ -0,0 +1,160 @@ +# URL Specification v1.0.0 + +## Table of contents + +- [Introduction notes](#introduction-notes) +- [URL generation](#url-generation) +- [Examples](#examples) + +## Introduction notes + +### Pod block classification + +Before write an URL specification, we need to know where those URLs point to. In the documentation, we define documents by using: + +~~~perl6 +=begin pod + +Docs! + +=end pod +~~~ + +This is usually called a *pod block*. In `Documentable`, these blocks are represented by a `Documentable::Primary` object. To avoid depending on the logical distribution of these files in a directory structure and in order to make a more granular classification of these pod blocks, we use additional *metadata*: + +~~~perl6 +=begin pod :kind("Type") :subkind("class") :category("basic") + +Docs! + +=end pod +~~~ + +The metadata is formed by three different values: + +- `kind`: An [enum](https://github.com/Raku/Documentable/blob/9563911c93fee5c7fe83f4de5a2e9ee58167bd87/lib/Documentable.pm6#L4-L6) with six different values, depending of the documentation you are writing: + + - Type: Pod blocks related to 'Types'. + - Language: Pod blocks related to 'Language'. + - Programs: Pod blocks related to 'Programs'. + - Syntax: Pieces of documentation with this kind of header: `=headN X<>` ([example](https://github.com/Raku/doc/blob/1be6eefaac9fa27341207be56c85a4729dcaa570/doc/Language/experimental.pod6#L17)) or with headers matching the `syntax` token of [this grammar](https://github.com/Raku/Documentable/blob/master/lib/Documentable/Heading/Grammar.pm6). + - Routine: Pieces of documentation with headers matching `routine` or `operator` tokens of the same grammar. + - Reference: created by `X<>` elements. + +- `subkind`: classification purposes (this value does not affect urls) +- `category`: classification purposes (this value does not affect urls) + +The last three are set by `Documentable` and should not be used in the metadata. For the creation of URLs, we are only interested in the first three, so I will only refer to those in the next paragraphs. + +*Side note:* have in mind that in the same `.pod6` file, can appear more than one pod block, so you can write things like: + +~~~perl6 +=begin pod :kind("Type") :subkind("class") :category("basic") + +Docs for a type! + +=end pod + +=begin pod :kind("Type") :subkind("class") :category("basic") + +Docs for another type! + +=end pod +~~~ + +### Pod block names + +We need to give each and every pod block a *meaningful* name, to show it if necessary. These names depend on the pod block `Kind` value. + +- `Kind::Type`: the last word of `=TITLE` is taken as name. So, if we have a pod block with `=TITLE class X::Some::Class`, the name will be set to `X::Some::Class`. +- `Kind::Language` and `Kind::Programs`: `=TITLE` is converted to string. So, if we have a pod block with `=TITLE Experimental features`, the name will be set to `Experimental features`. + +## URL generation + +### Pod block URLs + +Each and every pod block gets a standalone HTML page, so every pod block needs an URL. This URL will depend on `Kind` classification: + +- `Kind::Type`: the URL for those blocks will be formed as: `/${kind.lc}/{$name}`. +- `Kind::Language` and `Kind::Programs`: the URL for those blocks will be formed as `/{kind}/{$filename}`, where filename is the filename with the extension stripped out. So the URL for [experimental.pod6](https://github.com/Raku/doc/blob/master/doc/Language/experimental.pod6#L17) will be `/language/experimental`. + +See [this example](#get-all-urls-from-primary-objects). + + +### Secondary URLs + +In a pod block, we can have a lot of different documented methods, subs, etc. Lot of the time, we do not want all that information, but only a little part. How we define those *little parts of documentation*? We use headers. But not all headers are valid, they need to follow one of these two rules: + +- Match [this grammar](https://github.com/Raku/Documentable/blob/master/lib/Documentable/Heading/Grammar.pm6). +- Math `=headn X<>` format. + +Each and every one of these subsets of a pod block is represented by a `Documentable::Secondary` object. These objects also get a name, specified by the same grammar. They also get an HTML page, but not in the same way as primary objects. First, they are grouped by `name`, forming a single pod block. This is made in order to have the routines, subs and methods with the same named grouped in the same page, to help the final user. Now, to form the URL, the intuitive way would be: `"/${kind.lc}/${name}`, but this is not correct in some cases. + +As you may know, `Raku` accepts a huge range of symbols, so the name `attribute` can be a little bit weird sometimes (from a URL perspective). For this reason, `name` needs to be slightly altered to generate valid URLs. This alteration is made by [good-name](https://github.com/Raku/Documentable/blob/9563911c93fee5c7fe83f4de5a2e9ee58167bd87/lib/Documentable.pm6#L55-L75) sub. This function makes these replacements: + +~~~ +/ => $SOLIDUS +% => $PERCENT_SIGN +^ => $CIRCUMFLEX_ACCENT +# => $NUMBER_SIGN +' ' => _ +~~~ + +See [this example](#get-all-urls-from-secondary-objects) and [this one](#classification-of-secondary-objects-by-name). + +## Examples + +##### Get all URLs from Primary objects + +~~~perl6 +use Documentable:ver<2.0.0>; +use Documentable::Registry:ver<2.0.0>; + +my $registry = Documentable::Registry.new( + :topdir("doc"), + :dirs(DOCUMENTABLE-DIRS), + :!verbose, +); + +$registry.compose; + +say $registry.documentables.map({.url}); +~~~ + +##### Get all URLs from Secondary objects + +~~~perl6 +use Documentable:ver<2.0.0>; +use Documentable::Registry:ver<2.0.0>; + +my $registry = Documentable::Registry.new( + :topdir("doc"), + :dirs(DOCUMENTABLE-DIRS), + :!verbose, +); + +$registry.compose; + +say $registry.definitions.map({.url}); +~~~ + +#### Classification of secondary objects by name + +~~~perl6 +use Documentable:ver<2.0.0>; +use Documentable::Registry:ver<2.0.0>; + +my $registry = Documentable::Registry.new( + :topdir("doc"), + :dirs(DOCUMENTABLE-DIRS), + :!verbose, +); + +$registry.compose; + +my %routine-documents = $registry.lookup("routine", :by).categorize({.name}); +my %syntax-documents = $registry.lookup("syntax", :by).categorize({.name}); + +# you can check them! (very long output) +say %routine-documents<⊅>; +~~~ \ No newline at end of file From 0f61e76a7ee23a91d0070853facf32bc76ca7e5b Mon Sep 17 00:00:00 2001 From: Antonio Gamiz Date: Fri, 31 Jul 2020 14:27:11 +0200 Subject: [PATCH 2/2] Add new draft, second revision --- solutions/documentation/url-specification.md | 300 ++++++++++++++++--- 1 file changed, 251 insertions(+), 49 deletions(-) diff --git a/solutions/documentation/url-specification.md b/solutions/documentation/url-specification.md index 592ad31..055b541 100644 --- a/solutions/documentation/url-specification.md +++ b/solutions/documentation/url-specification.md @@ -1,98 +1,295 @@ -# URL Specification v1.0.0 - -## Table of contents +# URI Specification v1.0.0 - [Introduction notes](#introduction-notes) -- [URL generation](#url-generation) +- [Indexable Object](#indexable-object) + - [Attributes](#attributes) + - [name](#name) + - [pod](#pod) + - [kind](#kind) + - [subkinds](#subkinds) + - [categories](#categories) +- [Indexable object types](#indexable-object-types) + - [Primary indexable objects](#primary-indexable-objects) + - [Pod blocks](#pod-blocks) + - [Name attribute](#name-attribute) + - [Kind Type](#kind-type) + - [Kind Language and Programs](#kind-language-and-programs) + - [Multiple pod blocks](#multiple-pod-blocks) + - [Secondary indexable objects](#secondary-indexable-objects) + - [Kind::Routine](#kindroutine) + - [Attributes](#attributes-1) + - [Kind::Syntax](#kindsyntax) + - [Attributes](#attributes-2) + - [Kind::Reference](#kindreference) + - [Attributes](#attributes-3) + - [URI setting](#uri-setting) +- [URI setting](#uri-setting-1) +- [URI rewriting](#uri-rewriting) - [Examples](#examples) + - [Get all URLs from Primary objects](#get-all-urls-from-primary-objects) + - [Get all URLs from Secondary objects](#get-all-urls-from-secondary-objects) + - [Classification of secondary objects by name](#classification-of-secondary-objects-by-name) ## Introduction notes -### Pod block classification +In this specification, we want to set a common guidelines and rules for URLs in the [official documentation](raku.docs.org). This specification must be implemented be the tools generating the HTML pages of the doc site ([Documentable](https://github.com/Raku/Documentable) at this moment). For that reason, the described behavior is **currently** implemented in `Documentable:ver<2.0.0>`. + +Right now, there are some tests for URL generation in `Documentable`, but they are kind of scattered and are insufficient, so when this specification is finished, a dedicated set of tests will have to be created. Maybe a spec json file, as [Mustache](https://github.com/mustache/spec/tree/master/specs) does. + +In the official documentation, there are a lot of different things, like pages generated directly from a single [source file](https://docs.raku.org/type/Associative) from pages generated by grouping certain parts of several [source files](https://docs.raku.org/routine/(%7C),%20infix%20%E2%88%AA). In order to represent this information in a manageable way, we use certain data structures, name conventions and metadata, but everything is based on **indexable objects**. + +## Indexable Object + +An indexable object is a set of information documenting one thing or several related things that can be referred to. In order to clarify this definition, you can think of an indexable object as the documentation for a certain [type](https://github.com/Raku/doc/blob/master/doc/Type/Any.pod6), for some [method](https://github.com/Raku/doc/blob/aec4740ded31770c799b5e236d9e5d423b8f988b/doc/Type/Any.pod6#L19-L34) or a [tutorial](https://github.com/Raku/doc/blob/master/doc/Language/grammar_tutorial.pod6). Even [references](https://github.com/Raku/doc/blob/master/doc/Type/Any.pod6#L102) are indexable objects. + +We can extract and set additional information to these objects, in order to classify them and create URIs to refer them. **All indexable objects** share these attributes but with different values: + +### Attributes + +#### name + +Relatively short string to name the object. For instance: `Any`, `X::AdHoc`, `101-basics`. etc. See [indexable object types](#indexable-object-types). + +#### pod + +Pod representing the indexable object. This pod *does not have to be* a `=begin pod ... =end pod` block. It *must* be a [Pod::Block](https://docs.raku.org/type/Pod::Block) or an array containing `Pod::Block`s. -Before write an URL specification, we need to know where those URLs point to. In the documentation, we define documents by using: +#### kind + +This a **fixed** list of values to make a less granular classification of what the pod is representing. ~~~perl6 -=begin pod +enum Kind (Type, Language, Programs, Syntax, Routine, Reference); +~~~ + +The first three ones, cannot be easily deduced from the indexable object, so they need to be **specified by the user**, whereas the last three can be deduced without much trouble. You should set one of this to the indexable objects depending on the documentation you are trying to represent: + +- `Type`: when the docs is about a class, a role or an enum. +- `Language`: when the docs is related to the language itself. +- `Programs`: when the docs is describing a program: a debugger, for instance. + +Automatically deduced: + +- `Syntax`: when the docs is related to a `twigil`, `constant`, `variable`, `quote` or `declarator`1. +- `Routine`: when the docs is related to a `sub`, `method`, `term`, `routine`, `submethod`, `trait`, `infix`, `prefix`, `postfix`, `circumfix`, `postcircumfix` or a `listop`. +- `Reference`: when the docs is just a `X<>` element. + +#### subkinds + +This is used as a more granular classification of indexable objects, based on the contents of the documentation. The value of these subkinds depends on the kind of the indexable object: + +- `Type`: specified by the user. +- `Language`: specified by the user. +- `Programs`: specified by the user. +- `Routine`: deduced from the pod. A list containing a subset of these values: `infix, prefix, postfix, circumfix, postcircumfix, listop, sub, method, term, routine, submethod, trait twigil constant variable quote declarator`. +- `Syntax`: deduced from the pod. A list containing a subset of these values: `twigil, constant, variable, quote, declarator` 2. +- `Reference`: indexable objects of this kind always have the same `subkinds` value: `['reference']`. + +#### categories -Docs! +This is also used as a more granular classification of indexable objects, nonetheless, this classification is not based entirely in the contents of the documentation. This value also depends of the kind of the indexable object: +- `Type`: specified by the user. +- `Language`: specified by the user. +- `Programs`: specified by the user. +- `Routine`: same as `subkinds` except if `subkinds` contains one the following values: `infix, prefix, postfix, circumfix, postcircumfix, listop`. In that case, `categories` is always `['operators']`. +- `Syntax`: same as `subkinds`. 3. +- `Reference`: indexable objects of this kind always have the same `subkinds` value: `['reference']`. + +## Indexable object types + +### Primary indexable objects + +#### Pod blocks + +A primary indexable object is created from a `pod block`. A pod block is just a pod structure like this one: + +~~~perl6 +=begin pod +... =end pod ~~~ -This is usually called a *pod block*. In `Documentable`, these blocks are represented by a `Documentable::Primary` object. To avoid depending on the logical distribution of these files in a directory structure and in order to make a more granular classification of these pod blocks, we use additional *metadata*: +But that's not a *valid* one. For a pod block to be a primary indexable object, it needs to comply some rules: -~~~perl6 -=begin pod :kind("Type") :subkind("class") :category("basic") +- It must have a `=TITLE`. +- It must have a `=SUBTITLE`. +- It must contain three different key/value pairs following the format: `:kind() :subkind() :category()`. + - `:kind` has to be one and only one of the stringyfied version of the first three `Kind`s: `:kind("type")`, `:kind("language")` or `:kind("programs")`. + - `:subkind` is an arbitrary string. + - `:category` is an arbitrary string. -Docs! +So, a valid primary indexable object is something like this: +~~~perl6 +=begin pod :kind("Language") :subkind("Language") :category("migration") +=TITLE Perl to Raku guide - functions +=SUBTITLE Builtin functions in Perl to Raku =end pod ~~~ -The metadata is formed by three different values: - -- `kind`: An [enum](https://github.com/Raku/Documentable/blob/9563911c93fee5c7fe83f4de5a2e9ee58167bd87/lib/Documentable.pm6#L4-L6) with six different values, depending of the documentation you are writing: +In this key/value pairs, you can set the value of [subkinds](#subkinds) and [categories](#categories) of the first three kinds. - - Type: Pod blocks related to 'Types'. - - Language: Pod blocks related to 'Language'. - - Programs: Pod blocks related to 'Programs'. - - Syntax: Pieces of documentation with this kind of header: `=headN X<>` ([example](https://github.com/Raku/doc/blob/1be6eefaac9fa27341207be56c85a4729dcaa570/doc/Language/experimental.pod6#L17)) or with headers matching the `syntax` token of [this grammar](https://github.com/Raku/Documentable/blob/master/lib/Documentable/Heading/Grammar.pm6). - - Routine: Pieces of documentation with headers matching `routine` or `operator` tokens of the same grammar. - - Reference: created by `X<>` elements. +#### Name attribute -- `subkind`: classification purposes (this value does not affect urls) -- `category`: classification purposes (this value does not affect urls) +Name attribute depends on the kind specified by the user in the primary indexable object: -The last three are set by `Documentable` and should not be used in the metadata. For the creation of URLs, we are only interested in the first three, so I will only refer to those in the next paragraphs. +##### Kind Type -*Side note:* have in mind that in the same `.pod6` file, can appear more than one pod block, so you can write things like: +In this case, the last word of the `=TITLE` element is taken as name. So, if we have the following primary indexable object: ~~~perl6 =begin pod :kind("Type") :subkind("class") :category("basic") +=TITLE class Any +=SUBTITLE Thing/object + class Any is Mu {} +=end pod +~~~ + +Its name would be `Any`. -Docs for a type! +##### Kind Language and Programs +In this case, due to the arbitrariness of the `=TITLE` element, we cannot deduce a name, so we take the name of the file, stripping out the extension. So, if we have the following primary indexable object: + +~~~perl6 +=begin pod :kind("Language") :subkind("Language") :category("migration") +=TITLE Perl to Raku guide - functions +=SUBTITLE Builtin functions in Perl to Raku =end pod +~~~ -=begin pod :kind("Type") :subkind("class") :category("basic") +stored in `/SomeDirectory/perl-raku-guide.pod6`, its name would be `perl-raku-guide`. + +#### Multiple pod blocks -Docs for another type! +Several primary indexable objects of `Kind::Type` can be written in the same file as follows: +~~~perl6 +=begin pod :kind("Type") :subkind("class") :category("basic") +=TITLE class Any +=SUBTITLE Thing/object + class Any is Mu {} +=end pod + +=begin pod :kind("Type") :subkind("enum") :category("basic") +=TITLE enum Bool +=SUBTITLE Logical Boolean =end pod ~~~ -### Pod block names +They will be treated as two independent primary indexable objects. + +### Secondary indexable objects + +A primary indexable object can contain a lot of documentation, for instance, [Any](https://github.com/Raku/doc/blob/master/doc/Type/Any.pod6) has a very long list of methods. In order to gave a more granular documentation, we can extract certain parts of that pod and create more indexable objects. + +#### Kind::Routine + +To detect those parts, we use [pod headers](https://docs.raku.org/type/Pod::Heading). But not all pod headers are valid, they need to follow one of the these formats: + +- `[T|t]he ` +- ` ` + +where + +- `` is one element of `infix, prefix, postfix, circumfix, postcircumfix, listop, sub, method, term, routine, submethod, trait`. +- `` is a single word (without spaces). +- `` can be formed by several words separated by spaces. + +##### Attributes + +- `kind` is set to `Kind::Routine`. +- `name` is set to `` or ``. +- `subkinds` is set to `()`. +- `categories`: + - If subkind is one of `infix, prefix, postfix, circumfix, postcircumfix, listop`, then it will be set to `("operator")`. + - If subkind is one of `sub, method, term, routine, submethod, trait`, then it will be set to the same value as `subkinds`. + +#### Kind::Syntax -We need to give each and every pod block a *meaningful* name, to show it if necessary. These names depend on the pod block `Kind` value. +To detect those parts, we use [pod headers](https://docs.raku.org/type/Pod::Heading). But not all pod headers are valid, they need to follow one of the these formats: -- `Kind::Type`: the last word of `=TITLE` is taken as name. So, if we have a pod block with `=TITLE class X::Some::Class`, the name will be set to `X::Some::Class`. -- `Kind::Language` and `Kind::Programs`: `=TITLE` is converted to string. So, if we have a pod block with `=TITLE Experimental features`, the name will be set to `Experimental features`. +- `[T|t]he ` +- ` ` -## URL generation +where -### Pod block URLs +- `` is one element of `twigil constant variable quote declarator`. +- `` is a single word (without spaces). +- `` can be formed by several words separated by spaces. -Each and every pod block gets a standalone HTML page, so every pod block needs an URL. This URL will depend on `Kind` classification: +##### Attributes -- `Kind::Type`: the URL for those blocks will be formed as: `/${kind.lc}/{$name}`. -- `Kind::Language` and `Kind::Programs`: the URL for those blocks will be formed as `/{kind}/{$filename}`, where filename is the filename with the extension stripped out. So the URL for [experimental.pod6](https://github.com/Raku/doc/blob/master/doc/Language/experimental.pod6#L17) will be `/language/experimental`. +- `kind` is set to `Kind::Syntax`. +- `name` is set to `` or ``. +- `subkinds` is set to `()`. +- `categories`: will be set to same value as `subkinds`. -See [this example](#get-all-urls-from-primary-objects). +`=headn X<>`123 is also a valid header. +#### Kind::Reference -### Secondary URLs +These secondary indexable objects come from `X<>` elements (see [Pod::FormattingCode](https://docs.raku.org/type/Pod::FormattingCode)). They have to be written as follows: -In a pod block, we can have a lot of different documented methods, subs, etc. Lot of the time, we do not want all that information, but only a little part. How we define those *little parts of documentation*? We use headers. But not all headers are valid, they need to follow one of these two rules: +~~~perl6 +X +~~~ + +`meta` is a string containing several group of words, separated by `;`, and words inside each group separated by `,`. For instance: `foo, bar; w`. Raku would interpret that `meta` attribute as follows: `[ [foo bar] [w] ]`, that is, a list containing two lists: one with two elements and other with a single element. -- Match [this grammar](https://github.com/Raku/Documentable/blob/master/lib/Documentable/Heading/Grammar.pm6). -- Math `=headn X<>` format. +From a single `X<>` element, several secondary indexable objects can be created, one for every group of words found in `meta`. For instance: -Each and every one of these subsets of a pod block is represented by a `Documentable::Secondary` object. These objects also get a name, specified by the same grammar. They also get an HTML page, but not in the same way as primary objects. First, they are grouped by `name`, forming a single pod block. This is made in order to have the routines, subs and methods with the same named grouped in the same page, to help the final user. Now, to form the URL, the intuitive way would be: `"/${kind.lc}/${name}`, but this is not correct in some cases. +~~~perl6 +X +~~~ -As you may know, `Raku` accepts a huge range of symbols, so the name `attribute` can be a little bit weird sometimes (from a URL perspective). For this reason, `name` needs to be slightly altered to generate valid URLs. This alteration is made by [good-name](https://github.com/Raku/Documentable/blob/9563911c93fee5c7fe83f4de5a2e9ee58167bd87/lib/Documentable.pm6#L55-L75) sub. This function makes these replacements: +Would be interpreted as if you had typed: +~~~perl6 +X +X +X ~~~ + +`text` or `meta` can be empty strings, but not both at the same time, so `X<|meta>` and `X` are valid references. + +##### Attributes + +In all cases, `kind` and `subkinds` are set to `Kind::Reference` and `['reference']` respectively. `categories` attribute is not set in these indexable objects. + +`name` setting depends on `meta` variable: + +- `meta` is an empty string. Then, `meta` is set to `[text]`. So it would be interpreted as `X`. +- `meta` has only one element: `name` is set to the stringyfied version of `meta`. So `X<|a>` would get the name `a`. +- `meta` has more than one element: `name` is set to an alteration of `meta`. So `X<|a,b,c>` would get the name `c (a b)`. + +##### URI setting + +The URI of these indexable objects depends on the primary indexable object where the reference was found. The URI is formed as follows: + +~~~perl6 +"{$origin.uri}#index-entry-{$meta}-{$index-text}" +~~~ + +where: + - `origin.uri` is the URI of assigned to the primary indexable object where the reference was found. + - `$meta` is the concatenation by `-` of the groups found in `meta`. + - `$index-text` is `text`. + +## URI setting + +All indexable objects have an associated *Uniform Resource Identifier* or URI. It is formed based on the common attributes of all indexable objects, as follows: + +~~~perl6 +"/{$kind.lc}/{$name}" +~~~ + +## URI rewriting + +As you may know, `Raku` accepts a huge range of symbols, so the `name` attribute can be a little bit weird sometimes (from a URI perspective). For this reason, `name` needs to be slightly altered to generate valid URLs. This alteration is made by making these replacements: + +~~~perl6 / => $SOLIDUS % => $PERCENT_SIGN ^ => $CIRCUMFLEX_ACCENT @@ -100,10 +297,10 @@ As you may know, `Raku` accepts a huge range of symbols, so the name `attribute` ' ' => _ ~~~ -See [this example](#get-all-urls-from-secondary-objects) and [this one](#classification-of-secondary-objects-by-name). - ## Examples +This specification is intended to be independent from the tool used, but as it's the first version, it's entirely based in the behavior of `Documentable:ver<2.0.0>`, so here you have some examples to check by yourself the concepts explained before: + ##### Get all URLs from Primary objects ~~~perl6 @@ -138,7 +335,7 @@ $registry.compose; say $registry.definitions.map({.url}); ~~~ -#### Classification of secondary objects by name +##### Classification of secondary objects by name ~~~perl6 use Documentable:ver<2.0.0>; @@ -155,6 +352,11 @@ $registry.compose; my %routine-documents = $registry.lookup("routine", :by).categorize({.name}); my %syntax-documents = $registry.lookup("syntax", :by).categorize({.name}); -# you can check them! (very long output) say %routine-documents<⊅>; -~~~ \ No newline at end of file +~~~ + +1 Certain kind of headers (`=headn X<>`) too, but there are not logical reason to mark those headers as `Syntax`, so that's needs to be fixed. This behavior is inherited from the old `htmlify.p6`. + +2 Additionally, `=headn X<>` is an indexable object with subkinds its meta part. So, for instance, `=headn X<|foo>`, is a indexable object of kind `Syntax` with subkind set to `('foo')`. This also has to be changed, but once again, this behavior is inherited from `htmlify.pod6`. + +3 The same that happens with 2 and subkinds, also happens with `categories`. \ No newline at end of file