Skip to content

Instantly share code, notes, and snippets.

@antoniogamiz
Created July 30, 2020 17:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antoniogamiz/9f7feb5b93a95d0c121ec0ba03d28b6a to your computer and use it in GitHub Desktop.
Save antoniogamiz/9f7feb5b93a95d0c121ec0ba03d28b6a to your computer and use it in GitHub Desktop.
Raku docs url specification

URL Specification v1.0.0

Table of contents

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:

=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:

=begin pod :kind("Type") :subkind("class") :category("basic")

Docs!

=end pod

The metadata is formed by three different values:

  • kind: An enum 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) or with headers matching the syntax token of this grammar.
    • 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:

=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 will be /language/experimental.

See this example.

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:

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 sub. This function makes these replacements:

/   => $SOLIDUS
%   => $PERCENT_SIGN
^   => $CIRCUMFLEX_ACCENT
#   => $NUMBER_SIGN
' ' => _

See this example and this one.

Examples

Get all URLs from Primary objects
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
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

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<kind>).categorize({.name});
my %syntax-documents = $registry.lookup("syntax", :by<kind>).categorize({.name});

# you can check them! (very long output)
say %routine-documents<>;
@Altai-man
Copy link

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.

I wonder if we want to just encode those symbols using usual url encoding without inventing SOLIDUS-like names (preserving the backward compat).

@antoniogamiz
Copy link
Author

Can you elaborate on how is this maps to current state of things?

What do you mean? This is the current state of things. That's the purpose of the first version of this specification: knowing exactly what's being done to change things later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment