diff --git a/.gitignore b/.gitignore
index 3bed9a90..a6ebc2b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,13 +3,12 @@ node_modules
Thumbs.db
# Generated files
-*.html
-!examples/*.html
-api
-plugins
-components.json
-file-sizes.json
-_redirects
+.prism
+docs/plugins/*
+!docs/plugins/plugins.11tydata.js
+docs/components.json
+docs/file-sizes.json
+_site
# Cache
.cache
diff --git a/README.json b/README.json
deleted file mode 100644
index 4abebb76..00000000
--- a/README.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "layout": "home.njk",
- "resources": ["/plugins/keep-markup.js { type=module }", "/languages/bash.js { type=module }"]
-}
diff --git a/README.md b/README.md
deleted file mode 100644
index c53797ea..00000000
--- a/README.md
+++ /dev/null
@@ -1,304 +0,0 @@
-` (on its own) or `
-```
-
-or
-
-```html
-
-
-```
-
-## Usage with CDNs { #basic-usage-cdn }
-
-In combination with CDNs, we recommend using the [Autoloader plugin](plugins/autoloader) which automatically loads languages when necessary.
-
-The setup of the Autoloader, will look like the following. You can also add your own themes of course.
-
-
-
-Please note that links in the above code sample serve as placeholders. You have to replace them with valid links to the CDN of your choice.
-
-CDNs which provide PrismJS are e.g. [cdnjs](https://cdnjs.com/libraries/prism), [jsDelivr](https://www.jsdelivr.com/package/npm/prismjs), and [UNPKG](https://unpkg.com/browse/prismjs@1/).
-
-## Usage with Webpack, Browserify, & Other Bundlers { #basic-usage-bundlers }
-
-If you want to use Prism with a bundler, install Prism with `npm`:
-
-```bash
-$ npm install prismjs
-```
-
-You can then `import` into your bundle:
-
-```js
-import Prism from 'prismjs';
-```
-
-To make it easy to configure your Prism instance with only the languages and plugins you need, use the babel plugin, [babel-plugin-prismjs](https://github.com/mAAdhaTTah/babel-plugin-prismjs). This will allow you to load the minimum number of languages and plugins to satisfy your needs. See that plugin's documentation for configuration details.
-
-## Usage with Node { #basic-usage-node }
-
-If you want to use Prism on the server or through the command line, Prism can be used with Node.js as well. This might be useful if you're trying to generate static HTML pages with highlighted code for environments that don't support browser-side JS, like [AMP pages](https://www.ampproject.org/).
-
-Example:
-
-```js
-const Prism = require('prismjs');
-
-// The code snippet you want to highlight, as a string
-const code = `var data = 1;`;
-
-// Returns a highlighted HTML string
-const html = Prism.highlight(code, Prism.languages.javascript, 'javascript');
-```
-
-Requiring `prismjs` will load the default languages: `markup`, `css`, `clike` and `javascript`. You can load more languages with the `loadLanguages()`{ .language-javascript } utility, which will automatically handle any required dependencies.
-
-Example:
-
-```js
-const Prism = require('prismjs');
-const loadLanguages = require('prismjs/components/');
-loadLanguages(['haml']);
-
-// The code snippet you want to highlight, as a string
-const code = `= ['hi', 'there', 'reader!'].join " "`;
-
-// Returns a highlighted HTML string
-const html = Prism.highlight(code, Prism.languages.haml, 'haml');
-```
-
-**Note**: Do _not_ use `loadLanguages()`{ .language-javascript } with Webpack or another bundler, as this will cause Webpack to include all languages and plugins. Use the babel plugin described above.
-
-**Note**: `loadLanguages()`{ .language-javascript } will ignore unknown languages and log warning messages to the console. You can prevent the warnings by setting `loadLanguages.silent = true`{ .language-javascript }.
-
-<!DOCTYPE html>
-<html>
-<head>
- ...
- <link href="https://{{cdn}}/prismjs@v1.x/themes/prism.css" rel="stylesheet" />
-</head>
-<body>
- ...
- <script src="https://{{cdn}}/prismjs@v1.x/components/prism-core.min.js"></script>
-<script src="https://{{cdn}}/prismjs@v1.x/plugins/autoloader/prism-autoloader.min.js"></script>
-</body>
-</html>
- {% for id, language in languages -%}
-
-
-Couldn’t find the language you were looking for? [Request it](https://github.com/PrismJS/prism/issues)!
-
-{{ alias }}{{ ", " if not loop.last }}
- {%- endfor %}
-
- {% for plugin in collections.plugin -%}
- {%- set meta = plugin.data -%}
-
-
-No assembly required to use them. Just select them in the [download](download.html) page.
-
-It’s very easy to [write your own Prism plugins](extending.html#writing-plugins). Did you write a plugin for Prism that you want added to this list? [Send a pull request](https://github.com/PrismJS/plugins/)!
-
-` or `` Tag to Entities to Display Raw Code with PrismJS](https://websitebeaver.com/escape-html-inside-code-or-pre-tag-to-entities-to-display-raw-code-with-prismjs)
-- [Adding a Syntax Highlighter Shortcode Using Prism.js | WPTuts+](http://wp.tutsplus.com/tutorials/plugins/adding-a-syntax-highlighter-shortcode-using-prism-js/)
-- [Implement PrismJs Syntax Highlighting to your Blogger/BlogSpot](https://www.stramaxon.com/2012/07/prism-syntax-highlighter-for-blogger.html)
-- [How To Re-Run Prism.js On AJAX Content](https://schier.co/blog/2013/01/07/how-to-re-run-prismjs-on-ajax-content.html)
-- [Highlight your code syntax with Prism.js](https://www.semisedlak.com/highlight-your-code-syntax-with-prismjs)
-- [A code snippet content element powered by Prism.js for TYPO3 CMS](https://usetypo3.com/fs-code-snippet.html)
-
-- [Code syntax highlighting in Gutenberg, WordPress block editor](https://mkaz.blog/wordpress/code-syntax-highlighting-in-gutenberg/)
-- [Code Highlighting with Prism.js in Drupal](https://karlkaufmann.com/writing/technotes/code-highlighting-prism-drupal)
-- [Code highlighting in React using Prism.js](https://betterstack.dev/blog/code-highlighting-in-react-using-prismjs/)
-
-- [PrismJS Tutorial | Implement Prism in HTML and React](https://itsmycode.com/prismjs-tutorial/)
-- Code syntax highlighting in Pug with [:highlight](https://webdiscus.github.io/pug-loader/pug-filters/highlight.html) and [:markdown](https://webdiscus.github.io/pug-loader/pug-filters/markdown.html) filters using [pug-loader](https://github.com/webdiscus/pug-loader) and Prism.js
-
-Please note that the tutorials listed here are not verified to contain correct information. Read at your risk and always check the official documentation here if something doesn’t work. 🙂
-
-Have you written a tutorial about Prism that’s not already included here? Send a pull request!
-
-
, not the inner
- md.renderer.rules.fence = function (tokens, idx, options, env, slf) {
- let token = tokens[idx];
- let lang = token.info ? `class="language-${token.info}"` : "";
- let content = md.utils.escapeHtml(token.content).trim();
- return `${content}
`;
- };
- });
-
- config.addFilter("md", function (content) {
- if (typeof content !== "string") {
- return content;
- }
-
- let ret = mdLib.renderInline(content);
- let safeFilter = this.env?.filters?.safe;
- return safeFilter ? safeFilter(ret) : ret;
- });
-
- config.addPairedShortcode("md", content => {
- if (typeof content !== "string") {
- if (content instanceof String) {
- content = content + "";
- }
- else {
- return content;
- }
- }
-
- return mdLib.render(content);
- });
-
- config.addPlugin(pluginTOC, {
- tags: ["h1", "h2", "h3"],
- ul: true,
- });
-
- // Don't ignore the folders that are gitignored (plugins, examples, themes, etc.)
- config.setUseGitIgnore(false);
-
- return {
- markdownTemplateEngine: "njk",
- templateFormats: ["md", "njk"],
- dir: {
- layouts: "_layouts",
- output: ".",
- },
- };
-};
diff --git a/_build/filters.js b/_build/filters.js
index 5681b3f0..0be06e01 100644
--- a/_build/filters.js
+++ b/_build/filters.js
@@ -1,23 +1,5 @@
-import * as path from "path";
-
-export function relative (page) {
- if (!page.url) {
- return "";
- }
-
- let pagePath = page.url.replace(/[^/]+$/, "");
- let ret = path.relative(pagePath, "/");
-
- return ret || ".";
-}
-
-export function back_to_top (content) {
- // Add “↑ Back to top” at the end of each ``
- return content.replace(/<\/section>/g, ` `);
-}
-
export function pretty_size (size) {
- return Math.round(100 * size / 1024) / 100 + "KB";
+ return Math.round((100 * size) / 1024) / 100 + "KB";
}
export function parse_resources (resources = []) {
diff --git a/_build/postinstall.mjs b/_build/postinstall.mjs
index b0933cd1..b4733f3e 100644
--- a/_build/postinstall.mjs
+++ b/_build/postinstall.mjs
@@ -5,8 +5,10 @@ import { execSync } from "child_process";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
-const root = path.resolve(__dirname, "../node_modules");
-const prismPath = path.join(root, "prismjs");
+// Not node_modules/prismjs: markdown-it-prism, which highlights the docs, resolves the real
+// `prismjs` package from there, and it needs v1
+const root = path.resolve(__dirname, "..");
+const prismPath = path.join(root, ".prism");
let sourcePath, destPath;
@@ -14,7 +16,7 @@ let sourcePath, destPath;
console.log("[postinstall] Cloning Prism...");
// Ensure we work with a fresh copy
await fs.rm(prismPath, { recursive: true, force: true });
-execSync("git clone https://github.com/PrismJS/prism.git prismjs", {
+execSync("git clone https://github.com/PrismJS/prism.git .prism", {
cwd: root,
stdio: "inherit",
});
@@ -33,7 +35,7 @@ execSync("npm run build", {
// --- Working with plugins ---
sourcePath = path.join(prismPath, "src/plugins");
-destPath = path.resolve(__dirname, "../plugins");
+destPath = path.resolve(__dirname, "../docs/plugins");
async function copy () {
// We need { recursive: true } so the script doesn't fail if the folder already exists
@@ -71,18 +73,9 @@ catch (error) {
console.error(`[postinstall] Failed to copy Prism plugins docs: ${error.message}`);
}
-// Create plugins.json in the plugins folder with global data
-console.log("[postinstall] Creating plugins.json...");
-let json = {
- permalink: "{{ page.filePathStem.replace('README', '/index') }}.html",
- tags: ["plugin"],
-};
-
-await fs.writeFile(path.join(destPath, "plugins.json"), JSON.stringify(json, null, "\t"));
-
// --- Copying other files (components.json, file-sizes.json, etc.) ---
sourcePath = path.join(prismPath, "dist");
-destPath = path.resolve(__dirname, "..");
+destPath = path.resolve(__dirname, "../docs");
let filenames = ["components.json", "file-sizes.json"];
for (let file of filenames) {
diff --git a/_data/eleventyComputed.js b/_data/eleventyComputed.js
deleted file mode 100644
index 1c8cfd26..00000000
--- a/_data/eleventyComputed.js
+++ /dev/null
@@ -1,70 +0,0 @@
-export default {
- components (data) {
- return { ...data.components };
- },
- themes (data) {
- let themes = { ...data.components.themes };
- delete themes.meta;
- return themes;
- },
- languages (data) {
- let languages = { ...data.components.languages };
- delete languages.meta;
-
- for (let id in languages) {
- let ret = [id];
- let alias = Object.keys(languages[id].aliasTitles ?? {});
- if (alias) {
- ret = ret.concat(Array.isArray(alias) ? alias : [alias]);
- }
- languages[id].alias = ret;
- }
-
- return languages;
- },
- // Plugin id
- id (data) {
- let parts = data.page.inputPath.slice(2).split("/");
- if (parts[0] === "plugins") {
- // Folder name ↔ plugin id
- return parts[1];
- }
- },
- title (data) {
- if (data.title) {
- return data.title;
- }
-
- let path = data.page.inputPath;
- path = path.slice(2);
-
- let title = path.replace(".md", "");
- if (title === "README") {
- return;
- }
-
- title = title.replace(/-/g, " ");
-
- return title[0].toUpperCase() + title.slice(1);
- },
- resources (data) {
- let { id, resources = [] } = data;
- let ret = [];
-
- resources = Array.isArray(resources) ? resources : [resources];
- ret.push(...resources);
-
- if (!id) {
- return ret;
- }
-
- // We are working with plugin resources
- ret.push(`/plugins/${id}.js { type="module" }`);
-
- if (!data.noCSS) {
- ret.push(`/plugins/${id}.css`);
- }
-
- return ret;
- },
-};
diff --git a/_layouts/home.njk b/_layouts/home.njk
deleted file mode 100644
index dd139050..00000000
--- a/_layouts/home.njk
+++ /dev/null
@@ -1,28 +0,0 @@
-{% extends "./page.njk" %}
-
-{% block head_extra -%}
-
-{%- endblock %}
-
-{% block header_extra -%}
-{% md %}
-
-- **Dead simple**
- Include prism.css and prism.js, use proper HTML5 code tags (`code.language-xxxx`), done!
-- **Intuitive**
- Language classes are inherited so you can only define the language once for multiple code snippets.
-- **Light as a feather**
- The core is 2KB minified & gzipped. Languages add 0.3-0.5KB each, themes are around 1KB.
-- **Blazing fast**
- Supports parallelism with Web Workers, if available.
-- **Extensible**
- Define new languages or extend existing ones. Add new features thanks to Prism's plugin architecture.
-- **Easy styling**
- All styling is done through CSS, with sensible class names like `.comment`, `.string`, `.property` etc.
-{ id="features" }
-
-{% endmd %}
-{%- endblock %}
diff --git a/_layouts/page.njk b/_layouts/page.njk
deleted file mode 100644
index e36f9b5a..00000000
--- a/_layouts/page.njk
+++ /dev/null
@@ -1,102 +0,0 @@
-
-
-
- {% if base %}
-
- {% endif -%}
-
- {%- set main_title = title | md | striptags or subdomain | capitalize %}
- {{ main_title }}{{ " ▲" if main_title }} Prism {{ subdomain if subdomain | capitalize != main_title }}
-
-
-
-
-
-
-
-
-
- {% block head_extra -%}{%- endblock -%}
-
-
-
-
-
-
{{ subdomain }}
-
- Download
-
-
- Prism is a lightweight, extensible syntax highlighter, built with modern web standards in mind.
- It’s used in millions of websites, including some of those you visit daily.
-
-
-
- {% if theme_switcher -%}
-
- Theme:
- {%- for id, theme in themes %}
-
-
- {%- endfor %}
-
- {%- endif %}
-
- {% block header_extra -%}{%- endblock -%}
-
- {% if title -%}
- {{ title | md }}
- {{ (tagline or description) | md }}
- {%- endif %}
-
-
- {% if toc and content | toc -%}
-
- {%- endif %}
-
-
- {% if back_to_top -%}
- {{ content | back_to_top | safe }}
- {%- else -%}
- {{ content | safe }}
- {%- endif %}
-
-
-
-
-
-
- {% if theme_switcher -%}
-
- {%- endif %}
-
- {%- for resource in resources | parse_resources %}
- {{ resource | safe -}}
- {%- endfor %}
-
-
diff --git a/_redirects.njk b/_redirects.njk
deleted file mode 100644
index 12022bee..00000000
--- a/_redirects.njk
+++ /dev/null
@@ -1,22 +0,0 @@
----
-permalink: _redirects
-layout: null
-eleventyExcludeFromCollections: true
----
-
-# Themes and languages
-/themes/:file https://v2.dev.prismjs.com/dist/themes/:file 301
-/languages/:file https://v2.dev.prismjs.com/dist/languages/:file 301
-
-# Plugins
-{% for plugin in collections.plugin -%}
-{%- set id = plugin.data.id -%}
-/plugins/{{ id }}.js https://v2.dev.prismjs.com/dist/plugins/{{ id }}.js 301
-/plugins/{{ id }}/{{ id }}.js https://v2.dev.prismjs.com/src/plugins/{{ id }}/{{ id }}.js 301
-{% if not meta.noCSS -%}
-/plugins/{{ id }}.css https://v2.dev.prismjs.com/dist/plugins/{{ id }}.css 301
-/plugins/{{ id }}/{{ id }}.css https://v2.dev.prismjs.com/src/plugins/{{ id }}/{{ id }}.css 301
-{% endif -%}
-{% endfor -%}
-/plugins/:plugin/demo.js https://v2.dev.prismjs.com/src/plugins/:plugin/demo.js 301
-/plugins/:plugin/demo.css https://v2.dev.prismjs.com/src/plugins/:plugin/demo.css 301
diff --git a/assets/style.css b/assets/style.css
deleted file mode 100644
index 3998db82..00000000
--- a/assets/style.css
+++ /dev/null
@@ -1,918 +0,0 @@
-@import url(https://fonts.googleapis.com/css?family=Questrial);
-@import url(https://fonts.googleapis.com/css?family=Arvo);
-
-/*
- Shared styles
- */
-
-section h1,
-#features li strong,
-header h2,
-footer p {
- font: 100% Rockwell, Arvo, serif;
-}
-
-/*
- Styles
- */
-
-* {
- margin: 0;
- padding: 0;
-}
-
-body {
- font: 100%/1.5 Questrial, sans-serif;
- tab-size: 4;
- hyphens: auto;
-}
-
-a {
- color: inherit;
-}
-
-section h1 {
- font-size: 250%;
-}
-
- section section h1 {
- font-size: 150%;
- }
-
- section h1 code {
- font-style: normal;
- }
-
- section h1 > a,
- section h2[id] > a {
- text-decoration: none;
- }
-
- section h1 > a:before,
- section h2[id] > a:before {
- content: '§';
- position: absolute;
- padding: 0 .2em;
- margin-left: -1em;
- border-radius: .2em;
- color: silver;
- text-shadow: 0 1px white;
- }
-
- section h1 > a:hover:before,
- section h2[id] > a:hover:before {
- color: black;
- background: #f1ad26;
- }
-
-p {
- margin: 1em 0;
-}
-
-section h1,
-h2,
-h3 {
- margin: 1em 0 .3em;
-}
-
-h2,
-h3 {
- font-weight: normal;
-
- > a {
- text-decoration: none;
- }
-}
-
-dt {
- margin: 1em 0 0 0;
- font-size: 130%;
-}
-
- dt:after {
- content: ':';
- }
-
-dd {
- margin-left: 2em;
-}
-
-code, pre {
- font-family: Consolas, Monaco, 'Andale Mono', 'Lucida Console', monospace;
- hyphens: none;
-}
-
-pre {
- max-height: 30em;
- overflow: auto;
-}
-
-mark {
- outline: .4em solid red;
- outline-offset: .4em;
- margin: .4em 0;
- background-color: transparent;
- display: inline-block;
-}
-
-header,
-body > main {
- display: block;
- max-width: 900px;
- margin: auto;
-}
-
-header, footer {
- position: relative;
- padding: 30px -webkit-calc(50% - 450px); /* Workaround for bug */
- padding: 30px calc(50% - 450px);
- color: white;
- text-shadow: 0 -1px 2px black, 0 0 4px black,
- 0 -1px 0 black, 0 1px 0 black, -1px 0 0 black, 1px 0 0 black;
- background: linear-gradient(transparent, rgba(0, 0, 0, 0.6)), url(img/spectrum.png) fixed;
-}
-
-header:before,
-footer:before {
- content: '';
- position: absolute;
- bottom: 0; left: 0; right: 0;
- height: 20px;
- background-size: 20px 40px;
- background-repeat: repeat-x;
- background-image: linear-gradient(45deg, transparent 34%, white 34%, white 66%, transparent 66%),
- linear-gradient(135deg, transparent 34%, white 34%, white 66%, transparent 66%);
-}
-
- header .intro,
- html.simple header {
- overflow: hidden;
- }
-
- header h1 {
- float: left;
- margin-right: 30px;
- color: #7fab14;
- text-align: center;
- font-size: 140%;
- text-transform: uppercase;
- letter-spacing: .25em;
- }
-
- header h2 {
- margin-top: .5em;
- color: #f1ad26;
- }
-
- header h1 a {
- text-decoration: none;
- }
-
- header img {
- display: block;
- width: 150px;
- height: 128px;
- margin-bottom: .3em;
- border: 0;
- }
-
- header h2 {
- font-size: 300%;
- }
-
- header .intro p {
- margin: 0;
- font: 150%/1.4 Questrial, sans-serif;
- font-size: 150%;
- }
-
- #features {
- margin-top: 1.6em;
- }
-
- #features li {
- margin: 0 0 1.6em 0;
- list-style: none;
- display: inline-block;
- width: 49%;
- box-sizing: border-box;
- vertical-align: top;
- }
-
- #features li:nth-child(odd) {
- padding-right: 2em;
- }
- #features li:nth-child(even) {
- padding-left: 2em;
- }
-
- #features li:before {
- content: '✓';
- float: left;
- margin-left: -.8em;
- color: #7fab14;
- font-size: 320%;
- line-height: 1;
- }
-
- #features li strong {
- display: block;
- margin-bottom: .1em;
- font-size: 160%;
- }
-
- header .download-button {
- float: right;
- margin: 0 0 .5em .5em;
- }
-
- #theme {
- position: relative;
- z-index: 1;
- float: right;
- margin-right: -9em;
- text-align: center;
- text-transform: uppercase;
- letter-spacing: .2em;
- text-shadow: 0 -1px 2px black;
- }
-
- #theme > p {
- position: absolute;
- left: 100%;
- transform: translateX(50%) rotate(90deg) ;
- transform-origin: top left;
- font-size: 130%;
- }
-
- #theme > label {
- position: relative;
- display: flex;
- justify-content: center;
- align-items: center;
- width: 8.5em;
- height: 8.5em;
- line-height: 1em;
- border-radius: 50%;
- background: hsla(0,0%,100%,.5);
- cursor: pointer;
- font-size: 90%;
- padding: 0;
- }
-
- #theme > label:before {
- content: '';
- position: absolute;
- top: 0; right: 0; bottom: 0; left: 0;
- z-index: -1;
- border-radius: inherit;
- background: url(img/spectrum.png) fixed;
- }
-
- #theme > label:nth-of-type(n+2) {
- margin-top: -2.5em;
- }
-
- #theme > input:not(:checked) + label:hover {
- background: hsla(77, 80%, 60%, .5);
- }
-
- #theme > input {
- position: absolute;
- left: 0;
- clip: rect(0,0,0,0);
- }
-
- #theme > input:checked + label {
- background: #7fab14;
- }
-
- @media (max-width: 1300px) and (min-width: 1051px) {
- #theme {
- position: relative;
- z-index: 1;
- float: left;
- margin: 1em 0;
- width: 100%;
- }
- #theme + * {
- clear: both;
- }
-
- #theme > p {
- margin-top: .5em;
- }
-
- #theme > label {
- float: left;
- font-size: 82.6%;
- }
-
- #theme > label:before {
- display: none;
- }
-
- #theme > label:nth-of-type(n+2) {
- margin-top: 0;
- }
- }
-
- @media (max-width: 1050px) {
- #theme {
- position: relative;
- z-index: 1;
- float: left;
- margin: 1em 0;
- }
- #theme + * {
- clear: both;
- }
-
- #theme > p {
- left: inherit;
- right: -1em;
- }
-
- #theme > label {
- float: left;
- }
-
- #theme > label:before {
- display: none;
- }
-
- #theme > label:nth-of-type(n+2) {
- margin-top: 0;
- }
- #theme > label:nth-of-type(n+5) {
- margin-top: -2.5em;
- }
- #theme > label:nth-of-type(4n+1) {
- margin-left: 12.5em;
- }
- }
-
- @media (max-width: 800px) {
- #theme > label:nth-of-type(4) {
- margin-right: 4em;
- }
- #theme > label:nth-of-type(4n+1) {
- margin-left: 4em;
- }
- }
-
-
-footer {
- margin-top: 2em;
- background-position: bottom;
- color: white;
-}
-
- footer:before {
- bottom: auto;
- top: 0;
- background-position: bottom;
- }
-
- footer p {
- font-size: 150%;
- }
-
- footer ul {
- column-count: 3;
- }
-
-.download-button {
- display: block;
- padding: .2em .8em .1em;
- border: 1px solid rgba(0,0,0,0.5);
- border-radius: 10px;
- background: #39a1cf;
- box-shadow: 0 2px 10px black,
- inset 0 1px hsla(0,0%,100%,.3),
- inset 0 .4em hsla(0,0%,100%,.2),
- inset 0 10px 20px hsla(0,0%,100%,.25),
- inset 0 -15px 30px rgba(0,0,0,0.3);
- color: white;
- text-shadow: 0 -1px 2px black;
- text-align: center;
- font-size: 250%;
- line-height: 1.5;
- text-transform: uppercase;
- text-decoration: none;
- hyphens: manual;
-}
-
-.download-button:hover {
- background-color: #7fab14;
-}
-
-.download-button:active {
- box-shadow: inset 0 2px 8px rgba(0,0,0,.8);
-}
-
-#toc {
- position: fixed;
- bottom: 15px;
- max-width: calc(50% - 450px - 40px);
- font-size: 80%;
- z-index: 999;
- background: white;
- color: rgba(0,0,0,.5);
- padding: 0 10px 10px;
- border-radius: 0 3px 3px 0;
- box-sizing: border-box;
-
- &:hover {
- color: rgba(0,0,0,1);
- }
-
- h2 {
- font-family: Rockwell, Arvo, serif;
- font-size: 180%;
- margin-top: .75rem;
- }
-
- li {
- list-style: none;
- line-height: 1.2;
- padding: .2em 0;
-
- a {
- padding: .2em 0;
- }
- }
-
- > nav.toc {
- li > ul {
- margin-inline-start: .5rem;
- }
- }
-
- &:has(+ main .back-to-top) {
- position: static;
- max-width: 900px;
- margin-inline: auto;
- font-size: 100%;
- color: black;
-
- :is([data-inputpath="known-failures.md"] &) > .toc {
- column-count: 4;
-
- li > ul {
- /* Show top-level headings only */
- display: none;
- }
- }
- }
-
- @media (max-width: 1200px) {
- &:not(:has(+ main .back-to-top)) {
- display: none;
- }
- }
-}
-
-
-#logo {
- float: right;
- margin-block-start: 3.5em;
- margin-inline-start: .5em;
- height: 5em;
- filter: brightness(0) invert(1);
-}
-
-.used-by-logos {
- overflow: hidden;
-}
- .used-by-logos > a {
- float: left;
- width: 33.33%;
- height: 100px;
- text-align: center;
- background: #F5F2F0;
- box-sizing: border-box;
- border: 5px solid white;
- position: relative;
- }
- .used-by-logos > a > img {
- max-height: 100%;
- max-width: 100%;
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- }
-
-label a.owner {
- margin: 0 .5em;
-}
-
-label a.owner:not(:hover) {
- text-decoration: none;
- color: #aaa;
-}
-
-#languages-list {
- column-count: 3;
- column-gap: 2em;
-
- li {
- padding: .2em;
- }
-
- li[data-id="javascript"] {
- border-bottom: 1px solid #aaa;
- padding-bottom: 1em;
- margin-bottom: 1em;
- margin-right: 1em;
- }
-}
-
-ul.plugin-list {
- column-count: 2;
- column-gap: 2em;
-
- > li {
- break-inside: avoid;
- page-break-inside: avoid;
-
- > a {
- font-size: 110%;
- }
-
- > div {
- margin-bottom: .5em;
- }
- }
-}
-
-[data-inputpath="examples.md"] {
- #languages {
- column-count: 4;
-
- > h1 {
- margin-top: 0;
- column-span: all;
- }
-
- label {
- display: block;
- padding: .2em;
-
- &[data-id="javascript"] {
- border-bottom: 1px solid #aaa;
- padding-bottom: 1em;
- margin-bottom: 1em;
- }
- }
-
- .unavailable {
- color: #aaa;
- }
-
- input {
- margin-right: .7em;
- }
- }
-
- #examples {
- > section {
- display: block;
- margin: auto;
- max-width: 900px;
- }
-
- h3 {
- margin: 1em 0 0.3em;
- }
- }
-
- main ul {
- padding-left: 40px;
- }
-}
-
-[data-inputpath="known-failures.md"] {
- main h2 {
- font-size: 1.2em;
-
- &[id] > a::before {
- content: "";
- }
- }
-}
-
-[data-inputpath="tokens.md"] {
- table.styled {
- border: 1px solid #ccc;
- border-spacing: 0;
-
- tr:not(:first-child) > * {
- border-top: 1px solid #ccc;
- }
-
- tr > *:not(:first-child) {
- border-left: 1px solid #ccc;
- }
-
- tr:nth-child(2n + 1) {
- background-color: #F8F8F8;
- }
-
- tr > * {
- padding: .5em .75em;
- }
-
- tr > th {
- text-align: left;
- }
- }
-}
-
-[data-inputpath="extending.md"] {
- ol.indent {
- margin: 1em 0;
- padding-left: 2em;
- }
-
- table.stylish {
- border-collapse: collapse;
-
- &, tr, td, th {
- border: 1px solid #CCC;
- }
-
- td, th {
- padding: .5em .75em;
- }
-
- th, td:first-child {
- background-color: #F8F8F8;
- }
- }
-}
-
-[data-inputpath="test.md"] {
- textarea {
- width: 100%;
- height: 10em;
- padding: 1em;
- box-sizing: border-box;
- margin: .5em 0;
- background: #f5f2f0;
- color: black;
- text-shadow: 0 1px white;
- tab-size: 4;
- font: 100% Consolas, Monaco, monospace;
- white-space: pre;
- word-wrap: normal;
- resize: vertical;
- }
-
- #language {
- column-count: 4;
-
- label {
- display: block;
- padding: .2em;
- }
-
- label[data-id="javascript"] {
- border-bottom: 1px solid #aaa;
- padding-bottom: 1em;
- margin-bottom: 1em;
- }
-
- input {
- margin-right: 1em;
- }
-
- strong {
- display: block;
- column-span: all;
- }
- }
-
- pre.show-tokens {
- line-height: calc(1.5em + 12px);
- }
-
- .show-tokens {
- .token:not(:first-child) {
- margin-left: 1px;
- }
-
- .token:empty {
- background: red;
- }
-
- .token:empty::before {
- color: white;
- content: 'empty';
- font-style: italic;
- text-shadow: black 0 0 .3em;
- }
-
- .token {
- border: 1px solid;
- padding: 6px 1px;
- }
-
- .token > .token {
- padding: 4px 1px;
- }
-
- .token > .token > .token {
- padding: 2px 1px;
- }
-
- .token > .token > .token > .token {
- padding: 0 1px;
- }
-
- .token > .token > .token > .token > .token {
- border: none;
- border-left: 1px solid;
- border-right: 1px solid;
- padding: 0;
- margin: 0 1px;
- }
- }
-
- #options {
- position: relative;
- }
-
- .link-wrapper {
- position: absolute;
- top: 0;
- right: 0;
- background-color: white;
-
- .hidden-wrapper {
- display: none;
- }
-
- &:hover {
- top: -.5em;
- right: -1em;
- width: 300px;
- padding: .5em 1em;
- outline: 1px solid #888;
-
- .hidden-wrapper {
- display: block;
- }
- }
-
- input {
- width: 100%;
- box-sizing: border-box;
- }
-
- button {
- border: none;
- background: none;
- font: inherit;
- text-decoration: underline;
- cursor: pointer;
- }
- }
-}
-
-[data-inputpath^="download"] {
- form label {
- display: block;
- padding: .2em;
- padding-left: 1.9em;
- page-break-inside: avoid;
- break-inside: avoid;
-
- .name {
- margin-right: .3em;
- }
-
- a.owner {
- margin-left: 0;
- hyphens: none;
- }
-
- input {
- margin-right: .7em;
- margin-left: -1.7em;
- }
- }
-
-
- form > p:first-of-type > label {
- font-size: 150%;
-
- input {
- vertical-align: .3em;
- }
- }
-
-
- .filesize:empty {
- display: none;
- }
-
- #components {
- overflow: hidden;
- }
-
- section.options {
- width: 33.3%;
- width: calc(100% / 3);
- float: left;
-
- label[data-id^="check-all-"] {
- border-bottom: 1px solid #aaa;
- padding-bottom: 1em;
- margin-bottom: 1em;
- }
- }
-
- section.options#category-languages,
- section.options#category-plugins {
- width: 100%;
- float: none;
- column-count: 3;
- padding-top: 2em;
- overflow: visible;
-
- label {
- break-inside: avoid;
- }
-
- > h1 {
- margin-top: 0;
- column-span: all;
- }
-
- label[data-id="javascript"] {
- border-bottom: 1px solid #aaa;
- padding-bottom: 1em;
- margin-bottom: 1em;
- }
- }
-
-
- section.options#category-themes {
- width: 66.6%;
- width: calc(100% * 2/3);
- column-count: 2;
- overflow: visible;
- float: none;
-
- > h1 {
- column-span: all;
- }
- }
-
-
- section.download {
- width: 50%;
- float: left;
- }
-
- #download {
- overflow: hidden;
- padding: .3em;
- .error {
- color: #B61500;
- display: none;
- }
- pre {
- height: 20em;
- }
- .download-button {
- cursor: pointer;
- width: 100%;
- }
-
- }
-
- #download-js .download-button {
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
- }
-
- #download-css .download-button {
- background-color: #dc9e23;
- border-top-left-radius: 0;
- border-bottom-left-radius: 0;
- }
-}
-
-/* Decorate only the first link in headings */
-section :is(h1, h2, h3)[id] {
- a:not(:first-of-type) {
- text-decoration: revert;
-
- &::before {
- display: none;
- }
- }
-}
diff --git a/assets/styles/brand.css b/assets/styles/brand.css
new file mode 100644
index 00000000..734a2a29
--- /dev/null
+++ b/assets/styles/brand.css
@@ -0,0 +1,684 @@
+@import url(https://fonts.googleapis.com/css?family=Questrial);
+@import url(https://fonts.googleapis.com/css?family=Arvo);
+
+/*
+ * What Prism's docs add to the theme: the brand faces and logo, definition lists, the
+ * highlighted-markup `` affordance, and the page-specific widgets below — the language
+ * and plugin lists, the download builder, the test drive, the token tables.
+ */
+
+/* The brand faces */
+:root {
+ --font-body: Questrial, sans-serif;
+ --font-heading: Rockwell, Arvo, serif;
+}
+
+/*
+ * Docspire marks the current page and section by weight alone (600 and 550), which Questrial
+ * can't show: it ships one weight. The accent color marks them instead. Docspire reads
+ * --ui-color-accent but never defines it, so the outline's marker was invisible too.
+ * The outline's variable goes on the element, not :root, where the component's own value would win.
+ */
+:root {
+ /* The tints links use, 45 in light mode and 65 in dark */
+ --ui-color-accent: light-dark(
+ oklch(from var(--color-accent) var(--tint-45)),
+ oklch(from var(--color-accent) var(--tint-65))
+ );
+}
+
+page-outline {
+ --ui-color-text-outline-hover: var(--ui-color-accent);
+}
+
+#sidebar a.current {
+ color: var(--ui-color-accent);
+}
+
+body {
+ tab-size: 4;
+ hyphens: auto;
+}
+
+/* A hyphen dropped into an identifier reads as part of it */
+:is(code, pre, kbd, samp) {
+ hyphens: none;
+}
+
+/* Line numbers are rows beside the code, so a line of code must be exactly as tall as a row.
+ With line-height: normal, its height follows the font a line happens to be drawn in, and the
+ is not even in the block's font. Prism's own themes set both. */
+pre:has(> code) {
+ line-height: 1.5;
+
+ & code {
+ font-family: inherit;
+ }
+}
+
+/* Prism's plugins make room for their gutters with the 's padding, like line-highlight's
+ `pre[data-line] { padding: 1em 0 1em 3em }`. So a code-block pads its , not itself,
+ and a plugin's padding replaces Docspire's there too, instead of adding to it. */
+code-block {
+ padding: 0;
+
+ & > pre {
+ padding: var(--size-l);
+ }
+}
+
+/* A long block, like a whole file fetched by file-highlight, scrolls inside itself */
+pre {
+ max-height: 30em;
+ overflow: auto;
+}
+
+/* FIXME: Drop once Prism's autoloader stops highlighting again a file-highlight took over.
+ That pass replaces the with bare tokens, and Docspire styles only `pre:has(> code)`. */
+pre[data-src]:not(:has(> code)) {
+ padding: var(--size-l);
+ background: var(--ui-background-code, var(--ui-background-code-default));
+ border-radius: var(--ui-rounding-code, var(--rounding));
+ font: var(--size-s) / 1.5 var(--font-mono);
+}
+
+/*
+ * Nothing here was ever bold: section titles came from `font: 100% Rockwell…` and the rest
+ * from `h2, h3 { font-weight: normal }`. The page title takes h1 now, so those two sets are
+ * h2 and h3/h4. Sizes are the theme's, which already sit under that title.
+ */
+h2,
+h3,
+h4 {
+ font-weight: normal;
+}
+
+/* Below a section title the old stylesheet left headings in the body face */
+h3,
+h4 {
+ font-family: var(--font-body);
+}
+
+/*
+ * logo.svg is a white silhouette drawn for the dark spectrum header the old site had. Give it a
+ * dark ground back wherever it appears, rather than inverting it per color scheme — the shape
+ * then reads the same either way, as it does in the browser tab.
+ */
+:is(header .logo img, .hero .image) {
+ padding: var(--size-6xs);
+ border-radius: var(--rounding);
+ background: black;
+}
+
+/*
+ * Shown large, it gets the spectrum itself: the whole image, squeezed to fit, since cropping it
+ * leaves only the green middle. The dark overlay it used to carry went with the old header,
+ * which needed white text to stay legible over the colors.
+ */
+.hero .image {
+ padding: var(--size-l);
+ background: url("/assets/img/spectrum.png") center / 100% 100%;
+}
+
+/* Title and lede read as one block, and the title is no bolder than any other heading */
+.page-title {
+ margin-block-end: var(--size-xl);
+
+ h1 {
+ font-weight: normal;
+ margin-block-end: var(--size-3xs);
+ }
+
+ p {
+ color: var(--ui-color-text-quiet);
+ }
+}
+
+dt {
+ margin: 1em 0 0 0;
+ font-size: 130%;
+}
+
+dt:after {
+ content: ":";
+}
+
+dd {
+ margin-left: 2em;
+}
+
+mark {
+ outline: 0.4em solid red;
+ outline-offset: 0.4em;
+ margin: 0.4em 0;
+ background-color: transparent;
+ display: inline-block;
+}
+
+/* Homepage walkthrough: numbered steps, one snippet each (see docs/index.md), as on nudeps.dev.
+ Two-column grid (number, content) that each step subgrids into, so numbers and content align across steps. */
+.steps {
+ list-style: none;
+ counter-reset: step;
+ margin-block: var(--size-l);
+ padding: 0;
+ display: grid;
+ /* minmax(0) so a wide code block scrolls instead of widening the column */
+ grid-template-columns: auto minmax(0, 1fr);
+ column-gap: var(--size-m);
+
+ > li {
+ counter-increment: step;
+ display: grid;
+ grid-template-columns: subgrid;
+ grid-column: 1 / -1;
+
+ /* Step number, in the accent color like the hero's primary action */
+ &::before {
+ content: counter(step);
+ width: var(--size-2xl);
+ aspect-ratio: 1;
+ border-radius: 50%;
+ display: grid;
+ place-content: center;
+ font-weight: 700;
+ --color-core: var(--color-accent);
+ background: var(--color-core-45-65);
+ color: var(--color-core-100-15);
+ }
+
+ /* Everything else stacks in the content column */
+ > * {
+ grid-column: 2;
+ }
+
+ /* Space between steps, with a connector from this step's number down to the next */
+ &:not(:last-child) {
+ padding-block-end: var(--size-xl);
+ background: linear-gradient(var(--ui-border-color), var(--ui-border-color))
+ calc(var(--size-2xl) / 2 - 0.5px) var(--size-2xl) / 1px 100% no-repeat;
+ }
+
+ > h3 {
+ margin-block: 0 var(--size-2xs);
+ /* Same box height as the number, so the two line up */
+ line-height: var(--size-2xl);
+ }
+
+ > p {
+ margin-block: var(--size-2xs) 0;
+ color: var(--ui-color-text-quiet);
+ }
+ }
+}
+
+.used-by-logos {
+ overflow: hidden;
+}
+.used-by-logos > a {
+ float: left;
+ width: 33.33%;
+ height: 100px;
+ text-align: center;
+ background: #f5f2f0;
+ box-sizing: border-box;
+ border: 5px solid white;
+ position: relative;
+}
+.used-by-logos > a > img {
+ max-height: 100%;
+ max-width: 100%;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+}
+
+label a.owner {
+ margin: 0 0.5em;
+}
+
+label a.owner:not(:hover) {
+ text-decoration: none;
+ color: #aaa;
+}
+
+#languages-list {
+ column-count: 3;
+ column-gap: 2em;
+
+ li {
+ padding: 0.2em;
+ }
+
+ li[data-id="javascript"] {
+ border-bottom: 1px solid #aaa;
+ padding-bottom: 1em;
+ margin-bottom: 1em;
+ margin-right: 1em;
+ }
+}
+
+ul.plugin-list {
+ column-count: 2;
+ column-gap: 2em;
+
+ > li {
+ break-inside: avoid;
+ page-break-inside: avoid;
+
+ > a {
+ font-size: 110%;
+ }
+
+ > div {
+ margin-bottom: 0.5em;
+ }
+ }
+}
+
+[data-inputpath="examples.md"] {
+ #languages {
+ column-count: 4;
+
+ > h1 {
+ margin-top: 0;
+ column-span: all;
+ }
+
+ label {
+ display: block;
+ padding: 0.2em;
+
+ &[data-id="javascript"] {
+ border-bottom: 1px solid #aaa;
+ padding-bottom: 1em;
+ margin-bottom: 1em;
+ }
+ }
+
+ .unavailable {
+ color: #aaa;
+ }
+
+ input {
+ margin-right: 0.7em;
+ }
+ }
+
+ #examples {
+ /*
+ * Two kinds of h2: the language name that opens each section, and the titles inside
+ * the example file below it. Same size, told apart by the face, as before the
+ * migration — where the language name was the section's h1.
+ */
+ h2 {
+ font-size: 1.5em;
+ font-family: var(--font-body);
+ }
+
+ > section > h2:first-child {
+ font-family: var(--font-heading);
+ }
+
+ /* Sections lay out as a flex column, where `margin: auto` alone would shrink each
+ example to its widest line */
+ > section {
+ margin-inline: auto;
+ inline-size: min(100%, 900px);
+
+ /* Every language has one, and the column's gap would space out the ~300 unused */
+ &:empty {
+ display: none;
+ }
+ }
+
+ h3 {
+ margin: 1em 0 0.3em;
+ }
+ }
+
+ main ul {
+ padding-left: 40px;
+ }
+}
+
+[data-inputpath="known-failures.md"] {
+ /* h2 is the language, h3 the failure: keep the failure a label, not a second title */
+ main h3 {
+ font-size: 1.2em;
+
+ &[id] > a::before {
+ content: "";
+ }
+ }
+}
+
+[data-inputpath="tokens.md"] {
+ table.styled {
+ border: 1px solid #ccc;
+ border-spacing: 0;
+
+ tr:not(:first-child) > * {
+ border-top: 1px solid #ccc;
+ }
+
+ tr > *:not(:first-child) {
+ border-left: 1px solid #ccc;
+ }
+
+ /* Between the page and the code surface, so a code block still reads as a block */
+ tr:nth-child(2n + 1) {
+ background-color: color-mix(in oklch, var(--color-bg-soft), var(--color-bg));
+ }
+
+ tr > * {
+ padding: 0.5em 0.75em;
+ }
+
+ tr > th {
+ text-align: left;
+ }
+ }
+}
+
+[data-inputpath="extending.md"] {
+ ol.indent {
+ margin: 1em 0;
+ padding-left: 2em;
+ }
+
+ table.stylish {
+ border-collapse: collapse;
+
+ &,
+ tr,
+ td,
+ th {
+ border: 1px solid #ccc;
+ }
+
+ td,
+ th {
+ padding: 0.5em 0.75em;
+ }
+
+ th,
+ td:first-child {
+ background-color: #f8f8f8;
+ }
+ }
+}
+
+[data-inputpath="test.md"] {
+ textarea {
+ width: 100%;
+ height: 10em;
+ padding: 1em;
+ box-sizing: border-box;
+ margin: 0.5em 0;
+ background: #f5f2f0;
+ color: black;
+ text-shadow: 0 1px white;
+ tab-size: 4;
+ font:
+ 100% Consolas,
+ Monaco,
+ monospace;
+ white-space: pre;
+ word-wrap: normal;
+ resize: vertical;
+ }
+
+ #language {
+ column-count: 4;
+
+ label {
+ display: block;
+ padding: 0.2em;
+ }
+
+ label[data-id="javascript"] {
+ border-bottom: 1px solid #aaa;
+ padding-bottom: 1em;
+ margin-bottom: 1em;
+ }
+
+ input {
+ margin-right: 1em;
+ }
+
+ strong {
+ display: block;
+ column-span: all;
+ }
+ }
+
+ pre.show-tokens {
+ line-height: calc(1.5em + 12px);
+ }
+
+ .show-tokens {
+ .token:not(:first-child) {
+ margin-left: 1px;
+ }
+
+ .token:empty {
+ background: red;
+ }
+
+ .token:empty::before {
+ color: white;
+ content: "empty";
+ font-style: italic;
+ text-shadow: black 0 0 0.3em;
+ }
+
+ .token {
+ border: 1px solid;
+ padding: 6px 1px;
+ }
+
+ .token > .token {
+ padding: 4px 1px;
+ }
+
+ .token > .token > .token {
+ padding: 2px 1px;
+ }
+
+ .token > .token > .token > .token {
+ padding: 0 1px;
+ }
+
+ .token > .token > .token > .token > .token {
+ border: none;
+ border-left: 1px solid;
+ border-right: 1px solid;
+ padding: 0;
+ margin: 0 1px;
+ }
+ }
+
+ #options {
+ position: relative;
+ }
+
+ .link-wrapper {
+ position: absolute;
+ top: 0;
+ right: 0;
+ background-color: white;
+
+ .hidden-wrapper {
+ display: none;
+ }
+
+ &:hover {
+ top: -0.5em;
+ right: -1em;
+ width: 300px;
+ padding: 0.5em 1em;
+ outline: 1px solid #888;
+
+ .hidden-wrapper {
+ display: block;
+ }
+ }
+
+ input {
+ width: 100%;
+ box-sizing: border-box;
+ }
+
+ button {
+ border: none;
+ background: none;
+ font: inherit;
+ text-decoration: underline;
+ cursor: pointer;
+ }
+ }
+}
+
+[data-inputpath^="download"] {
+ form label {
+ display: block;
+ padding: 0.2em;
+ padding-left: 1.9em;
+ page-break-inside: avoid;
+ break-inside: avoid;
+
+ .name {
+ margin-right: 0.3em;
+ }
+
+ a.owner {
+ margin-left: 0;
+ hyphens: none;
+ }
+
+ input {
+ margin-right: 0.7em;
+ margin-left: -1.7em;
+ }
+ }
+
+ .filesize:empty {
+ display: none;
+ }
+
+ #components {
+ overflow: hidden;
+ }
+
+ section.options {
+ width: 33.3%;
+ width: calc(100% / 3);
+ float: left;
+
+ label[data-id^="check-all-"] {
+ border-bottom: 1px solid #aaa;
+ padding-bottom: 1em;
+ margin-bottom: 1em;
+ }
+ }
+
+ section.options#category-languages,
+ section.options#category-plugins {
+ width: 100%;
+ float: none;
+ column-count: 3;
+ padding-top: 2em;
+ overflow: visible;
+
+ label {
+ break-inside: avoid;
+ }
+
+ > h2 {
+ margin-top: 0;
+ column-span: all;
+ }
+
+ label[data-id="javascript"] {
+ border-bottom: 1px solid #aaa;
+ padding-bottom: 1em;
+ margin-bottom: 1em;
+ }
+ }
+
+ section.options#category-themes {
+ width: 66.6%;
+ width: calc(100% * 2 / 3);
+ column-count: 2;
+ overflow: visible;
+ float: none;
+
+ > h2 {
+ column-span: all;
+ }
+ }
+
+ section.download {
+ width: 50%;
+ float: left;
+ }
+
+ .download-button {
+ display: block;
+ padding: 0.2em 0.8em 0.1em;
+ border: 1px solid rgba(0, 0, 0, 0.5);
+ border-radius: 10px;
+ background: #39a1cf;
+ box-shadow:
+ 0 2px 10px black,
+ inset 0 1px hsla(0, 0%, 100%, 0.3),
+ inset 0 0.4em hsla(0, 0%, 100%, 0.2),
+ inset 0 10px 20px hsla(0, 0%, 100%, 0.25),
+ inset 0 -15px 30px rgba(0, 0, 0, 0.3);
+ color: white;
+ text-shadow: 0 -1px 2px black;
+ text-align: center;
+ font-size: 250%;
+ line-height: 1.5;
+ text-transform: uppercase;
+ text-decoration: none;
+ hyphens: manual;
+
+ &:hover {
+ background-color: #7fab14;
+ }
+
+ &:active {
+ box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.8);
+ }
+ }
+
+ #download {
+ overflow: hidden;
+ padding: 0.3em;
+ .error {
+ color: #b61500;
+ display: none;
+ }
+ pre {
+ height: 20em;
+ }
+ .download-button {
+ cursor: pointer;
+ width: 100%;
+ }
+ }
+
+ #download-js .download-button {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ }
+
+ #download-css .download-button {
+ background-color: #dc9e23;
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ }
+}
diff --git a/data/prism.js b/data/prism.js
new file mode 100644
index 00000000..ac18fc2f
--- /dev/null
+++ b/data/prism.js
@@ -0,0 +1,7 @@
+import components from "../docs/components.json" with { type: "json" };
+import file_sizes from "../docs/file-sizes.json" with { type: "json" };
+
+// Every category keeps a `meta` entry among its components
+let { meta, ...languages } = components.languages;
+
+export default { components, file_sizes, languages };
diff --git a/assets/download.js b/docs/assets/download.js
similarity index 99%
rename from assets/download.js
rename to docs/assets/download.js
index a38d1c76..ff9d6997 100644
--- a/assets/download.js
+++ b/docs/assets/download.js
@@ -2,6 +2,7 @@
* Manage downloads
*/
+import Prism from "./prism.js";
import { getFileContents, toArray } from "./util.js";
let components = await (await fetch("/components.json")).json();
@@ -486,6 +487,7 @@ function buildCode (promises) {
* @returns {Promise}
*/
async function getVersion () {
+ // FIXME: Drop “v2” from the host when Prism v2 is released
let packageJSON = await getFileContents("https://v2.dev.prismjs.com/package.json");
return JSON.parse(packageJSON).version;
}
diff --git a/assets/examples.js b/docs/assets/examples.js
similarity index 81%
rename from assets/examples.js
rename to docs/assets/examples.js
index 1acae9c8..babc5f99 100644
--- a/assets/examples.js
+++ b/docs/assets/examples.js
@@ -2,6 +2,7 @@
* Manage examples
*/
+import Prism from "./prism.js";
import { toArray, getFileContents } from "./util.js";
let components = await (await fetch("/components.json")).json();
@@ -22,7 +23,7 @@ async function fileExists (filepath) {
// on localhost: The missing example might be for a new language
if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
try {
- await getFileContents(filepath);
+ await getFileContents("/" + filepath);
return true;
}
catch (error) {
@@ -34,7 +35,8 @@ async function fileExists (filepath) {
function buildContentsHeader (id) {
let language = languages[id];
- let header = `${language.title}
`;
+ // h2: the page already has its own , and this sits inside a section of it
+ let header = `${language.title}
`;
if (language.aliasTitles) {
let alias = Object.keys(language.aliasTitles);
header += "
To use this language, use one of the following classes:
";
@@ -62,7 +64,7 @@ function buildContentsHeader (id) {
}
if (deps.length) {
header += "";
- header += `Dependencies:`;
+ header += `Dependencies:`;
header += " This component";
if (deps.length === 1) {
header += ` ${deps[0]}.`;
@@ -83,22 +85,21 @@ function buildContentsHeader (id) {
async function update (id) {
let language = languages[id];
if (language.enabled) {
- let contents = await getFileContents(language.examplesPath);
- examples[id].innerHTML = buildContentsHeader(id) + contents;
+ // Leading slash: examplesPath is a repo path, and this page is served from /examples/
+ let contents = await getFileContents("/" + language.examplesPath);
/** @type {HTMLElement} */
let container = examples[id];
container.innerHTML = buildContentsHeader(id) + contents;
- // the current language might be an extension of a language
- // so to be safe, we explicitly add a dependency to the current language
- container.querySelectorAll("pre").forEach(
- /** @param {HTMLElement} pre */ pre => {
- let dependencies = (pre.getAttribute("data-dependencies") || "").trim();
- dependencies = dependencies ? dependencies + "," + id : id;
- pre.setAttribute("data-dependencies", dependencies);
- },
- );
+ for (let pre of container.querySelectorAll("pre")) {
+ // An example file may name its own language, as OpenCL's does with cpp
+ let language = pre.className.match(/language-([\w-]+)/)?.[1] ?? id;
+
+ // The language might extend another, so depend on the current one explicitly
+ pre.dataset.dependencies = [pre.dataset.dependencies, id].filter(Boolean).join(",");
+ pre.className = `language-${language}`;
+ }
Prism.highlightAll({ root: container });
}
diff --git a/assets/faq.js b/docs/assets/faq.js
similarity index 67%
rename from assets/faq.js
rename to docs/assets/faq.js
index a235b9a5..cd91b752 100644
--- a/assets/faq.js
+++ b/docs/assets/faq.js
@@ -2,6 +2,7 @@
* Show tokens for a language on the FAQ page
*/
+import Prism from "./prism.js";
import { toArray } from "./util.js";
let languageSelect = document.querySelector("#language-select");
@@ -9,7 +10,12 @@ languageSelect.addEventListener("change", showTokens);
let tokensOutput = document.querySelector("#print-tokens-output");
-function printTokens (grammar) {
+// Prism.languages holds language definitions; the tokens live in the grammar they resolve to
+function grammar (id) {
+ return Prism.languageRegistry.getLanguage(id).resolvedGrammar;
+}
+
+function printTokens (root) {
let lines = [];
function log (line) {
if (!lines.includes(line)) {
@@ -19,14 +25,18 @@ function printTokens (grammar) {
let languageMap = new Map();
let languages = [...languageSelect.options].map(o => o.value);
- Prism.components.entries
- .keys()
+ Object.keys(Prism.languages)
.filter(l => languages.includes(l))
- .forEach(l => languageMap.set(Prism.components.getLanguage(l), `Prism.languages["${l}"]`));
+ .forEach(l => languageMap.set(grammar(l), `Prism.languages["${l}"]`));
let stack = new Map();
function inner (g, prefix) {
+ // v2 can name the grammar by language id, as in `inside: "xml"`
+ if (typeof g === "string") {
+ log(`${prefix} > ...Prism.languages["${g}"]`);
+ return;
+ }
if (prefix && languageMap.has(g)) {
log(prefix + " > ..." + languageMap.get(g));
return;
@@ -40,11 +50,12 @@ function printTokens (grammar) {
for (let name in g) {
let element = g[name];
- if (name === "rest") {
+ if (name === "$rest") {
inner(element, (prefix ? prefix + " > " : "") + ":rest:");
}
- else {
- for (let a = toArray(element), i = 0, token; (token = a[i++]); ) {
+ // Other special keys, like `$inner`, aren't tokens
+ else if (!name.startsWith("$")) {
+ for (let a = toArray(element), i = 0, token; (token = a[i++]);) {
let line =
(prefix ? prefix + " > " : "") +
name +
@@ -63,7 +74,7 @@ function printTokens (grammar) {
stack.delete(g);
}
- inner(grammar, "");
+ inner(root, "");
return lines.join("\n");
}
@@ -71,16 +82,15 @@ function printTokens (grammar) {
let loadedLanguages = {};
function showTokens () {
let language = languageSelect.value;
- if (Prism.components.has(language)) {
- tokensOutput.textContent = printTokens(Prism.components.getLanguage(language));
+ if (Prism.languageRegistry.has(language)) {
+ tokensOutput.textContent = printTokens(grammar(language));
}
else if (language in loadedLanguages) {
tokensOutput.textContent = `"${language}" doesn't have any tokens.`;
}
else {
// load grammar
- Prism.plugins.autoloader
- .loadLanguages(language)
+ Prism.loadLanguage(language)
.then(() => {
loadedLanguages[language] = true;
showTokens();
@@ -91,5 +101,4 @@ function showTokens () {
}
}
-// Give Prism a chance to load
-setTimeout(showTokens, 100);
+showTokens();
diff --git a/assets/img/failures/coy-overlap.png b/docs/assets/img/failures/coy-overlap.png
similarity index 100%
rename from assets/img/failures/coy-overlap.png
rename to docs/assets/img/failures/coy-overlap.png
diff --git a/assets/img/logo-ala.png b/docs/assets/img/logo-ala.png
similarity index 100%
rename from assets/img/logo-ala.png
rename to docs/assets/img/logo-ala.png
diff --git a/assets/img/logo-css-tricks.png b/docs/assets/img/logo-css-tricks.png
similarity index 100%
rename from assets/img/logo-css-tricks.png
rename to docs/assets/img/logo-css-tricks.png
diff --git a/assets/img/logo-drupal.png b/docs/assets/img/logo-drupal.png
similarity index 100%
rename from assets/img/logo-drupal.png
rename to docs/assets/img/logo-drupal.png
diff --git a/assets/img/logo-mdn.png b/docs/assets/img/logo-mdn.png
similarity index 100%
rename from assets/img/logo-mdn.png
rename to docs/assets/img/logo-mdn.png
diff --git a/assets/img/logo-mysql.png b/docs/assets/img/logo-mysql.png
similarity index 100%
rename from assets/img/logo-mysql.png
rename to docs/assets/img/logo-mysql.png
diff --git a/assets/img/logo-react.png b/docs/assets/img/logo-react.png
similarity index 100%
rename from assets/img/logo-react.png
rename to docs/assets/img/logo-react.png
diff --git a/assets/img/logo-sitepoint.png b/docs/assets/img/logo-sitepoint.png
similarity index 100%
rename from assets/img/logo-sitepoint.png
rename to docs/assets/img/logo-sitepoint.png
diff --git a/assets/img/logo-smashing.png b/docs/assets/img/logo-smashing.png
similarity index 100%
rename from assets/img/logo-smashing.png
rename to docs/assets/img/logo-smashing.png
diff --git a/assets/img/logo-stripe.png b/docs/assets/img/logo-stripe.png
similarity index 100%
rename from assets/img/logo-stripe.png
rename to docs/assets/img/logo-stripe.png
diff --git a/assets/img/spectrum.png b/docs/assets/img/spectrum.png
similarity index 100%
rename from assets/img/spectrum.png
rename to docs/assets/img/spectrum.png
diff --git a/docs/assets/prism.js b/docs/assets/prism.js
new file mode 100644
index 00000000..201ff1ab
--- /dev/null
+++ b/docs/assets/prism.js
@@ -0,0 +1,19 @@
+/**
+ * The one Prism instance the site runs on.
+ */
+// FIXME: Drop “v2” from the host when Prism v2 is released
+import Prism from "https://v2.dev.prismjs.com/dist/index.js";
+// Pages use
without loading the plugin themselves
+import "/plugins/file-highlight.js";
+
+// Core waits for the document only when loaded by a deferred classic
+```
+
+
+
+
+## Mark up your code
+
+```html
+p { color: red }
+```
+
+Prism finds it on load and highlights it. The class is [inherited](/start/#language-inheritance), so one on a common ancestor covers every snippet inside.
+
+
+
+
+That’s it. Read the [full walkthrough](/start/), see [what else Prism does](/features/), or [try it out for yourself](/test/).
+
+
+
+
+
+# Used By
+
+Prism is used on several websites, small and large. Some of them are:
+
+
+
+
+
+
+
+# Credits
+
+- Special thanks to [Michael Schmidt](https://github.com/RunDevelopment), [James DiGioia](https://github.com/mAAdhaTTah), [Golmote](https://github.com/Golmote) and [Jannik Zschiesche](https://github.com/apfelbox) for their contributions and for being **amazing maintainers**. Prism would not have been able to keep up without their help.
+- To [Roman Komarov](https://twitter.com/kizmarh) for his contributions, feedback and testing.
+- To [Zachary Forrest](https://twitter.com/zdfs) for [coming up with the name “Prism”](https://twitter.com/zdfs/statuses/217834980871639041).
+- To [Jason Hobbs](https://twitter.com/thecodezombie) for [encouraging me](https://twitter.com/thecodezombie/status/217663703825399809) to release this script as standalone.
+
+
diff --git a/known-failures.md b/docs/known-failures.md
similarity index 98%
rename from known-failures.md
rename to docs/known-failures.md
index 1ca2bb5f..da408e61 100644
--- a/known-failures.md
+++ b/docs/known-failures.md
@@ -2,7 +2,6 @@
tagline: A list of rare edge cases where Prism highlights code incorrectly.
back_to_top: true
body_classes: language-none
-resources: /plugins/autoloader.js { type="module" }
---
There are certain edge cases where Prism will fail. There are always such cases in every regex-based syntax highlighter.
@@ -459,7 +458,7 @@ Some of our themes are not compatible with certain layouts.
Coy's shadows and background might not wrap around the code correctly if combined with float of flexbox layouts.
-
+
## Workarounds
diff --git a/docs/plugins.md b/docs/plugins.md
new file mode 100644
index 00000000..fa8c5073
--- /dev/null
+++ b/docs/plugins.md
@@ -0,0 +1,20 @@
+---
+title: Plugins
+tagline: Additional scripts and styles that extend Prism’s functionality. Many are official, released separately to keep Prism core small for those who don’t need them.
+permalink: /plugins/
+parentOf: plugin
+---
+
+
+ {% for plugin in collections.plugin -%}
+ {%- set meta = plugin.data -%}
+ -
+ {{ meta.title | md }}
+ {{ meta.description | md }}
+
+ {% endfor -%}
+
+
+No assembly required to use them. Just select them in the [download](/download/) page.
+
+It’s very easy to [write your own Prism plugins](/extending/#writing-plugins). Did you write a plugin for Prism that you want added to this list? [Send a pull request](https://github.com/PrismJS/plugins/)!
diff --git a/docs/plugins/plugins.11tydata.js b/docs/plugins/plugins.11tydata.js
new file mode 100644
index 00000000..5205ac61
--- /dev/null
+++ b/docs/plugins/plugins.11tydata.js
@@ -0,0 +1,25 @@
+export default {
+ tags: ["plugin"],
+ eleventyComputed: {
+ // The directory postinstall copied the page into
+ id: data => data.page.filePathStem.split("/")[2],
+
+ // The plugin comes before the page's own demo.js, which builds on it
+ resources: data => [
+ `/plugins/${data.id}.js { type="module" }`,
+ ...(data.noCSS ? [] : [`/plugins/${data.id}.css`]),
+ ...[data.resources ?? []].flat(),
+ ],
+
+ // A README is the plugin's page; a demo keeps the .html URL its README fetches it by
+ permalink: data =>
+ data.page.fileSlug === "README"
+ ? data.page.filePathStem.replace(/README$/, "index.html")
+ : `${data.page.filePathStem}.html`,
+
+ // These pages are copied from the Prism repo by postinstall, so that is where edits go
+ // FIXME: Switch to the main branch when Prism v2 is released
+ editLink: data =>
+ `https://github.com/PrismJS/prism/edit/v2/src/plugins/${data.page.inputPath.split("/plugins/").pop()}`,
+ },
+};
diff --git a/docs/start.md b/docs/start.md
new file mode 100644
index 00000000..7fad9aec
--- /dev/null
+++ b/docs/start.md
@@ -0,0 +1,146 @@
+---
+title: Getting started
+tagline: Include Prism in your page, mark up your code, and Prism does the rest.
+order: 0
+resources:
+ - /plugins/keep-markup.js { type="module" }
+---
+
+
+
+# Basic usage
+
+You will need to include the `prism.css` and `prism.js` files you [downloaded](/download/) in your page. Example:
+
+<!DOCTYPE html>
+<html>
+<head>
+ ...
+ <link href="themes/prism.css" rel="stylesheet" />
+</head>
+<body>
+ ...
+ <script src="prism.js"></script>
+</body>
+</html>
+
+Prism does its best to encourage good authoring practices. Therefore, it only works with `` elements, since marking up code without a `` element is semantically invalid. [According to the HTML5 spec](https://www.w3.org/TR/html52/textlevel-semantics.html#the-code-element), the recommended way to define a code language is a `language-xxxx` class, which is what Prism uses. Alternatively, Prism also supports a shorter version: `lang-xxxx`.
+
+The [recommended way to mark up a code block](https://www.w3.org/TR/html5/grouping-content.html#the-pre-element) (both for semantics and for Prism) is a `` element with a `` element inside, like so:
+
+```html
+p { color: red }
+```
+
+If you use that pattern, the `` will automatically get the `language-xxxx` class (if it doesn’t already have it) and will be styled as a code block.
+
+Inline code snippets are done like this:
+
+```html
+p { color: red }
+```
+
+**Note**: You have to escape all `<` and `&` characters inside `` elements (code blocks and inline snippets) with `<` and `&` respectively, or else the browser might interpret them as an HTML tag or [entity](https://developer.mozilla.org/en-US/docs/Glossary/Entity). If you have large portions of HTML code, you can use the [Unescaped Markup plugin](/plugins/unescaped-markup/) to work around this.
+
+## Language inheritance
+
+To make things easier however, Prism assumes that the language class is inherited. Therefore, if multiple `` elements have the same language, you can add the `language-xxxx` class on one of their common ancestors. This way, you can also define a document-wide default language, by adding a `language-xxxx` class on the `` or `` element.
+
+If you want to opt-out of highlighting a `` element that inherits its language, you can add the `language-none` class to it. The `none` language can also be inherited to disable highlighting for the element with the class and all of its descendants.
+
+If you want to opt-out of highlighting but still use plugins like [Show Invisibles](/plugins/show-invisibles/), use `language-plain` class instead.
+
+## Manual highlighting
+
+If you want to prevent any elements from being automatically highlighted and instead use the [API](/extending/#api-documentation), you can set [`Prism.config.manual`{ .language-javascript }](/api/interfaces/types.PrismConfig.html#manual) to `true`{ .language-javascript } before the `DOMContentLoaded` event is fired. By setting the `data-manual` attribute on the `
+```
+
+or
+
+```html
+
+
+```
+
+## Usage with CDNs { #basic-usage-cdn }
+
+In combination with CDNs, we recommend using the [Autoloader plugin](/plugins/autoloader) which automatically loads languages when necessary.
+
+The setup of the Autoloader, will look like the following. You can also add your own themes of course.
+
+<!DOCTYPE html>
+<html>
+<head>
+ ...
+ <link href="https://{% raw %}{{cdn}}{% endraw %}/prismjs@v1.x/themes/prism.css" rel="stylesheet" />
+</head>
+<body>
+ ...
+ <script src="https://{% raw %}{{cdn}}{% endraw %}/prismjs@v1.x/components/prism-core.min.js"></script>
+<script src="https://{% raw %}{{cdn}}{% endraw %}/prismjs@v1.x/plugins/autoloader/prism-autoloader.min.js"></script>
+</body>
+</html>
+
+Please note that links in the above code sample serve as placeholders. You have to replace them with valid links to the CDN of your choice.
+
+CDNs which provide PrismJS are e.g. [cdnjs](https://cdnjs.com/libraries/prism), [jsDelivr](https://www.jsdelivr.com/package/npm/prismjs), and [UNPKG](https://unpkg.com/browse/prismjs@1/).
+
+## Usage with Webpack, Browserify, & Other Bundlers { #basic-usage-bundlers }
+
+If you want to use Prism with a bundler, install Prism with `npm`:
+
+```bash
+$ npm install prismjs
+```
+
+You can then `import` into your bundle:
+
+```js
+import Prism from "prismjs";
+```
+
+To make it easy to configure your Prism instance with only the languages and plugins you need, use the babel plugin, [babel-plugin-prismjs](https://github.com/mAAdhaTTah/babel-plugin-prismjs). This will allow you to load the minimum number of languages and plugins to satisfy your needs. See that plugin's documentation for configuration details.
+
+## Usage with Node { #basic-usage-node }
+
+If you want to use Prism on the server or through the command line, Prism can be used with Node.js as well. This might be useful if you're trying to generate static HTML pages with highlighted code for environments that don't support browser-side JS, like [AMP pages](https://www.ampproject.org/).
+
+Example:
+
+```js
+const Prism = require("prismjs");
+
+// The code snippet you want to highlight, as a string
+const code = `var data = 1;`;
+
+// Returns a highlighted HTML string
+const html = Prism.highlight(code, Prism.languages.javascript, "javascript");
+```
+
+Requiring `prismjs` will load the default languages: `markup`, `css`, `clike` and `javascript`. You can load more languages with the `loadLanguages()`{ .language-javascript } utility, which will automatically handle any required dependencies.
+
+Example:
+
+```js
+const Prism = require("prismjs");
+const loadLanguages = require("prismjs/components/");
+loadLanguages(["haml"]);
+
+// The code snippet you want to highlight, as a string
+const code = `= ['hi', 'there', 'reader!'].join " "`;
+
+// Returns a highlighted HTML string
+const html = Prism.highlight(code, Prism.languages.haml, "haml");
+```
+
+**Note**: Do _not_ use `loadLanguages()`{ .language-javascript } with Webpack or another bundler, as this will cause Webpack to include all languages and plugins. Use the babel plugin described above.
+
+**Note**: `loadLanguages()`{ .language-javascript } will ignore unknown languages and log warning messages to the console. You can prevent the warnings by setting `loadLanguages.silent = true`{ .language-javascript }.
+
+
diff --git a/docs/supported-languages.md b/docs/supported-languages.md
new file mode 100644
index 00000000..fedec7d3
--- /dev/null
+++ b/docs/supported-languages.md
@@ -0,0 +1,23 @@
+---
+title: Supported languages
+tagline: Every language Prism highlights, and the classes that select it.
+---
+
+
+
+This is the list of all {{ prism.languages | length }} languages currently supported by Prism, with their corresponding alias, to use in place of `xxxx` in the `language-xxxx` (or `lang-xxxx`) class:
+
+
+ {% for id, language in prism.languages -%}
+ -
+ {{ language.title }} —
{{ id }}
+ {%- for alias, title in language.aliasTitles -%}
+ , {{ alias }}
+ {%- endfor %}
+
+ {% endfor %}
+
+
+Couldn’t find the language you were looking for? [Request it](https://github.com/PrismJS/prism/issues)!
+
+
diff --git a/test-suite.md b/docs/test-suite.md
similarity index 99%
rename from test-suite.md
rename to docs/test-suite.md
index 7d7bc3bd..402cd0b3 100644
--- a/test-suite.md
+++ b/docs/test-suite.md
@@ -1,8 +1,6 @@
---
title: Running the test suite
tagline: Prism has a test suite, that ensures that the correct tokens are matched.
-body_classes: language-javascript
-resources: /languages/bash.js { type="module" }
---
diff --git a/test.md b/docs/test.md
similarity index 85%
rename from test.md
rename to docs/test.md
index efc0ebd7..394586dd 100644
--- a/test.md
+++ b/docs/test.md
@@ -2,11 +2,10 @@
title: Test drive
tagline: Take Prism for a spin!
resources:
- - /assets/test-drive.js
- - /plugins/autoloader.js { type="module" }
+ - /assets/test-drive.js { type="module" }
+ - /plugins/autoloader.js { type="module" }
---
-