diff --git a/package-lock.json b/package-lock.json index 4ed3dbdf9..1cd1abe39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "sass-site", "version": "2.0.0", "license": "MIT", + "dependencies": { + "seedrandom": "^3.0.5" + }, "devDependencies": { "@11ty/eleventy": "^2.0.1", "@11ty/eleventy-plugin-rss": "^1.2.0", @@ -29,6 +32,7 @@ "@types/markdown-it-footnote": "^3.0.0", "@types/node": "^16", "@types/prismjs": "^1.26.0", + "@types/seedrandom": "^3.0.5", "@types/semver": "^7.5.0", "cheerio": "^1.0.0-rc.12", "date-fns": "^2.30.0", @@ -2583,6 +2587,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-kopEpYpFQvQdYsZkZVwht/0THHmTFFYXDaqV/lM45eweJ8kcGVDgZHs0RVTolSq55UPZNmjhKc9r7UvLu/mQQg==", + "dev": true + }, "node_modules/@types/semver": { "version": "7.5.0", "dev": true, @@ -7597,6 +7607,11 @@ "node": ">=4" } }, + "node_modules/seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, "node_modules/semver": { "version": "7.5.2", "dev": true, @@ -10373,6 +10388,12 @@ "version": "1.20.2", "dev": true }, + "@types/seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-kopEpYpFQvQdYsZkZVwht/0THHmTFFYXDaqV/lM45eweJ8kcGVDgZHs0RVTolSq55UPZNmjhKc9r7UvLu/mQQg==", + "dev": true + }, "@types/semver": { "version": "7.5.0", "dev": true @@ -13477,6 +13498,11 @@ "kind-of": "^6.0.0" } }, + "seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, "semver": { "version": "7.5.2", "dev": true, diff --git a/package.json b/package.json index e4800642c..ba5215394 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "build:sass": "sass --style=compressed ./source/assets/sass/sass.scss:./source/assets/dist/css/sass.css ./source/assets/sass/noscript.scss:./source/assets/dist/css/noscript.css", "watch:sass": "sass --watch ./source/assets/sass/sass.scss:./source/assets/dist/css/sass.css ./source/assets/sass/noscript.scss:./source/assets/dist/css/noscript.css", "build-dev:scripts": "rollup -c", - "build-prod:scripts": "BABEL_ENV=production rollup -c", + "build-prod:scripts": "NODE_ENV=production BABEL_ENV=production rollup -c", "watch:scripts": "npm run build-dev:scripts -- -w", "build:typedoc": "./tool/typedoc-build.sh", "build:11ty": "NODE_OPTIONS='-r ts-node/register' eleventy", @@ -60,6 +60,7 @@ "@types/markdown-it-footnote": "^3.0.0", "@types/node": "^16", "@types/prismjs": "^1.26.0", + "@types/seedrandom": "^3.0.5", "@types/semver": "^7.5.0", "cheerio": "^1.0.0-rc.12", "date-fns": "^2.30.0", @@ -89,5 +90,8 @@ "ts-node": "^10.9.1", "typescript": "^5.1.3", "typogr": "^0.6.8" + }, + "dependencies": { + "seedrandom": "^3.0.5" } } diff --git a/source/documentation/interpolation.md b/source/documentation/interpolation.md index ec0b9c768..f92bfc794 100644 --- a/source/documentation/interpolation.md +++ b/source/documentation/interpolation.md @@ -63,6 +63,8 @@ interpolation in SassScript always returns an unquoted string. [unquoted strings]: /documentation/values/strings#unquoted [slash-separated values]: /documentation/operators/numeric#slash-separated-values + + {% codeExample 'interpolation-sass-script' %} @mixin inline-animation($duration) { $name: inline-#{unique-id()}; @@ -101,6 +103,20 @@ interpolation in SassScript always returns an unquoted string. background-color: yellow to background-color: red + === + .pulse { + animation-name: inline-uifpe6h; + animation-duration: 2s; + animation-iteration-count: infinite; + } + @keyframes inline-uifpe6h { + from { + background-color: yellow; + } + to { + background-color: red; + } + } {% endcodeExample %} {% funFact %} diff --git a/source/helpers/type.ts b/source/helpers/type.ts index 27d6f09b3..390f24cf1 100644 --- a/source/helpers/type.ts +++ b/source/helpers/type.ts @@ -1,10 +1,13 @@ import {LoremIpsum} from 'lorem-ipsum'; +import seedrandom from 'seedrandom'; import truncate from 'truncate-html'; import {typogrify} from 'typogr'; import {markdownEngine} from './engines'; -const lorem = new LoremIpsum(); +const lorem = new LoremIpsum({ + random: seedrandom("Feelin' Sassy!"), +}); /** * Returns block of generated `lorem ipsum` text. diff --git a/source/source.11tydata.js b/source/source.11tydata.js new file mode 100644 index 000000000..4e663dc01 --- /dev/null +++ b/source/source.11tydata.js @@ -0,0 +1,3 @@ +if (process.env.NODE_ENV === 'production') { + module.exports = {date: 'git Last Modified'}; +} diff --git a/tool/typedoc-theme.js b/tool/typedoc-theme.js index 44304f092..05baae526 100644 --- a/tool/typedoc-theme.js +++ b/tool/typedoc-theme.js @@ -1,5 +1,12 @@ -// eslint-disable-next-line node/no-missing-require -const {DefaultTheme, DefaultThemeRenderContext, JSX} = require('typedoc'); +const { + DefaultTheme, + DefaultThemeRenderContext, + JSX, + UrlMapping, + // eslint-disable-next-line node/no-missing-require +} = require('typedoc'); +const child_process = require('child_process'); +const fs = require('fs'); function bind(fn, first) { return (...r) => fn(first, ...r); @@ -129,7 +136,40 @@ class SassSiteTheme extends DefaultTheme { return this.contextCache; } + getUrls(project) { + const urls = super.getUrls(project); + + // Most pages in the docs have their date set based on their last git + // commit, but that doesn't work for the generated TypeDoc. To avoid having + // a bunch of churn in the sitemap for these files, we set their date to the + // last modified date for the entire directory. + if (fs.existsSync('js-api-doc')) { + const lastModified = child_process + .execSync('git log -1 --date=iso-strict --format=%cd js-api-doc', { + encoding: 'utf8', + }) + .trim(); + urls.push( + new UrlMapping( + 'js-api.11tydata.json', + // This isn't actually based on a TypeDoc model, but if we don't + // provide a real one TypeDoc will crash. See TypeStrong/typedoc#2318. + urls[0].model, + () => + JSON.stringify({ + date: lastModified, + }) + ) + ); + } + + return urls; + } + render(page, template) { + // This is js-api.11tydata.json. + if (page.url === 'js-api.11tydata.json') return template(); + const context = this.getRenderContext(page); // The default header includes a search bar that we don't want, so we just