feat: update shortcode usage#236
Conversation
Signed-off-by: Lenox Wiltshire <lenoxwiltshire@gmail.com>
📝 WalkthroughWalkthroughThe pull request updates Hugo shortcodes for parameterized CSV permission tables, stored lab content, styled markdown, SVG resource lookup, and Swagger UI rendering. It adds configurable resource resolution, validation, role discovery, and page-level asset initialization. ChangesShortcode rendering and resource resolution
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Reader
participant SwaggerUIShortcode
participant HugoResources
participant Browser
Reader->>SwaggerUIShortcode: provide OpenAPI src and options
SwaggerUIShortcode->>HugoResources: resolve page bundle or asset resource
HugoResources-->>SwaggerUIShortcode: return specification URL
SwaggerUIShortcode->>Browser: load Swagger UI assets once per page
SwaggerUIShortcode->>Browser: initialize SwaggerUIBundle
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
hi @banana-three-join , what I checked:
I couldn’t really dig into svg, csvtable / csvtable-roles, lab-outro, or swaggerui-api here. Most of those examples in digitalocean-academy only document the shortcodes instead of actually calling them, and this repo doesn’t have a CSV fixture or a lab-outro example. The swagger page also uses Docsy’s swaggerui, not the theme’s swaggerui-api. overall, no issues for what digitalocean academy exercises. |
Signed-off-by: Lenox Wiltshire <lenoxwiltshire@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (2)
layouts/shortcodes/csvtable.html (2)
63-66: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winNo validation that Function/Feature columns exist.
The doc comment states the CSV is expected to have
FunctionandFeaturecolumns, but unlikecsvtable-roles.html(whicherrorfs when either is missing), this template silently omits the "Permission"/"Description" header and cell rendering if they're absent. Consider mirroring the sibling shortcode's explicit check to fail fast on malformed input, consistent with the PR's goal of surfacing missing/invalid inputs at build time.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@layouts/shortcodes/csvtable.html` around lines 63 - 66, Add explicit validation in the csvtable shortcode to require both “Function” and “Feature” columns before rendering, mirroring the checks in csvtable-roles.html and using errorf to fail the build when either is missing; preserve the existing header and cell rendering for valid CSV input.
68-82: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winUnmapped column prefixes silently fall back to
"roles"with no warning.Unlike
csvtable-roles.html's equivalent block (whichwarnfs and guesses a URL when a role name doesn't match a known prefix), this file leaves$urlPathat its default"roles"value silently. See consolidated comment for the full cross-file finding.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@layouts/shortcodes/csvtable.html` around lines 68 - 82, Update the column-link logic in the csvtable template so an unrecognized $sectionName prefix emits a warning and applies the same URL-guessing behavior as the equivalent csvtable-roles.html block, instead of silently retaining the default "roles" path. Preserve the existing mappings for workspace, team, org, provider, and user prefixes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@layouts/shortcodes/chapterstyle.html`:
- Around line 4-8: Update both shortcode examples in the chapterstyle
documentation to invoke the defined chapterstyle shortcode instead of chapter,
preserving their existing content and style attributes.
In `@layouts/shortcodes/csvtable-roles.html`:
- Around line 72-83: The prefix mapping chain in the csvtable roles shortcode is
missing the user case. Add a hasPrefix $sectionName "user" branch in the same
chain as the workspace, team, org, and provider mappings, assigning the explicit
"roles/user-role" path so user-prefixed sections avoid the fallback URL and
warning.
In `@layouts/shortcodes/csvtable.html`:
- Around line 46-54: Update the header, link-header, and body rendering
conditions around the category column to exclude column 0 by position, matching
the positional category extraction in the unique-category loop. Preserve the
existing named-header exclusion as needed, but ensure the first CSV column is
never rendered as a normal data column or roles link regardless of its header
text.
In `@layouts/shortcodes/lab-intro.html`:
- Line 11: Update the lab intro consumer in layouts/lab/content.html to read
“lab_intro” from Page.Store, matching the write in the lab-intro shortcode. Also
update archetypes/lab.md to include the lab-outro shortcode so generated lab
pages render the complete intro/outro structure, or retain a compatible
Page.Scratch write if the consumer migration is not made.
In `@layouts/shortcodes/swaggerui-api.html`:
- Around line 18-20: Secure the Swagger UI assets referenced by the shortcode’s
$base URL: either vendor the CSS/JS locally, or constrain the version used by
$version to approved versions and add matching integrity and crossorigin
attributes to every jsDelivr asset load. Reuse the existing SRI approach from
the Swagger layout and reject or safely default unsupported version values.
- Around line 4-7: Update all shortcode examples in the usage documentation to
invoke the defined `swaggerui-api` shortcode instead of `swaggerui`, preserving
each existing src value.
---
Nitpick comments:
In `@layouts/shortcodes/csvtable.html`:
- Around line 63-66: Add explicit validation in the csvtable shortcode to
require both “Function” and “Feature” columns before rendering, mirroring the
checks in csvtable-roles.html and using errorf to fail the build when either is
missing; preserve the existing header and cell rendering for valid CSV input.
- Around line 68-82: Update the column-link logic in the csvtable template so an
unrecognized $sectionName prefix emits a warning and applies the same
URL-guessing behavior as the equivalent csvtable-roles.html block, instead of
silently retaining the default "roles" path. Preserve the existing mappings for
workspace, team, org, provider, and user prefixes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: fb3d9b74-6682-45b3-bdd4-71c374d2286a
📒 Files selected for processing (7)
layouts/shortcodes/chapterstyle.htmllayouts/shortcodes/csvtable-roles.htmllayouts/shortcodes/csvtable.htmllayouts/shortcodes/lab-intro.htmllayouts/shortcodes/lab-outro.htmllayouts/shortcodes/svg.htmllayouts/shortcodes/swaggerui-api.html
| {{< chapter >}} | ||
| Your markdown content goes here. | ||
| {{< /chapter >}} | ||
|
|
||
| {{< chapter style="columns: 2; text-align: justify;" >}}...{{< /chapter >}} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== File listing ==\n'
git ls-files 'layouts/shortcodes/*' | sed -n '1,120p'
printf '\n== chapterstyle shortcode file ==\n'
wc -l layouts/shortcodes/chapterstyle.html
cat -n layouts/shortcodes/chapterstyle.html
printf '\n== Search for shortcode references ==\n'
rg -n --hidden --glob '!**/.git/**' '\{\{<\s*(chapterstyle|chapter)\b' .Repository: layer5io/academy-theme
Length of output: 2333
Use chapterstyle in the examples. layouts/shortcodes/chapterstyle.html defines the chapterstyle shortcode, and there’s no chapter.html alias in this repo, so the current usage examples will fail for readers copying them.
🧰 Tools
🪛 HTMLHint (1.9.2)
[error] 4-4: Special characters must be escaped : [ < ].
(spec-char-escape)
[error] 4-4: Special characters must be escaped : [ > ].
(spec-char-escape)
[error] 6-6: Special characters must be escaped : [ < ].
(spec-char-escape)
[error] 6-6: Special characters must be escaped : [ > ].
(spec-char-escape)
[error] 8-8: Special characters must be escaped : [ < ].
(spec-char-escape)
[error] 8-8: Special characters must be escaped : [ > ].
(spec-char-escape)
[error] 8-8: Special characters must be escaped : [ < ].
(spec-char-escape)
[error] 8-8: Special characters must be escaped : [ > ].
(spec-char-escape)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@layouts/shortcodes/chapterstyle.html` around lines 4 - 8, Update both
shortcode examples in the chapterstyle documentation to invoke the defined
chapterstyle shortcode instead of chapter, preserving their existing content and
style attributes.
| {{ if hasPrefix $sectionName "workspace" }} | ||
| {{ $urlPath = "roles/workspace-roles" }} | ||
| {{ else if hasPrefix $sectionName "team" }} | ||
| {{ $urlPath = "roles/team-roles" }} | ||
| {{ else if hasPrefix $sectionName "org" }} | ||
| {{ $urlPath = "roles/organization-roles" }} | ||
| {{ else if hasPrefix $sectionName "provider" }} | ||
| {{ $urlPath = "roles/#provider-admin-role" }} | ||
| {{ else }} | ||
| {{ $urlPath = print "roles/" (urlize $sectionName) }} | ||
| {{ warnf "csvtable-roles: no URL mapping for role %q, guessing %q. See %s" $role.name $urlPath $.Position }} | ||
| {{ end }} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Missing "user" prefix mapping present in the sibling csvtable.html.
csvtable.html's equivalent prefix chain also maps hasPrefix $sectionName "user" → "roles/user-role"; this block omits that case, so a role column named e.g. "User..." falls into the generic guess+warnf branch here but gets the correct explicit link in csvtable.html. See consolidated comment for the full cross-file finding.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@layouts/shortcodes/csvtable-roles.html` around lines 72 - 83, The prefix
mapping chain in the csvtable roles shortcode is missing the user case. Add a
hasPrefix $sectionName "user" branch in the same chain as the workspace, team,
org, and provider mappings, assigning the explicit "roles/user-role" path so
user-prefixed sections avoid the fallback URL and warning.
| {{ $uniqueCategories := slice }} | ||
| {{ range $i, $row := $data }} | ||
| {{ if gt $i $headerRow }} | ||
| {{ $category := trim (index $row 0) " " }} | ||
| {{ if not (in $uniqueCategories $category) }} | ||
| {{ $uniqueCategories = $uniqueCategories | append $category }} | ||
| {{ end }} | ||
| {{ end }} | ||
| {{ end }} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Category exclusion relies on exact header text, not position.
$category is derived positionally from column 0 (Line 49), but Line 22/62/94 hide the category column from rendering only when the header cell literally equals "Category". If the CSV's first column header is spelled differently (case, wording, localization), the category value will additionally render as a normal data column (with a spurious "roles" link header), duplicating the <h2> grouping.
🐛 Proposed fix: exclude column 0 by position instead of relying solely on name
- {{ range $col := $header }}
- {{ if not (in $excludedColumns $col) }}
+ {{ range $idx, $col := $header }}
+ {{ if and (ne $idx 0) (not (in $excludedColumns $col)) }}and similarly in the body loop:
- {{ range $j, $cell := $row }}
- {{ $cell = trim $cell " " }}
- {{ $col := index $header $j }}
- {{ if not (in $excludedColumns $col) }}
+ {{ range $j, $cell := $row }}
+ {{ $cell = trim $cell " " }}
+ {{ $col := index $header $j }}
+ {{ if and (ne $j 0) (not (in $excludedColumns $col)) }}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@layouts/shortcodes/csvtable.html` around lines 46 - 54, Update the header,
link-header, and body rendering conditions around the category column to exclude
column 0 by position, matching the positional category extraction in the
unique-category loop. Preserve the existing named-header exclusion as needed,
but ensure the first CSV column is never rendered as a normal data column or
roles link regardless of its header text.
| Output is emitted by {{< lab-outro >}}, which must appear later in the | ||
| same file. | ||
| */}} | ||
| {{- .Page.Store.Set "lab_intro" .Inner -}} No newline at end of file |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== files ==\n'
git ls-files 'layouts/shortcodes/lab-intro.html' 'layouts/lab/content.html' 'archetypes/lab.md'
printf '\n== layouts/shortcodes/lab-intro.html ==\n'
cat -n layouts/shortcodes/lab-intro.html
printf '\n== layouts/lab/content.html ==\n'
cat -n layouts/lab/content.html
printf '\n== archetypes/lab.md ==\n'
cat -n archetypes/lab.md
printf '\n== search for lab_intro / lab_outro usage ==\n'
rg -n '"lab_intro"|"lab_outro"|Page\.Scratch|Page\.Store|lab-intro|lab-outro' layouts archetypesRepository: layer5io/academy-theme
Length of output: 6571
🏁 Script executed:
#!/bin/bash
set -euo pipefail
cat -n layouts/shortcodes/lab-outro.htmlRepository: layer5io/academy-theme
Length of output: 544
Migrate the lab intro consumers to Page.Store. layouts/lab/content.html still reads Page.Scratch.Get "lab_intro", while lab-intro now only writes to Page.Store; archetypes/lab.md also omits lab-outro, so new lab pages won’t render the intro unless these callers are updated together or the legacy Scratch write is kept.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@layouts/shortcodes/lab-intro.html` at line 11, Update the lab intro consumer
in layouts/lab/content.html to read “lab_intro” from Page.Store, matching the
write in the lab-intro shortcode. Also update archetypes/lab.md to include the
lab-outro shortcode so generated lab pages render the complete intro/outro
structure, or retain a compatible Page.Scratch write if the consumer migration
is not made.
| Usage: | ||
| {{< swaggerui src="example.json" >}} | ||
| {{< swaggerui src="/data/openapi.json" >}} | ||
| {{< swaggerui src="https://petstore3.swagger.io/api/v3/openapi.json" >}} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
set -e
printf 'Files:\n'
git ls-files | rg '(^|/)(swaggerui|swagger|shortcodes).*\.(html|md)$|(^|/)layouts/shortcodes/'
printf '\nReferences:\n'
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' 'swaggerui-api|swaggerui' .Repository: layer5io/academy-theme
Length of output: 2180
🏁 Script executed:
set -e
echo 'Shortcode files:'
fd -a 'swaggerui*' layouts content . || true
echo
echo 'Inspect shortcode directory:'
find layouts/shortcodes -maxdepth 1 -type f | sort | sed -n '1,120p'Repository: layer5io/academy-theme
Length of output: 910
🏁 Script executed:
set -e
python3 - <<'PY'
from pathlib import Path
root = Path('.')
hits = []
for p in root.rglob('*'):
if p.is_file() and p.suffix in {'.html', '.md', '.txt'}:
text = p.read_text(errors='ignore')
if 'swaggerui-api' in text or 'swaggerui' in text:
hits.append((str(p), text.count('swaggerui-api'), text.count('swaggerui')))
for item in hits[:200]:
print(item[0], item[1], item[2])
PYRepository: layer5io/academy-theme
Length of output: 202
Use swaggerui-api in the examples. This shortcode is defined as swaggerui-api, so {{< swaggerui ... >}} will not resolve unless an alias is added.
🧰 Tools
🪛 HTMLHint (1.9.2)
[error] 5-5: Special characters must be escaped : [ < ].
(spec-char-escape)
[error] 5-5: Special characters must be escaped : [ > ].
(spec-char-escape)
[error] 6-6: Special characters must be escaped : [ < ].
(spec-char-escape)
[error] 6-6: Special characters must be escaped : [ > ].
(spec-char-escape)
[error] 7-7: Special characters must be escaped : [ < ].
(spec-char-escape)
[error] 7-7: Special characters must be escaped : [ > ].
(spec-char-escape)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@layouts/shortcodes/swaggerui-api.html` around lines 4 - 7, Update all
shortcode examples in the usage documentation to invoke the defined
`swaggerui-api` shortcode instead of `swaggerui`, preserving each existing src
value.
| {{- $version := .Get "version" | default "5.17.14" -}} | ||
| {{- $deepLinking := eq (.Get "deepLinking" | default "false") "true" -}} | ||
| {{- $base := printf "https://cdn.jsdelivr.net/npm/swagger-ui-dist@%s" $version -}} |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== File outline: layouts/shortcodes/swaggerui-api.html ==\n'
ast-grep outline layouts/shortcodes/swaggerui-api.html --view expanded || true
printf '\n== Relevant search: swagger-ui-dist / integrity / crossorigin ==\n'
rg -n --hidden -S 'swagger-ui-dist|integrity=|crossorigin=|Swagger' layouts . || true
printf '\n== File contents: layouts/shortcodes/swaggerui-api.html ==\n'
cat -n layouts/shortcodes/swaggerui-api.html
printf '\n== Candidate related files (names) ==\n'
fd -a 'swagger.*(html|htm)$|Swagger.*(html|htm)$' layouts . || trueRepository: layer5io/academy-theme
Length of output: 7469
Add SRI or local assets for the Swagger UI CDN files. layouts/shortcodes/swaggerui-api.html:39-40 loads executable CSS/JS from jsDelivr without integrity/crossorigin, while layouts/swagger/baseof.html already uses SRI. Either vendor the assets locally, or restrict version to a small known-safe set with matching integrity values.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@layouts/shortcodes/swaggerui-api.html` around lines 18 - 20, Secure the
Swagger UI assets referenced by the shortcode’s $base URL: either vendor the
CSS/JS locally, or constrain the version used by $version to approved versions
and add matching integrity and crossorigin attributes to every jsDelivr asset
load. Reuse the existing SRI approach from the Swagger layout and reject or
safely default unsupported version values.
Summary
Shortcodes that read files were hardcoded to a single location.
All of them now resolve
srcagainst the page bundle first, thenassets/,so colocated assets work. Each also gained a usage comment and a build-time
error instead of failing silently.
svg.Resources→.Page.Resources. In a shortcode.is the shortcode,not the page, so page-bundle lookup never worked.
$r+if not $rreassignment into a singlewith or (...) (...)/elsechain.srcparam for an explicit path, taking precedence overname.warnfs with both attempted paths instead of emitting anHTML comment.
namenorsrcbeing passed.chapterstylestylenever rendering: Go's autoescaper voids unparseable CSSattributes as
ZgotmplZ. AddedsafeCSS..Innerrendering inline:RenderStringnow gets(dict "display" "block")so multi-paragraph content is wrapped in<p>.| default "".lab-intro/lab-outro(new)lab-introstores raw.Inner; rendering moved to output time.lab-outroshortcode renders it, replacing the manualScratch.Getcall at each site..Scratch→.Store.lab-outroruns without a precedinglab-intro.csvtable(one table per category)srcparam — resolves page bundle →assets/→ project root.Defaults to
static/data/csv/keys-backup.csv, so existing bare call sitesare unaffected.
keys-backup.csvhas its headerat row 0, so the first data row was rendering as the header. New
headerRowparam, default 0.
range (3–9), which had to stay manually in sync with the exclusion list.
$headerMap, an HTML comment shipping to output, ano-op
elsebranch, and an unreachable "No data available" tail.csvtable-roles(one table per role)srcparam andheaderRowfix. The wrong row broke the build here:it scanned a data row for Function/Feature and errored out.
gt $i 3bound silently dropped Workspace Admin — that role never got a table.
$hasAccess/$functionValue/$featureValueand the$stopAddingCategoriesflag; hoisted the Function/Feature lookup out of theper-row loop, which was rescanning the header for every row of every table.
print "roles/" $sectionName | urlize, whichslugified the slash along with the name.
guesses a slug and would otherwise ship a silent 404.
swaggerui-apiswagger-ui.cssandswagger-ui-bundle.jsfrom CDN itself, so nofront matter type is required. Emitted once per page via
.Page.Store.srcresolves: absolute URLs and root-relative paths pass through;anything else resolves against the page bundle, then
assets/..Ordinalgives each instance a uniquedom_id.deepLinkingoff by default (multiple viewers on one page collide over theURL fragment), exposed as an opt-in param.
StandaloneLayoutand its preset — that's the spec-URL topbar,which Docsy hides with CSS anyway.
swagger-ui-distversion pinned, overridable per call.Not included
iframe— page-bundled.htmlis classified by Hugo as a page resource withno permalink, so it needs either a site-config change or a republish step.
Deferred.
Notes for Reviewers
Signed commits
Summary by CodeRabbit
New Features
Improvements