Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add first draft of URL specification, refs #93 #216

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions solutions/documentation/url-specification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# URL Specification v1.0.0

## Table of contents

- [Introduction notes](#introduction-notes)
- [URL generation](#url-generation)
- [Examples](#examples)

## Introduction notes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably add here some general principles. What we want from this URL scheme, things like compatibility, testability, things like that.

### 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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we write. Also clarify if this is current state, or a proposal.


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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are those values fixed by this document?

- 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).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't really define the information that has that metadata, but rather how to generate them. Also, it would be interesting to split this metadata into "primary" (which the author uses) or "secondary" (generated).

- Routine: Pieces of documentation with headers matching `routine` or `operator` tokens of the same grammar.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, you're not saying what they are, only how they are generated. And again, these are secondary tags, not primary.

- Reference: created by `X<>` elements.

- `subkind`: classification purposes (this value does not affect urls)
- `category`: classification purposes (this value does not affect urls)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URLs include fragments. Are you sure this does not affect the generation of fragments?


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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if they are? What if you want to directly generate a "syntax" instead of deducing it from the markup?


*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
~~~

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know what to make of this. If this document is a URL generation document, it should include all of it, not the directory part. Right now, the name of the file is taken directly from the name of the primary file. What happens in this case?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi class files are only supported for types, so they have different names. I will clarify that.

### 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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't say "if necessary". It's going to be used in the URL fragment. So this should be part of the URL specification too.

- `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).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a table that clarifies how any URI is generated?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not added a table yet because there are over 60 valid headers and references. Nonetheless, I have added a list of tests to check that the document describes the current behavior in Documentable:ver<2.0.1>


### 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Match.
Also, I think that generating URLs should be separated from specifying the URLs. You should define the kind of objects, and their URLs. Then, in a second phase, how these objects are identified. But special-casing this kind of thing is going to lead again to ambiguity.
Additionally, there are not "primary" and "secondary" URLs there are URLs (which include fragments) generated from objects. Some of these objects will not be altered from the original shape, some of them will be generated. But that has nothing to do with the URL itself, and should be strictly separated.


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
' ' => _
~~~
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never really liked these, any thoughts on changing them to something else? For example, CIRCUMFLEX_ACCENT can be simplified to CARET, but maybe there's an even better way?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To tell you the truth, I do not know. Some of those characters are there because they are not valid in paths. So maybe they should only be changed in the filename of the HTML page and redirected from the tool serving the pages. With a dynamic site, we would not need those I think.


See [this example](#get-all-urls-from-secondary-objects) and [this one](#classification-of-secondary-objects-by-name).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all the symbols that can be found there?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only from secondary files. Those are all URLs under /syntax/ and /routines/.


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

# you can check them! (very long output)
say %routine-documents<⊅>;
~~~