Skip to content

Commit ba35a89

Browse files
authored
Merge pull request #1 from missing-elements/docs/pdfjs-viewer
Docs/pdfjs viewer
2 parents 1f6c20e + 695dca9 commit ba35a89

20 files changed

Lines changed: 3003 additions & 1 deletion

‎.github/dependabot.yml‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
version: 2
2+
updates:
3+
# The docs run the pdfjs-viewer version they describe, so new releases arrive as their own PR.
4+
- package-ecosystem: npm
5+
directory: /
6+
schedule:
7+
interval: daily
8+
groups:
9+
tooling:
10+
patterns: ["*"]
11+
exclude-patterns: ["@missing-elements/*"]
12+
- package-ecosystem: github-actions
13+
directory: /
14+
schedule:
15+
interval: monthly

‎.github/workflows/pages.yml‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Deploy to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
concurrency:
14+
group: pages
15+
cancel-in-progress: false
16+
17+
jobs:
18+
build:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v7
22+
- uses: pnpm/action-setup@v6
23+
- uses: actions/setup-node@v7
24+
with:
25+
node-version: 24
26+
cache: pnpm
27+
- run: pnpm install --frozen-lockfile
28+
- run: pnpm build
29+
- uses: actions/configure-pages@v6
30+
- uses: actions/upload-pages-artifact@v5
31+
with:
32+
path: _site
33+
34+
deploy:
35+
needs: build
36+
runs-on: ubuntu-latest
37+
environment:
38+
name: github-pages
39+
url: ${{ steps.deployment.outputs.page_url }}
40+
steps:
41+
- id: deployment
42+
uses: actions/deploy-pages@v5

‎.gitignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules/
2+
_site/
3+
.DS_Store

‎README.md‎

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,41 @@
1-
# missing-elements.github.io
1+
# missing-elements.github.io
2+
3+
Docs for the [missing-elements](https://github.com/missing-elements) web components, published at <https://missing-elements.github.io>.
4+
5+
| Path | Source |
6+
| --- | --- |
7+
| `/` | [src/index.njk](src/index.njk), project list in [src/_data/site.js](src/_data/site.js) |
8+
| `/pdfjs-viewer/` | [src/pdfjs-viewer/index.md](src/pdfjs-viewer/index.md) |
9+
10+
Built with [Eleventy](https://www.11ty.dev/). The pages ship no framework: the only client-side JavaScript is the theme toggle, code-block buttons and the live preview.
11+
12+
## Develop
13+
14+
```bash
15+
pnpm install
16+
pnpm dev # http://localhost:8080
17+
pnpm build # writes _site/
18+
```
19+
20+
Pushes to `main` deploy through [.github/workflows/pages.yml](.github/workflows/pages.yml).
21+
22+
## Editing the pdfjs-viewer docs
23+
24+
- **Prose:** [src/pdfjs-viewer/index.md](src/pdfjs-viewer/index.md). Headings `##` and `###` make up the table of contents.
25+
- **Attribute tables and playground controls:** [src/_data/pdfjsAttributes.js](src/_data/pdfjsAttributes.js).
26+
- **Version numbers:** read at build time from the installed `@missing-elements/pdfjs-viewer`. The docs serve that package's `dist/` as the live preview, so bumping the dependency updates both.
27+
28+
### Try buttons
29+
30+
Add `try` after the language of a code fence to give it a **▶ Try** button that applies the snippet to the preview:
31+
32+
````md
33+
```html try
34+
<pdfjs-viewer-element src="/file.pdf" zoom="page-width"></pdfjs-viewer-element>
35+
```
36+
````
37+
38+
- **HTML snippets** copy the attributes of their `<pdfjs-viewer-element>` onto the preview. `style`, `id`, `class` and the placeholder `src="/file.pdf"` are skipped.
39+
- **JavaScript snippets** run exactly as written. `document.querySelector('pdfjs-viewer-element')` returns the preview element.
40+
- Every Try button comes with a **Reset** button that puts the preview back to its defaults.
41+
- **`try=fresh`** replaces the preview with a new element first. Use it for settings that only apply when the viewer is built, such as `setViewerOptions` and the "before connect" attributes.

‎eleventy.config.js‎

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
2+
import attributes from "./src/_data/pdfjsAttributes.js";
3+
4+
const slugify = (text) =>
5+
text.toLowerCase().replace(/<[^>]+>/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
6+
7+
const escapeHtml = (text) =>
8+
String(text).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
9+
10+
export default function (eleventyConfig) {
11+
eleventyConfig.addPlugin(syntaxHighlight, { preAttributes: { tabindex: 0 } });
12+
13+
eleventyConfig.addPassthroughCopy("src/assets");
14+
eleventyConfig.addPassthroughCopy("src/pdfjs-viewer/samples");
15+
eleventyConfig.addPassthroughCopy("src/pdfjs-viewer/docs.js");
16+
// The docs run the exact package version they describe, served from this site.
17+
eleventyConfig.addPassthroughCopy({ "node_modules/@missing-elements/pdfjs-viewer/dist": "pdfjs-viewer/vendor" });
18+
19+
let markdown;
20+
eleventyConfig.amendLibrary("md", (md) => {
21+
markdown = md;
22+
23+
// Heading ids, so the table of contents and deep links work.
24+
md.core.ruler.push("heading_ids", (state) => {
25+
state.tokens.forEach((token, i) => {
26+
if (token.type === "heading_open" && !token.attrGet("id")) {
27+
token.attrSet("id", slugify(state.tokens[i + 1].content));
28+
}
29+
});
30+
});
31+
32+
// A fence flagged with `try` (```html try, ```js try, ```js try=fresh) gets a Try button
33+
// in the browser that applies the snippet to the preview viewer.
34+
const fence = md.renderer.rules.fence;
35+
md.renderer.rules.fence = (tokens, idx, options, env, self) => {
36+
const html = fence(tokens, idx, options, env, self);
37+
const flag = tokens[idx].info.split(/\s+/).slice(1).find((word) => word.startsWith("try"));
38+
if (!flag) return html;
39+
const mode = flag === "try=fresh" ? "fresh" : "apply";
40+
return `<div class="example" data-try="${mode}">${html}</div>\n`;
41+
};
42+
});
43+
44+
// h2/h3 headings of the rendered page, for the sidebar table of contents.
45+
eleventyConfig.addFilter("toc", (content) =>
46+
[...content.matchAll(/<h([23]) id="([^"]+)">(.*?)<\/h\1>/g)].map(([, level, id, text]) => ({
47+
level: Number(level),
48+
id,
49+
text: text.replace(/<[^>]+>/g, ""),
50+
}))
51+
);
52+
53+
const inline = (text) => markdown.renderInline(text);
54+
55+
const tableCaptions = {
56+
document: "Document and navigation attributes",
57+
interface: "Interface attributes",
58+
files: "Runtime file attributes",
59+
resources: "PDF.js resource attributes",
60+
};
61+
62+
eleventyConfig.addShortcode("attributeTable", (group) => {
63+
const rows = attributes
64+
.filter((attr) => attr.group === group)
65+
.map(
66+
(attr) => `<tr id="attr-${attr.name}">
67+
<th scope="row"><a href="#attr-${attr.name}"><code>${attr.name}</code></a></th>
68+
<td>${inline(attr.description)}</td>
69+
<td class="default">${attr.default ? inline(attr.default) : `<span class="muted"><span aria-hidden="true">—</span><span class="visually-hidden">None</span></span>`}</td>
70+
<td><span class="update update-${attr.update}">${{ live: "Live", load: "Next load", init: "Before connect", none: "No effect" }[attr.update]}</span></td>
71+
</tr>`
72+
)
73+
.join("");
74+
return `<div class="table-wrap"><table class="attributes"><caption class="visually-hidden">${tableCaptions[group]}</caption><thead><tr><th scope="col">Attribute</th><th scope="col">Description</th><th scope="col">Default</th><th scope="col">Updates</th></tr></thead><tbody>${rows}</tbody></table></div>`;
75+
});
76+
77+
eleventyConfig.addShortcode("playground", () => {
78+
const controls = attributes
79+
.filter((attr) => attr.playground)
80+
.map(({ name, playground: control }) => {
81+
const id = `pg-${name}`;
82+
let field;
83+
if (control.type === "select") {
84+
const options = control.options
85+
.map((option) => {
86+
const [value, label] = Array.isArray(option) ? option : [option, option || "(unset)"];
87+
return `<option value="${escapeHtml(value)}">${escapeHtml(label)}</option>`;
88+
})
89+
.join("");
90+
field = `<select id="${id}" data-attr="${name}">${options}</select>`;
91+
} else if (control.type === "checkbox") {
92+
field = `<input id="${id}" type="checkbox" data-attr="${name}" value="true">`;
93+
} else {
94+
field = `<input id="${id}" type="${control.type}" data-attr="${name}"${control.min ? ` min="${control.min}"` : ""} placeholder="${escapeHtml(control.placeholder ?? "")}" autocomplete="off">`;
95+
}
96+
return `<div class="control"><label for="${id}"><code>${name}</code></label>${field}</div>`;
97+
})
98+
.join("");
99+
return `<form class="playground" data-playground aria-label="Attribute playground"><p class="playground-hint">Each change applies to the live preview straight away.</p>${controls}</form>`;
100+
});
101+
102+
return {
103+
dir: { input: "src", output: "_site" },
104+
markdownTemplateEngine: "njk",
105+
htmlTemplateEngine: "njk",
106+
};
107+
}

‎package.json‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "missing-elements.github.io",
3+
"private": true,
4+
"type": "module",
5+
"packageManager": "pnpm@10.24.0",
6+
"scripts": {
7+
"dev": "eleventy --serve",
8+
"build": "eleventy"
9+
},
10+
"devDependencies": {
11+
"@11ty/eleventy": "3.1.7",
12+
"@11ty/eleventy-plugin-syntaxhighlight": "5.0.2"
13+
},
14+
"dependencies": {
15+
"@missing-elements/pdfjs-viewer": "4.3.0"
16+
}
17+
}

0 commit comments

Comments
 (0)