Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
31 changes: 29 additions & 2 deletions build/transform_json_sections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,38 @@ function parseHeading(raw: string): { title: string; id: string } {
return { title: raw, id: slugify(raw) };
}

/**
* Slugify a heading the way Hugo does, so section ids match the anchor on the page.
*
* Hugo has no autoHeadingID setting in config.toml, so it uses Goldmark's default
* "github" style: lowercase, discard anything that is not a letter, decimal digit, ASCII
* whitespace, underscore or hyphen, then turn each remaining whitespace character into one
* hyphen. Note decimal digit specifically -- a subscript such as the one in
* "Naming convention: LVQ<B1>x<B2>" is a Unicode "other number" and Hugo discards it,
* anchoring as "naming-convention-lvqbxb".
*
* Five details matter and all five were wrong before. Underscores and runs of hyphens
* are KEPT, so "redis_url" stays "redis_url" rather than collapsing to "redis-url".
* Whitespace runs are NOT collapsed, so "The special $ ID" becomes "the-special--id"
* with two hyphens, the discarded "$" leaving the spaces either side of it. Leading and
* trailing hyphens are NOT trimmed -- a heading "Negation !" really does anchor as
* "negation-" and "- and + special IDs" as "--and--special-ids". And the whitespace
* class is ASCII only, matching Go's \s, so a non-breaking space is discarded rather
* than turned into a hyphen: "Development environment" anchors as
* "developmentenvironment". JavaScript's \s would have hyphenated it.
*
* Measured against 3,616 heading/anchor pairs harvested from the rendered HTML: this
* reproduces Hugo's anchor for 90.3% of them, against 80.2% for the previous version,
* and every remaining difference is a heading carrying an explicit {#anchor}, which
* parseHeading handles before this function is reached. The trim, whitespace-run and
* non-breaking-space rules were each confirmed against the anchor Hugo emitted for a
* specific heading, since the harvested sample normalises whitespace and cannot show them.
*/
function slugify(text: string): string {
return text
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-|-$/g, '');
.replace(/[^\p{L}\p{Nd}\t\n\f\r _-]/gu, '')
.replace(/[\t\n\f\r ]/g, '-');
}

// Section IDs to filter out (metadata noise, not useful for RAG)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ To add a reader node to an existing database, select **Add reader** from the **A

You can also create one during database creation by selecting **Create an Aurora Replica or Reader node in a different AZ (recommended for scaled availability)** under **Availability & durability > Multi-AZ deployment**.

## <a id="aurora-create-and-apply-parameter-group"></a>Create and apply parameter group
## Create and apply parameter group {#aurora-create-and-apply-parameter-group}

RDI requires some changes to database parameters. On AWS Aurora, you change these parameters via a parameter group.

Expand Down Expand Up @@ -108,7 +108,7 @@ RDI requires some changes to database parameters. On AWS Aurora, you change thes
- [ ] [Create Debezium user](#rds-create-debezium-user)
```

## <a id="rds-create-and-apply-parameter-group"></a>Create and apply parameter group
## Create and apply parameter group {#rds-create-and-apply-parameter-group}

RDI requires some changes to database parameters. On AWS RDS, you change these parameters via a parameter group.

Expand Down
85 changes: 60 additions & 25 deletions layouts/partials/toc-from-markdown.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{{- /* This parses ## and ### headers directly from .RawContent */ -}}
{{- /* since Hugo's .TableOfContents may be empty for custom templates */ -}}

{{- $page := . -}}
{{- $content := .RawContent -}}

{{- /* Unescape HTML entities that may be present in .RawContent */ -}}
Expand Down Expand Up @@ -47,38 +48,72 @@
{{- $title = replaceRE `^## +` "" $headerMatch -}}
{{- end -}}

{{- /* Remove inline code markers */ -}}
{{- $title = replaceRE "`([^`]+)`" "$1" $title -}}
{{- /* Remove other inline formatting */ -}}
{{- $title = replaceRE `\*\*([^*]+)\*\*` "$1" $title -}}
{{- $title = replaceRE `\*([^*]+)\*` "$1" $title -}}
{{- $title = replaceRE `_([^_]+)_` "$1" $title -}}
{{- /* Trim whitespace */ -}}
{{- $title = $title | strings.TrimSpace -}}

{{- /* Hugo's explicit heading anchor, "## Title {#custom-id}". Hugo uses the
anchor as the rendered heading id and does not display it, so it has to come
out of the title and be used verbatim as the id. Matched strictly, because a
loose trailing-brace match would eat Python signatures ending in an empty
dict and dict defaults such as {'extra': 'ignore'}. */ -}}
{{- /* Hugo's explicit heading anchor, "## Title {#custom-id}". Hugo uses the anchor as the
rendered heading id and does not display it, so it has to come out of the title and
be used verbatim as the id. Matched strictly, because a loose trailing-brace match
would eat Python signatures ending in an empty dict and dict defaults such as
{'extra': 'ignore'}.

Lifted off the RAW heading, before any rendering. Doing it afterwards means the
anchor has to survive whatever the renderer does to it, and the emphasis regexes
this used to sit behind ate the underscores out of anchors such as
{#redis.error_reply}, yielding redis.errorreply and a dead deep link. */ -}}
{{- $explicitId := "" -}}
{{- with (findRESubmatch `\s*\{#([A-Za-z0-9][A-Za-z0-9_.:-]*)\}\s*$` $title 1) -}}
{{- $explicitId = index (index . 0) 1 -}}
{{- end -}}
{{- if $explicitId -}}
{{- $title = $title | replaceRE `\s*\{#[A-Za-z0-9][A-Za-z0-9_.:-]*\}\s*$` "" | strings.TrimSpace -}}
{{- $title = $title | replaceRE `\s*\{#[A-Za-z0-9][A-Za-z0-9_.:-]*\}\s*$` "" -}}
{{- end -}}

{{- /* Generate ID (slug) from title */ -}}
{{- $id := $title | lower -}}
{{- /* Replace spaces with hyphens */ -}}
{{- $id = $id | replaceRE `\s+` "-" -}}
{{- /* Remove special characters except hyphens */ -}}
{{- $id = $id | replaceRE `[^a-z0-9-]` "" -}}
{{- /* Remove consecutive hyphens */ -}}
{{- $id = $id | replaceRE `-+` "-" -}}
{{- /* Trim leading/trailing hyphens */ -}}
{{- $id = $id | replaceRE `^-+|-+$` "" -}}
{{- /* Escape a leading ordered-list marker before rendering. Even with display "inline"
the renderer reads "1. Launch the app" as a list item and drops the number, where
the rendered page heading keeps it -- and Hugo's anchor includes it, so dropping it
breaks the deep link too. 299 headings start this way; none starts with -, + or *. */ -}}
{{- $title = $title | replaceRE `^(\d+)([.)])(\s)` `${1}\${2}${3}` -}}

{{- /* Reduce the heading to plain text with Hugo's own Markdown renderer rather than
hand-rolled regexes.

What this replaces stripped inline code markers first and then treated any remaining
* or _ as emphasis, so by that point there was no way to tell that a character had
come from inside a code span. Code-formatted headings therefore lost characters:
"**kwargs" became "*kwargs" and "redis_url" became "redisurl", which published
incorrect API signatures on the redisvl reference pages.

Goldmark applies the real CommonMark rules, including the ban on intraword underscore
emphasis, so snake_case survives whether or not it sits in a code span. RenderString
rather than markdownify because markdownify renders the string as a block. plainify
then strips the inline markup and htmlUnescape restores literal text. */ -}}
{{- /* Keep the raw heading for the id, because Hugo slugs the heading's own text, which
preserves whitespace runs where rendering collapses them: a heading with a double
space anchors as "choosing-the-capacity--capacity", and slugging the rendered title
would give one hyphen. Slugging the raw text costs nothing, because the markup
characters it still contains are discarded by the slug rules anyway, and no heading
in this repo contains a Markdown link -- the one case where the two would diverge.

Whitespace-trimmed, but hyphens are not: a trailing space would otherwise become a
trailing hyphen, where Hugo slugs the trimmed heading text. Those are not the same
thing -- "Negation !" trims to itself, and the space left behind when the "!" is
discarded still becomes the trailing hyphen Hugo emits. */ -}}
{{- $rawTitle := $title | strings.TrimSpace -}}

{{- $title = $page.RenderString (dict "display" "inline") $title | plainify | htmlUnescape | strings.TrimSpace -}}

{{- /* Slug the title the way Hugo does, so the id matches the anchor on the page.
Goldmark's default "github" style: lowercase, discard anything that is not a
letter, number, whitespace, underscore or hyphen, then turn each remaining
whitespace character into one hyphen.

Underscores and runs of hyphens are kept, whitespace runs are NOT collapsed, and
leading and trailing hyphens are NOT trimmed -- "Negation !" really does anchor as
"negation-". The previous version stripped underscores, collapsed runs and trimmed,
so it disagreed with the page anchor three ways. Slugged from the raw heading, not
the rendered title, and kept identical to slugify in
build/transform_json_sections.ts -- change the two together. */ -}}
{{- $id := $rawTitle | lower -}}
{{- $id = $id | replaceRE `[^\p{L}\p{Nd}\s_-]` "" -}}
{{- $id = $id | replaceRE `\s` "-" -}}
Comment thread
andy-stark-redis marked this conversation as resolved.

{{- /* An explicit anchor overrides the slug entirely */ -}}
{{- if $explicitId -}}
Expand Down
Loading