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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ public/
_import/
docs/superpowers/

# synced from node_modules/medium-zoom by scripts/sync-vendor-assets.js
# (see the preantora/preantora-local npm scripts)
ui/supplemental/js/vendor/

# macOS and IDEs
.DS_Store
.vscode/
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ antora-extensions/ comp-version, latest/next-alias, sitemap-cleanup, globa
asciidoc-extensions/ tabs, remote-include
global-attributes.yml site-wide AsciiDoc attributes (local)
ui/supplemental/ branding + Pagefind modal search on the stock UI
ui/supplemental/js/vendor/ gitignored; synced from node_modules by scripts/sync-vendor-assets.js
content/<product>/<ver>/ each version is a folder with its own antora.yml
sync/ retired upstream-mirror tooling, kept as provenance
scripts/ build-time helpers (npm `pre*` hooks), e.g. sync-vendor-assets.js
.github/workflows/ci.yml build → pagefind → deploy to GitHub Pages
```

Expand Down
18 changes: 18 additions & 0 deletions extension-tests/static-files.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,21 @@ test('root static files are not published under the UI output dir', (t) => {
// ui.yml is consumed by the UI loader; it must never be published itself.
assert.ok(!fs.existsSync(path.join(PUBLIC, 'assets', 'ui.yml')), 'ui.yml leaked into the build output')
})

test('the medium-zoom vendor bundle synced from node_modules is published', (t) => {
if (!fs.existsSync(path.join(PUBLIC, 'index.html'))) {
t.skip('public/ not built (run `npm run antora` to enable)')
return
}
// ui/supplemental/js/vendor/ is gitignored and repopulated from node_modules by
// scripts/sync-vendor-assets.js (wired as preantora/preantora-local). Every
// page still references js/vendor/medium-zoom.min.js regardless, so a build
// that skips that step (e.g. `npx antora` directly) publishes green with a
// 404'ing <script> and dead image zoom -- this guard fails loudly instead.
for (const name of ['medium-zoom.min.js', 'LICENSE-medium-zoom.txt']) {
assert.ok(
fs.existsSync(path.join(PUBLIC, 'assets/js/vendor', name)),
`assets/js/vendor/${name} is missing -- did the build run through \`npm run antora\` (not \`npx antora\` directly), so preantora's sync-vendor-assets.js had a chance to run?`
)
}
})
9 changes: 8 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"homepage": "https://github.com/owncloud/docs.owncloud.com#readme",
"license": "AGPL-3.0-or-later",
"scripts": {
"preantora": "node scripts/sync-vendor-assets.js",
"antora": "antora --stacktrace site.yml",
"preantora-local": "node scripts/sync-vendor-assets.js",
"antora-local": "antora --stacktrace --url http://localhost:8080 site.yml",
"pagefind": "pagefind --site public",
"build": "npm run antora && npm run pagefind",
Expand All @@ -15,7 +17,8 @@
"antora": "^3.2.0",
"asciidoctor": "^4.0.11",
"asciidoctor-kroki": "^1.0.1",
"js-yaml": "^5.4.1"
"js-yaml": "^5.4.1",
"medium-zoom": "^1.1.0"
},
"devDependencies": {
"@sntke/antora-mermaid-extension": "^0.0.13",
Expand Down
34 changes: 34 additions & 0 deletions scripts/sync-vendor-assets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use strict'

// Copies prebuilt browser bundles out of node_modules into the Antora UI
// supplemental tree. ui/supplemental is layered onto the stock UI bundle as
// plain files (site.yml ui.supplemental_files) -- there is no bundler step of
// our own -- so real npm dependencies (tracked in package.json/package-lock.json,
// and by Dependabot) still need their browser build placed on disk before
// Antora runs. Wired up as `preantora`/`preantora-local` in package.json.
//
// To vendor another package's browser build the same way, add an entry below
// rather than writing a new script.
const VENDOR_FILES = [
{ package: 'medium-zoom', src: 'dist/medium-zoom.min.js', dest: 'js/vendor/medium-zoom.min.js' },
{ package: 'medium-zoom', src: 'LICENSE', dest: 'js/vendor/LICENSE-medium-zoom.txt' },
]

const fs = require('node:fs')
const path = require('node:path')

const ROOT = path.join(__dirname, '..')
const VENDOR_DIR = path.join(ROOT, 'ui/supplemental/js/vendor')

// Wiped and repopulated on every run (this directory only ever holds files this
// script manages -- see the .gitignore entry), so dropping an entry from
// VENDOR_FILES actually removes the stale file instead of leaving it on disk
// for any local checkout or reused CI workspace that copied it in previously.
fs.rmSync(VENDOR_DIR, { recursive: true, force: true })

for (const { package: pkg, src, dest } of VENDOR_FILES) {
const from = path.join(ROOT, 'node_modules', pkg, src)
const to = path.join(ROOT, 'ui/supplemental', dest)
fs.mkdirSync(path.dirname(to), { recursive: true })
fs.copyFileSync(from, to)
}
21 changes: 21 additions & 0 deletions ui/supplemental/css/medium-zoom.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* medium-zoom (js/vendor/medium-zoom.min.js) injects its own stylesheet for the
* overlay and the zoom transition, but that stylesheet sets no stacking order.
* The stock Antora default UI goes up to z-index 4 (navbar, toolbar), so without
* this the navbar would sit on top of the zoomed image and its backdrop.
*
* `body >` on the overlay bumps our specificity above the library's own
* `.medium-zoom-overlay` rule, so we stay correct even if a future release adds
* a z-index there (it injects its <style> after this stylesheet, so a plain
* class-vs-class tie would otherwise go to source order, i.e. to them).
*
* `--opened` (not the bare `medium-zoom-image` class) targets only the zoomed
* clone medium-zoom appends to <body>: the bare class stays on every bound
* image for as long as it's attached, so using it here would promote every
* doc image on the page to z-index 1000 the moment anything gives one
* `position: relative/absolute/sticky` (a caption overlay, a figure badge).
*/
body > .medium-zoom-overlay,
img.medium-zoom-image--opened {
z-index: 1000;
}
19 changes: 19 additions & 0 deletions ui/supplemental/js/medium-zoom-init.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Click-to-zoom for images, restoring the behavior the retired custom UI
* (docs-ui) provided via its webpack-bundled `js/vendor/medium-zoom.js`.
*
* Binds medium-zoom to every image Asciidoctor emits:
* span.image img -- inline images (`image:file[]`)
* div.imageblock img -- block images (`image::file[]`), including svg
* With that, no `role` or attribute is needed in the page source: all images
* are zoomable.
*
* Loaded with `defer` after js/vendor/medium-zoom.min.js so the global is in
* place -- deferred external scripts execute in document order.
*/
;(function () {
'use strict'

if (typeof window.mediumZoom !== 'function') return
window.mediumZoom('span.image img, div.imageblock img', { background: '#fff', margin: 10 })
})()
5 changes: 5 additions & 0 deletions ui/supplemental/partials/footer-scripts.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@
{{!-- Companion behavior for the AsciiDoc tabs extension (asciidoc-extensions/tabs.js):
removes the is-loading fallback and wires tab switching. --}}
<script src="{{{uiRootPath}}}/js/tabs.js"></script>
{{!-- Click-to-zoom for images. `defer` on both (not `async`) because the init
script needs the global the vendored library defines, and deferred external
scripts run in document order. --}}
<script defer src="{{{uiRootPath}}}/js/vendor/medium-zoom.min.js"></script>
<script defer src="{{{uiRootPath}}}/js/medium-zoom-init.js"></script>
1 change: 1 addition & 0 deletions ui/supplemental/partials/head-styles.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
<link rel="stylesheet" href="{{{siteRootPath}}}/pagefind/pagefind-component-ui.css">
<link rel="stylesheet" href="{{{uiRootPath}}}/css/owncloud.css">
<link rel="stylesheet" href="{{{uiRootPath}}}/css/tabs.css">
<link rel="stylesheet" href="{{{uiRootPath}}}/css/medium-zoom.css">
Loading