diff --git a/.eslintrc.json b/.eslintrc.json index 5436d43f4d12..b4262cf6ede7 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -197,6 +197,15 @@ "unicorn/no-array-for-each": "off" } }, + { + "files": [ + "site/assets/js/**" + ], + "parserOptions": { + "sourceType": "module", + "ecmaVersion": 2020 + } + }, { "files": [ "**/*.md" diff --git a/hugo.yml b/hugo.yml index a6de700c0c44..1ff261b04228 100644 --- a/hugo.yml +++ b/hugo.yml @@ -8,8 +8,6 @@ security: getenv: - ^HUGO_ - NETLIFY - gotemplates: - allowActionJSTmpl: true markup: goldmark: @@ -21,6 +19,9 @@ markup: startLevel: 2 endLevel: 6 +build: + noJSConfigInAssets: true + buildDrafts: true buildFuture: true @@ -44,6 +45,8 @@ module: target: layouts - source: site/static target: static + - source: node_modules/@docsearch/css + target: assets/scss/@docsearch/css - source: site/static/docs/5.3/assets/img/favicons/apple-touch-icon.png target: static/apple-touch-icon.png - source: site/static/docs/5.3/assets/img/favicons/favicon.ico @@ -70,6 +73,11 @@ params: analytics: fathom_site: "ITUSEYJG" + algolia: + appId: "AK7KMZKZHQ" + apiKey: "3151f502c7b9e9dafd5e6372b691a24e" + indexName: "bootstrap" + download: source: "https://github.com/twbs/bootstrap/archive/v5.3.3.zip" dist: "https://github.com/twbs/bootstrap/releases/download/v5.3.3/bootstrap-5.3.3-dist.zip" diff --git a/package-lock.json b/package-lock.json index 56ffe1e60e91..b7d368c30c40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,14 +22,17 @@ "@babel/cli": "^7.23.9", "@babel/core": "^7.24.0", "@babel/preset-env": "^7.24.0", + "@docsearch/js": "^3.6.0", "@popperjs/core": "^2.11.8", "@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-replace": "^5.0.5", + "@stackblitz/sdk": "^1.9.0", "autoprefixer": "^10.4.18", "bundlewatch": "^0.3.3", "clean-css-cli": "^5.6.3", + "clipboard": "^2.0.11", "cross-env": "^7.0.3", "eslint": "^8.57.0", "eslint-config-xo": "^0.44.0", @@ -88,6 +91,180 @@ "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", "dev": true }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "dev": true, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.22.1.tgz", + "integrity": "sha512-Sw6IAmOCvvP6QNgY9j+Hv09mvkvEIDKjYW8ow0UDDAxSXy664RBNQk3i/0nt7gvceOJ6jGmOTimaZoY1THmU7g==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.22.1" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.22.1.tgz", + "integrity": "sha512-TJMBKqZNKYB9TptRRjSUtevJeQVXRmg6rk9qgFKWvOy8jhCPdyNZV1nB3SKGufzvTVbomAukFR8guu/8NRKBTA==", + "dev": true + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.22.1.tgz", + "integrity": "sha512-ve+6Ac2LhwpufuWavM/aHjLoNz/Z/sYSgNIXsinGofWOysPilQZPUetqLj8vbvi+DHZZaYSEP9H5SRVXnpsNNw==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.22.1" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.22.1.tgz", + "integrity": "sha512-k8m+oegM2zlns/TwZyi4YgCtyToackkOpE+xCaKCYfBfDtdGOaVZCM5YvGPtK+HGaJMIN/DoTL8asbM3NzHonw==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.22.1", + "@algolia/client-search": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.22.1.tgz", + "integrity": "sha512-1ssi9pyxyQNN4a7Ji9R50nSdISIumMFDwKNuwZipB6TkauJ8J7ha/uO60sPJFqQyqvvI+px7RSNRQT3Zrvzieg==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.22.1", + "@algolia/client-search": "4.22.1", + "@algolia/requester-common": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.22.1.tgz", + "integrity": "sha512-IvaL5v9mZtm4k4QHbBGDmU3wa/mKokmqNBqPj0K7lcR8ZDKzUorhcGp/u8PkPC/e0zoHSTvRh7TRkGX3Lm7iOQ==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.22.1.tgz", + "integrity": "sha512-sl+/klQJ93+4yaqZ7ezOttMQ/nczly/3GmgZXJ1xmoewP5jmdP/X/nV5U7EHHH3hCUEHeN7X1nsIhGPVt9E1cQ==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.22.1", + "@algolia/requester-common": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.22.1.tgz", + "integrity": "sha512-yb05NA4tNaOgx3+rOxAmFztgMTtGBi97X7PC3jyNeGiwkAjOZc2QrdZBYyIdcDLoI09N0gjtpClcackoTN0gPA==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.22.1", + "@algolia/requester-common": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, + "node_modules/@algolia/logger-common": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.22.1.tgz", + "integrity": "sha512-OnTFymd2odHSO39r4DSWRFETkBufnY2iGUZNrMXpIhF5cmFE8pGoINNPzwg02QLBlGSaLqdKy0bM8S0GyqPLBg==", + "dev": true + }, + "node_modules/@algolia/logger-console": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.22.1.tgz", + "integrity": "sha512-O99rcqpVPKN1RlpgD6H3khUWylU24OXlzkavUAMy6QZd1776QAcauE3oP8CmD43nbaTjBexZj2nGsBH9Tc0FVA==", + "dev": true, + "dependencies": { + "@algolia/logger-common": "4.22.1" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.22.1.tgz", + "integrity": "sha512-dtQGYIg6MteqT1Uay3J/0NDqD+UciHy3QgRbk7bNddOJu+p3hzjTRYESqEnoX/DpEkaNYdRHUKNylsqMpgwaEw==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.22.1" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.22.1.tgz", + "integrity": "sha512-dgvhSAtg2MJnR+BxrIFqlLtkLlVVhas9HgYKMk2Uxiy5m6/8HZBL40JVAMb2LovoPFs9I/EWIoFVjOrFwzn5Qg==", + "dev": true + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.22.1.tgz", + "integrity": "sha512-JfmZ3MVFQkAU+zug8H3s8rZ6h0ahHZL/SpMaSasTCGYR5EEJsCc8SI5UZ6raPN2tjxa5bxS13BRpGSBUens7EA==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.22.1" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.22.1.tgz", + "integrity": "sha512-kzWgc2c9IdxMa3YqA6TN0NW5VrKYYW/BELIn7vnLyn+U/RFdZ4lxxt9/8yq3DKV5snvoDzzO4ClyejZRdV3lMQ==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.22.1", + "@algolia/logger-common": "4.22.1", + "@algolia/requester-common": "4.22.1" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -1879,6 +2056,54 @@ "postcss-selector-parser": "^6.0.13" } }, + "node_modules/@docsearch/css": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", + "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==", + "dev": true + }, + "node_modules/@docsearch/js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.6.0.tgz", + "integrity": "sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==", + "dev": true, + "dependencies": { + "@docsearch/react": "3.6.0", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", + "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.0", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2596,6 +2821,12 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", "dev": true }, + "node_modules/@stackblitz/sdk": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@stackblitz/sdk/-/sdk-1.9.0.tgz", + "integrity": "sha512-3m6C7f8pnR5KXys/Hqx2x6ylnpqOak6HtnZI6T5keEO0yT+E4Spkw37VEbdwuC+2oxmjdgq6YZEgiKX7hM1GmQ==", + "dev": true + }, "node_modules/@stylistic/stylelint-config": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@stylistic/stylelint-config/-/stylelint-config-1.0.1.tgz", @@ -3013,6 +3244,28 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/algoliasearch": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.22.1.tgz", + "integrity": "sha512-jwydKFQJKIx9kIZ8Jm44SdpigFwRGPESaxZBaHSV0XWN2yBJAOT4mT7ppvlrpA4UGzz92pqFnVKr/kaZXrcreg==", + "dev": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.22.1", + "@algolia/cache-common": "4.22.1", + "@algolia/cache-in-memory": "4.22.1", + "@algolia/client-account": "4.22.1", + "@algolia/client-analytics": "4.22.1", + "@algolia/client-common": "4.22.1", + "@algolia/client-personalization": "4.22.1", + "@algolia/client-search": "4.22.1", + "@algolia/logger-common": "4.22.1", + "@algolia/logger-console": "4.22.1", + "@algolia/requester-browser-xhr": "4.22.1", + "@algolia/requester-common": "4.22.1", + "@algolia/requester-node-http": "4.22.1", + "@algolia/transporter": "4.22.1" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4028,6 +4281,17 @@ "node": ">=4" } }, + "node_modules/clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "dev": true, + "dependencies": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -4421,6 +4685,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "dev": true + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -6119,6 +6389,15 @@ "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", "dev": true }, + "node_modules/good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "dev": true, + "dependencies": { + "delegate": "^3.1.2" + } + }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -9147,6 +9426,16 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/preact": { + "version": "10.19.6", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.19.6.tgz", + "integrity": "sha512-gympg+T2Z1fG1unB8NH29yHJwnEaCH37Z32diPDku316OTnRPeMbiRV9kTrfZpocXjdfnWuFUl/Mj4BHaf6gnw==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -9905,6 +10194,13 @@ "node": ">=18" } }, + "node_modules/search-insights": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.13.0.tgz", + "integrity": "sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==", + "dev": true, + "peer": true + }, "node_modules/seek-bzip": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", @@ -9924,6 +10220,12 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", + "dev": true + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -11076,6 +11378,12 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "dev": true + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", diff --git a/package.json b/package.json index 10491932e1ff..a8ca542df099 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "docs-serve": "hugo server --port 9001 --disableFastRender --noHTTPCache --renderToMemory --printPathWarnings --printUnusedTemplates", "docs-serve-only": "npx sirv-cli _site --port 9001", "lockfile-lint": "lockfile-lint --allowed-hosts npm --allowed-schemes https: --empty-hostname false --type npm --path package-lock.json", - "update-deps": "ncu -u -x jasmine,karma-browserstack-launcher,karma-rollup-preprocessor && echo Manually update site/assets/js/vendor", + "update-deps": "ncu -u -x jasmine,karma-browserstack-launcher,karma-rollup-preprocessor", "release": "npm-run-all dist release-sri docs-build release-zip*", "release-sri": "node build/generate-sri.mjs", "release-version": "node build/change-version.mjs", @@ -106,14 +106,17 @@ "@babel/cli": "^7.23.9", "@babel/core": "^7.24.0", "@babel/preset-env": "^7.24.0", + "@docsearch/js": "^3.6.0", "@popperjs/core": "^2.11.8", "@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-replace": "^5.0.5", + "@stackblitz/sdk": "^1.9.0", "autoprefixer": "^10.4.18", "bundlewatch": "^0.3.3", "clean-css-cli": "^5.6.3", + "clipboard": "^2.0.11", "cross-env": "^7.0.3", "eslint": "^8.57.0", "eslint-config-xo": "^0.44.0", diff --git a/site/assets/js/application.js b/site/assets/js/application.js index a16defbd4431..ef706ed4d14b 100644 --- a/site/assets/js/application.js +++ b/site/assets/js/application.js @@ -9,22 +9,12 @@ * For details, see https://creativecommons.org/licenses/by/3.0/. */ -(() => { - 'use strict' +/* eslint-disable import/no-unresolved */ +import sidebarScroll from 'js/partials/sidebar.js' +import codeExamples from 'js/partials/code-examples.js' +import snippets from 'js/partials/snippets.js' +/* eslint-enable import/no-unresolved */ - // Scroll the active sidebar link into view - const sidenav = document.querySelector('.bd-sidebar') - const sidenavActiveLink = document.querySelector('.bd-links-nav .active') - - if (sidenav && sidenavActiveLink) { - const sidenavHeight = sidenav.clientHeight - const sidenavActiveLinkTop = sidenavActiveLink.offsetTop - const sidenavActiveLinkHeight = sidenavActiveLink.clientHeight - const viewportTop = sidenavActiveLinkTop - const viewportBottom = viewportTop - sidenavHeight + sidenavActiveLinkHeight - - if (sidenav.scrollTop > viewportTop || sidenav.scrollTop < viewportBottom) { - sidenav.scrollTop = viewportTop - (sidenavHeight / 2) + (sidenavActiveLinkHeight / 2) - } - } -})() +sidebarScroll() +codeExamples() +snippets() diff --git a/site/assets/js/code-examples.js b/site/assets/js/partials/code-examples.js similarity index 97% rename from site/assets/js/code-examples.js rename to site/assets/js/partials/code-examples.js index 3462da59badd..d81191a96565 100644 --- a/site/assets/js/code-examples.js +++ b/site/assets/js/partials/code-examples.js @@ -2,18 +2,18 @@ // IT'S ALL JUST JUNK FOR OUR DOCS! // ++++++++++++++++++++++++++++++++++++++++++ -/*! +/* * JavaScript for Bootstrap's docs (https://getbootstrap.com/) * Copyright 2011-2024 The Bootstrap Authors * Licensed under the Creative Commons Attribution 3.0 Unported License. * For details, see https://creativecommons.org/licenses/by/3.0/. */ -/* global ClipboardJS: false, bootstrap: false */ +/* global bootstrap: false */ -(() => { - 'use strict' +import ClipboardJS from 'clipboard' +export default () => { // Insert copy to clipboard button before .highlight const btnTitle = 'Copy to clipboard' const btnEdit = 'Edit on StackBlitz' @@ -87,4 +87,4 @@ tooltipBtn.setContent({ '.tooltip-inner': btnTitle }) }, { once: true }) }) -})() +} diff --git a/site/assets/js/partials/sidebar.js b/site/assets/js/partials/sidebar.js new file mode 100644 index 000000000000..c43f4148197c --- /dev/null +++ b/site/assets/js/partials/sidebar.js @@ -0,0 +1,30 @@ +// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT +// IT'S ALL JUST JUNK FOR OUR DOCS! +// ++++++++++++++++++++++++++++++++++++++++++ + +/* + * JavaScript for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2011-2024 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * For details, see https://creativecommons.org/licenses/by/3.0/. + */ + +export default () => { + // Scroll the active sidebar link into view + const sidenav = document.querySelector('.bd-sidebar') + const sidenavActiveLink = document.querySelector('.bd-links-nav .active') + + if (!sidenav || !sidenavActiveLink) { + return + } + + const sidenavHeight = sidenav.clientHeight + const sidenavActiveLinkTop = sidenavActiveLink.offsetTop + const sidenavActiveLinkHeight = sidenavActiveLink.clientHeight + const viewportTop = sidenavActiveLinkTop + const viewportBottom = viewportTop - sidenavHeight + sidenavActiveLinkHeight + + if (sidenav.scrollTop > viewportTop || sidenav.scrollTop < viewportBottom) { + sidenav.scrollTop = viewportTop - (sidenavHeight / 2) + (sidenavActiveLinkHeight / 2) + } +} diff --git a/site/assets/js/partials/snippets.js b/site/assets/js/partials/snippets.js new file mode 100644 index 000000000000..1771612cf0e0 --- /dev/null +++ b/site/assets/js/partials/snippets.js @@ -0,0 +1,168 @@ +// NOTICE!!! Initially embedded in our docs this JavaScript +// file contains elements that can help you create reproducible +// use cases in StackBlitz for instance. +// In a real project please adapt this content to your needs. +// ++++++++++++++++++++++++++++++++++++++++++ + +/* + * JavaScript for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2011-2024 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * For details, see https://creativecommons.org/licenses/by/3.0/. + */ + +/* global bootstrap: false */ + +export default () => { + // -------- + // Tooltips + // -------- + // Instantiate all tooltips in a docs or StackBlitz + document.querySelectorAll('[data-bs-toggle="tooltip"]') + .forEach(tooltip => { + new bootstrap.Tooltip(tooltip) + }) + + // -------- + // Popovers + // -------- + // Instantiate all popovers in docs or StackBlitz + document.querySelectorAll('[data-bs-toggle="popover"]') + .forEach(popover => { + new bootstrap.Popover(popover) + }) + + // ------------------------------- + // Toasts + // ------------------------------- + // Used by 'Placement' example in docs or StackBlitz + const toastPlacement = document.getElementById('toastPlacement') + if (toastPlacement) { + document.getElementById('selectToastPlacement').addEventListener('change', function () { + if (!toastPlacement.dataset.originalClass) { + toastPlacement.dataset.originalClass = toastPlacement.className + } + + toastPlacement.className = `${toastPlacement.dataset.originalClass} ${this.value}` + }) + } + + // Instantiate all toasts in docs pages only + document.querySelectorAll('.bd-example .toast') + .forEach(toastNode => { + const toast = new bootstrap.Toast(toastNode, { + autohide: false + }) + + toast.show() + }) + + // Instantiate all toasts in docs pages only + // js-docs-start live-toast + const toastTrigger = document.getElementById('liveToastBtn') + const toastLiveExample = document.getElementById('liveToast') + + if (toastTrigger) { + const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample) + toastTrigger.addEventListener('click', () => { + toastBootstrap.show() + }) + } + // js-docs-end live-toast + + // ------------------------------- + // Alerts + // ------------------------------- + // Used in 'Show live alert' example in docs or StackBlitz + + // js-docs-start live-alert + const alertPlaceholder = document.getElementById('liveAlertPlaceholder') + const appendAlert = (message, type) => { + const wrapper = document.createElement('div') + wrapper.innerHTML = [ + `' + ].join('') + + alertPlaceholder.append(wrapper) + } + + const alertTrigger = document.getElementById('liveAlertBtn') + if (alertTrigger) { + alertTrigger.addEventListener('click', () => { + appendAlert('Nice, you triggered this alert message!', 'success') + }) + } + // js-docs-end live-alert + + // -------- + // Carousels + // -------- + // Instantiate all non-autoplaying carousels in docs or StackBlitz + document.querySelectorAll('.carousel:not([data-bs-ride="carousel"])') + .forEach(carousel => { + bootstrap.Carousel.getOrCreateInstance(carousel) + }) + + // ------------------------------- + // Checks & Radios + // ------------------------------- + // Indeterminate checkbox example in docs and StackBlitz + document.querySelectorAll('.bd-example-indeterminate [type="checkbox"]') + .forEach(checkbox => { + if (checkbox.id.includes('Indeterminate')) { + checkbox.indeterminate = true + } + }) + + // ------------------------------- + // Links + // ------------------------------- + // Disable empty links in docs examples only + document.querySelectorAll('.bd-content [href="#"]') + .forEach(link => { + link.addEventListener('click', event => { + event.preventDefault() + }) + }) + + // ------------------------------- + // Modal + // ------------------------------- + // Modal 'Varying modal content' example in docs and StackBlitz + // js-docs-start varying-modal-content + const exampleModal = document.getElementById('exampleModal') + if (exampleModal) { + exampleModal.addEventListener('show.bs.modal', event => { + // Button that triggered the modal + const button = event.relatedTarget + // Extract info from data-bs-* attributes + const recipient = button.getAttribute('data-bs-whatever') + // If necessary, you could initiate an Ajax request here + // and then do the updating in a callback. + + // Update the modal's content. + const modalTitle = exampleModal.querySelector('.modal-title') + const modalBodyInput = exampleModal.querySelector('.modal-body input') + + modalTitle.textContent = `New message to ${recipient}` + modalBodyInput.value = recipient + }) + } + // js-docs-end varying-modal-content + + // ------------------------------- + // Offcanvas + // ------------------------------- + // 'Offcanvas components' example in docs only + const myOffcanvas = document.querySelectorAll('.bd-example-offcanvas .offcanvas') + if (myOffcanvas) { + myOffcanvas.forEach(offcanvas => { + offcanvas.addEventListener('show.bs.offcanvas', event => { + event.preventDefault() + }, false) + }) + } +} diff --git a/site/assets/js/search.js b/site/assets/js/search.js index b095d3bbd95d..48047abc8750 100644 --- a/site/assets/js/search.js +++ b/site/assets/js/search.js @@ -2,21 +2,31 @@ // IT'S ALL JUST JUNK FOR OUR DOCS! // ++++++++++++++++++++++++++++++++++++++++++ -(() => { - 'use strict' +/*! + * JavaScript for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2024 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * For details, see https://creativecommons.org/licenses/by/3.0/. + */ + +import docsearch from '@docsearch/js' +// https://gohugo.io/hugo-pipes/js/#options +// eslint-disable-next-line import/no-unresolved +import { appId, apiKey, indexName } from '@params'; +(() => { const searchElement = document.getElementById('docsearch') - if (!window.docsearch || !searchElement) { + if (!searchElement) { return } const siteDocsVersion = searchElement.getAttribute('data-bd-docs-version') - window.docsearch({ - apiKey: '3151f502c7b9e9dafd5e6372b691a24e', - indexName: 'bootstrap', - appId: 'AK7KMZKZHQ', + docsearch({ + apiKey, + indexName, + appId, container: searchElement, searchParameters: { facetFilters: [`version:${siteDocsVersion}`] diff --git a/site/assets/js/snippets.js b/site/assets/js/snippets.js index 94d8f6deeee1..3fce5e437fe9 100644 --- a/site/assets/js/snippets.js +++ b/site/assets/js/snippets.js @@ -1,170 +1,15 @@ -// NOTICE!!! Initially embedded in our docs this JavaScript -// file contains elements that can help you create reproducible -// use cases in StackBlitz for instance. -// In a real project please adapt this content to your needs. -// ++++++++++++++++++++++++++++++++++++++++++ - -/*! +/* * JavaScript for Bootstrap's docs (https://getbootstrap.com/) * Copyright 2011-2024 The Bootstrap Authors * Licensed under the Creative Commons Attribution 3.0 Unported License. * For details, see https://creativecommons.org/licenses/by/3.0/. */ -/* global bootstrap: false */ - -(() => { - 'use strict' - - // -------- - // Tooltips - // -------- - // Instantiate all tooltips in a docs or StackBlitz - document.querySelectorAll('[data-bs-toggle="tooltip"]') - .forEach(tooltip => { - new bootstrap.Tooltip(tooltip) - }) - - // -------- - // Popovers - // -------- - // Instantiate all popovers in docs or StackBlitz - document.querySelectorAll('[data-bs-toggle="popover"]') - .forEach(popover => { - new bootstrap.Popover(popover) - }) - - // ------------------------------- - // Toasts - // ------------------------------- - // Used by 'Placement' example in docs or StackBlitz - const toastPlacement = document.getElementById('toastPlacement') - if (toastPlacement) { - document.getElementById('selectToastPlacement').addEventListener('change', function () { - if (!toastPlacement.dataset.originalClass) { - toastPlacement.dataset.originalClass = toastPlacement.className - } - - toastPlacement.className = `${toastPlacement.dataset.originalClass} ${this.value}` - }) - } - - // Instantiate all toasts in docs pages only - document.querySelectorAll('.bd-example .toast') - .forEach(toastNode => { - const toast = new bootstrap.Toast(toastNode, { - autohide: false - }) - - toast.show() - }) - - // Instantiate all toasts in docs pages only - // js-docs-start live-toast - const toastTrigger = document.getElementById('liveToastBtn') - const toastLiveExample = document.getElementById('liveToast') - - if (toastTrigger) { - const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample) - toastTrigger.addEventListener('click', () => { - toastBootstrap.show() - }) - } - // js-docs-end live-toast - - // ------------------------------- - // Alerts - // ------------------------------- - // Used in 'Show live alert' example in docs or StackBlitz - - // js-docs-start live-alert - const alertPlaceholder = document.getElementById('liveAlertPlaceholder') - const appendAlert = (message, type) => { - const wrapper = document.createElement('div') - wrapper.innerHTML = [ - `' - ].join('') - - alertPlaceholder.append(wrapper) - } - - const alertTrigger = document.getElementById('liveAlertBtn') - if (alertTrigger) { - alertTrigger.addEventListener('click', () => { - appendAlert('Nice, you triggered this alert message!', 'success') - }) - } - // js-docs-end live-alert - - // -------- - // Carousels - // -------- - // Instantiate all non-autoplaying carousels in docs or StackBlitz - document.querySelectorAll('.carousel:not([data-bs-ride="carousel"])') - .forEach(carousel => { - bootstrap.Carousel.getOrCreateInstance(carousel) - }) - - // ------------------------------- - // Checks & Radios - // ------------------------------- - // Indeterminate checkbox example in docs and StackBlitz - document.querySelectorAll('.bd-example-indeterminate [type="checkbox"]') - .forEach(checkbox => { - if (checkbox.id.includes('Indeterminate')) { - checkbox.indeterminate = true - } - }) - - // ------------------------------- - // Links - // ------------------------------- - // Disable empty links in docs examples only - document.querySelectorAll('.bd-content [href="#"]') - .forEach(link => { - link.addEventListener('click', event => { - event.preventDefault() - }) - }) - - // ------------------------------- - // Modal - // ------------------------------- - // Modal 'Varying modal content' example in docs and StackBlitz - // js-docs-start varying-modal-content - const exampleModal = document.getElementById('exampleModal') - if (exampleModal) { - exampleModal.addEventListener('show.bs.modal', event => { - // Button that triggered the modal - const button = event.relatedTarget - // Extract info from data-bs-* attributes - const recipient = button.getAttribute('data-bs-whatever') - // If necessary, you could initiate an Ajax request here - // and then do the updating in a callback. - - // Update the modal's content. - const modalTitle = exampleModal.querySelector('.modal-title') - const modalBodyInput = exampleModal.querySelector('.modal-body input') +// Note that this file is not published; we only include it in scrpts.html +// for StackBlitz to work - modalTitle.textContent = `New message to ${recipient}` - modalBodyInput.value = recipient - }) - } - // js-docs-end varying-modal-content +/* eslint-disable import/no-unresolved */ +import snippets from 'js/partials/snippets.js' +/* eslint-enable import/no-unresolved */ - // ------------------------------- - // Offcanvas - // ------------------------------- - // 'Offcanvas components' example in docs only - const myOffcanvas = document.querySelectorAll('.bd-example-offcanvas .offcanvas') - if (myOffcanvas) { - myOffcanvas.forEach(offcanvas => { - offcanvas.addEventListener('show.bs.offcanvas', event => { - event.preventDefault() - }, false) - }) - } -})() +snippets() diff --git a/site/assets/js/stackblitz.js b/site/assets/js/stackblitz.js new file mode 100644 index 000000000000..ff826247489f --- /dev/null +++ b/site/assets/js/stackblitz.js @@ -0,0 +1,66 @@ +// NOTICE!!! Initially embedded in our docs this JavaScript +// file contains elements that can help you create reproducible +// use cases in StackBlitz for instance. +// In a real project please adapt this content to your needs. +// ++++++++++++++++++++++++++++++++++++++++++ + +/*! + * JavaScript for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2024 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * For details, see https://creativecommons.org/licenses/by/3.0/. + */ + +import sdk from '@stackblitz/sdk' +// https://gohugo.io/hugo-pipes/js/#options +import { + cssCdn, docsVersion, jsBundleCdn, jsSnippetFile +} from '@params' // eslint-disable-line import/no-unresolved + +// Open in StackBlitz logic +document.querySelectorAll('.btn-edit').forEach(btn => { + btn.addEventListener('click', event => { + const codeSnippet = event.target.closest('.bd-code-snippet') + const exampleEl = codeSnippet.querySelector('.bd-example') + + const htmlSnippet = exampleEl.innerHTML + const jsSnippet = codeSnippet.querySelector('.btn-edit').getAttribute('data-sb-js-snippet') + // Get extra classes for this example + const classes = Array.from(exampleEl.classList).join(' ') + + openBootstrapSnippet(htmlSnippet, jsSnippet, classes) + }) +}) + +const openBootstrapSnippet = (htmlSnippet, jsSnippet, classes) => { + const indexHtml = ` + + + + + + + Bootstrap Example + <${'script'} defer src="${jsBundleCdn}"> + + + +${htmlSnippet.trimStart().replace(/^/gm, ' ').replace(/^ {4}$/gm, '').trimEnd()} + + + +` + + const project = { + files: { + 'index.html': indexHtml, + ...(jsSnippet && { 'index.js': jsSnippetFile }) + }, + title: 'Bootstrap Example', + description: `Official example from ${window.location.href}`, + template: jsSnippet ? 'javascript' : 'html', + tags: ['bootstrap'] + } + + sdk.openProject(project, { openFile: 'index.html' }) +} diff --git a/site/assets/js/vendor/clipboard.min.js b/site/assets/js/vendor/clipboard.min.js deleted file mode 100644 index 1103f811ed80..000000000000 --- a/site/assets/js/vendor/clipboard.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * clipboard.js v2.0.11 - * https://clipboardjs.com/ - * - * Licensed MIT © Zeno Rocha - */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return b}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),r=n.n(e);function c(t){try{return document.execCommand(t)}catch(t){return}}var a=function(t){t=r()(t);return c("cut"),t};function o(t,e){var n,o,t=(n=t,o="rtl"===document.documentElement.getAttribute("dir"),(t=document.createElement("textarea")).style.fontSize="12pt",t.style.border="0",t.style.padding="0",t.style.margin="0",t.style.position="absolute",t.style[o?"right":"left"]="-9999px",o=window.pageYOffset||document.documentElement.scrollTop,t.style.top="".concat(o,"px"),t.setAttribute("readonly",""),t.value=n,t);return e.container.appendChild(t),e=r()(t),c("copy"),t.remove(),e}var f=function(t){var e=1}} +{{< js-docs name="live-alert" file="site/assets/js/partials/snippets.js" >}} ### Link color diff --git a/site/content/docs/5.3/components/modal.md b/site/content/docs/5.3/components/modal.md index 3ca7cc4d2240..e00931e8162e 100644 --- a/site/content/docs/5.3/components/modal.md +++ b/site/content/docs/5.3/components/modal.md @@ -481,7 +481,7 @@ Below is a live demo followed by example HTML and JavaScript. For more informati {{< /example >}} -{{< js-docs name="varying-modal-content" file="site/assets/js/snippets.js" >}} +{{< js-docs name="varying-modal-content" file="site/assets/js/partials/snippets.js" >}} ### Toggle between modals diff --git a/site/content/docs/5.3/components/toasts.md b/site/content/docs/5.3/components/toasts.md index a7d1cb7130e2..4beae7dc89a2 100644 --- a/site/content/docs/5.3/components/toasts.md +++ b/site/content/docs/5.3/components/toasts.md @@ -87,7 +87,7 @@ Click the button below to show a toast (positioned with our utilities in the low We use the following JavaScript to trigger our live toast demo: -{{< js-docs name="live-toast" file="site/assets/js/snippets.js" >}} +{{< js-docs name="live-toast" file="site/assets/js/partials/snippets.js" >}} ### Translucent diff --git a/site/content/docs/5.3/docsref.md b/site/content/docs/5.3/docsref.md index d0fc42f3db86..6b811f47d16f 100644 --- a/site/content/docs/5.3/docsref.md +++ b/site/content/docs/5.3/docsref.md @@ -46,4 +46,4 @@ sitemap_exclude: true {{< scss-docs name="variable-gradient" file="scss/_variables.scss" >}} -{{< js-docs name="live-toast" file="site/assets/js/snippets.js" >}} +{{< js-docs name="live-toast" file="site/assets/js/partials/snippets.js" >}} diff --git a/site/content/docs/5.3/examples/cheatsheet-rtl/index.html b/site/content/docs/5.3/examples/cheatsheet-rtl/index.html index eeb825fad3fb..824afb4f23dc 100644 --- a/site/content/docs/5.3/examples/cheatsheet-rtl/index.html +++ b/site/content/docs/5.3/examples/cheatsheet-rtl/index.html @@ -5,6 +5,7 @@ - "../cheatsheet/cheatsheet.rtl.css" extra_js: - src: "../cheatsheet/cheatsheet.js" + defer: true body_class: "bg-body-tertiary" direction: rtl --- diff --git a/site/content/docs/5.3/examples/cheatsheet/index.html b/site/content/docs/5.3/examples/cheatsheet/index.html index cbe2b745c9ef..ad52ceebb41e 100644 --- a/site/content/docs/5.3/examples/cheatsheet/index.html +++ b/site/content/docs/5.3/examples/cheatsheet/index.html @@ -5,6 +5,7 @@ - "cheatsheet.css" extra_js: - src: "cheatsheet.js" + defer: true body_class: "bg-body-tertiary" --- diff --git a/site/content/docs/5.3/examples/checkout-rtl/index.html b/site/content/docs/5.3/examples/checkout-rtl/index.html index 6516efea61ab..6ec0889e3389 100644 --- a/site/content/docs/5.3/examples/checkout-rtl/index.html +++ b/site/content/docs/5.3/examples/checkout-rtl/index.html @@ -6,6 +6,7 @@ - "../checkout/checkout.css" extra_js: - src: "../checkout/checkout.js" + defer: true body_class: "bg-body-tertiary" --- diff --git a/site/content/docs/5.3/examples/checkout/index.html b/site/content/docs/5.3/examples/checkout/index.html index d39f0f2a41e2..a6ecd813eb17 100644 --- a/site/content/docs/5.3/examples/checkout/index.html +++ b/site/content/docs/5.3/examples/checkout/index.html @@ -5,6 +5,7 @@ - "checkout.css" extra_js: - src: "checkout.js" + defer: true body_class: "bg-body-tertiary" --- diff --git a/site/content/docs/5.3/examples/dashboard-rtl/index.html b/site/content/docs/5.3/examples/dashboard-rtl/index.html index d0a71f67b7ab..a2ccc9e160f2 100644 --- a/site/content/docs/5.3/examples/dashboard-rtl/index.html +++ b/site/content/docs/5.3/examples/dashboard-rtl/index.html @@ -7,7 +7,9 @@ extra_js: - src: "https://cdn.jsdelivr.net/npm/chart.js@4.3.2/dist/chart.umd.js" integrity: "sha384-eI7PSr3L1XLISH8JdDII5YN/njoSsxfbrkCTnJrzXt+ENP5MOVBxD+l6sEG4zoLp" + defer: true - src: "dashboard.js" + defer: true --- diff --git a/site/content/docs/5.3/examples/dashboard/index.html b/site/content/docs/5.3/examples/dashboard/index.html index 508e8b8c4cca..d8941f3684b2 100644 --- a/site/content/docs/5.3/examples/dashboard/index.html +++ b/site/content/docs/5.3/examples/dashboard/index.html @@ -6,7 +6,9 @@ extra_js: - src: "https://cdn.jsdelivr.net/npm/chart.js@4.3.2/dist/chart.umd.js" integrity: "sha384-eI7PSr3L1XLISH8JdDII5YN/njoSsxfbrkCTnJrzXt+ENP5MOVBxD+l6sEG4zoLp" + defer: true - src: "dashboard.js" + defer: true --- diff --git a/site/content/docs/5.3/examples/offcanvas-navbar/index.html b/site/content/docs/5.3/examples/offcanvas-navbar/index.html index f72583f9b1c5..34c06ad88d61 100644 --- a/site/content/docs/5.3/examples/offcanvas-navbar/index.html +++ b/site/content/docs/5.3/examples/offcanvas-navbar/index.html @@ -5,6 +5,7 @@ - "offcanvas-navbar.css" extra_js: - src: "offcanvas-navbar.js" + defer: true body_class: "bg-body-tertiary" aliases: "/docs/5.3/examples/offcanvas/" --- diff --git a/site/content/docs/5.3/examples/sidebars/index.html b/site/content/docs/5.3/examples/sidebars/index.html index 02a9456cc8f5..135c26832391 100644 --- a/site/content/docs/5.3/examples/sidebars/index.html +++ b/site/content/docs/5.3/examples/sidebars/index.html @@ -5,6 +5,7 @@ - "sidebars.css" extra_js: - src: "sidebars.js" + defer: true body_class: "" --- diff --git a/site/layouts/_default/docs.html b/site/layouts/_default/docs.html index a71e0f7b54fd..3f9463bddb3b 100644 --- a/site/layouts/_default/docs.html +++ b/site/layouts/_default/docs.html @@ -67,7 +67,7 @@

{{ .Title | markdownify }}

{{ end }} {{ define "footer" }} {{ range .Page.Params.extra_js -}} - + {{- end -}} {{ end }} diff --git a/site/layouts/_default/examples.html b/site/layouts/_default/examples.html index 3b048a9d4414..c252ea46eae6 100644 --- a/site/layouts/_default/examples.html +++ b/site/layouts/_default/examples.html @@ -159,13 +159,13 @@ {{ .Content }} {{- if hugo.IsProduction -}} - + {{- else -}} - + {{- end }} {{ range .Page.Params.extra_js -}} - + {{- end -}} diff --git a/site/layouts/partials/header.html b/site/layouts/partials/header.html index ba58893286a0..66bdf2fb1bcf 100644 --- a/site/layouts/partials/header.html +++ b/site/layouts/partials/header.html @@ -7,11 +7,13 @@ -{{ if .IsHome }}{{ .Site.Title | markdownify }} · {{ .Site.Params.subtitle | markdownify }}{{ else }}{{ .Title | markdownify }} · {{ .Site.Title | markdownify }} v{{ .Site.Params.docs_version }}{{ end }} - - +{{ if (ne .Page.Layout "examples") -}} + +{{- end }} + +{{ if .IsHome }}{{ .Site.Title | markdownify }} · {{ .Site.Params.subtitle | markdownify }}{{ else }}{{ .Title | markdownify }} · {{ .Site.Title | markdownify }} v{{ .Site.Params.docs_version }}{{ end }} {{ with .Params.robots -}} diff --git a/site/layouts/partials/scripts.html b/site/layouts/partials/scripts.html index 046f659a9470..e224c4b3775d 100644 --- a/site/layouts/partials/scripts.html +++ b/site/layouts/partials/scripts.html @@ -1,73 +1,40 @@ {{ if hugo.IsProduction -}} - + {{ else -}} - + {{- end }} - - -{{ if eq .Page.Layout "docs" -}} - -{{- end }} - -{{- $vendor := resources.Match "js/vendor/*.js" -}} -{{- $js := resources.Match "js/*.js" -}} -{{- $targetDocsJSPath := path.Join "/docs" .Site.Params.docs_version "assets/js/docs.js" -}} -{{- $docsJs := append $js $vendor | resources.Concat $targetDocsJSPath -}} +{{- $esbuildOptions := dict "target" "es2019" -}} +{{- $targetDocsJSPath := path.Join "/docs" .Site.Params.docs_version -}} {{- if hugo.IsProduction -}} - {{- $docsJs = $docsJs | resources.Minify -}} + {{- $esbuildOptions = merge $esbuildOptions (dict "minify" "true") -}} {{- end }} - - -{{ if eq .Page.Layout "docs" -}} - - -${htmlSnippet.replace(/^/gm, ' ')} - - -` +{{- if (ne .Page.Layout "examples") -}} +{{- $esbuildParams := dict + "apiKey" .Site.Params.algolia.apiKey + "appId" .Site.Params.algolia.appId + "indexName" .Site.Params.algolia.indexName +-}} +{{- $esbuildOptions = merge $esbuildOptions (dict "params" $esbuildParams) -}} +{{- $searchJs := resources.Get "js/search.js" | js.Build $esbuildOptions | resources.Copy (path.Join $targetDocsJSPath "/assets/js/search.js") }} + +{{- end -}} - const jsSnippetContent = jsSnippet ? '{{ os.ReadFile "site/assets/js/snippets.js" }}' : null - const project = { - files: { - 'index.html': markup, - 'index.js': jsSnippetContent - }, - title: 'Bootstrap Example', - description: `Official example from ${window.location.href}`, - template: jsSnippet ? 'javascript' : 'html', - tags: ['bootstrap'] - } - - StackBlitzSDK.openProject(project, { openFile: 'index.html' }) - } - -{{- end }} +{{ if eq .Page.Layout "docs" -}} +{{- /* Disable minify options for snippets.js so that the file's readable on StackBlitz */ -}} +{{- $snippetsFile := resources.Get "js/snippets.js" | js.Build (merge $esbuildOptions (dict "minify" "false")) -}} +{{- $esbuildParams := dict + "cssCdn" .Site.Params.cdn.css + "jsBundleCdn" .Site.Params.cdn.js_bundle + "docsVersion" .Site.Params.docs_version + "jsSnippetFile" $snippetsFile.Content +-}} +{{- $esbuildOptions = merge $esbuildOptions (dict "params" $esbuildParams) -}} +{{- $stackblitzJs := resources.Get "js/stackblitz.js" | js.Build $esbuildOptions | resources.Copy (path.Join $targetDocsJSPath "/assets/js/stackblitz.js") }} + +{{- end -}} diff --git a/site/layouts/partials/stylesheet.html b/site/layouts/partials/stylesheet.html index f675d7212502..9969ee44fc4f 100644 --- a/site/layouts/partials/stylesheet.html +++ b/site/layouts/partials/stylesheet.html @@ -1,5 +1,3 @@ - - {{ if hugo.IsProduction -}} {{ if eq .Page.Params.direction "rtl" -}} @@ -11,15 +9,19 @@ {{- end }} {{- if (ne .Page.Layout "examples") }} -{{- $targetDocsCssPath := path.Join "/docs" .Site.Params.docs_version "assets/css/docs.css" -}} -{{- $sassOptions := dict "targetPath" $targetDocsCssPath "outputStyle" "expanded" "precision" 6 -}} +{{- $sassOptions := dict "outputStyle" "expanded" "precision" 6 -}} {{- $postcssOptions := dict "use" "autoprefixer" "noMap" true -}} +{{- $targetDocsCssPath := path.Join "/docs" .Site.Params.docs_version "assets/css/docs.css" -}} +{{- $targetSearchCssPath := path.Join "/docs" .Site.Params.docs_version "assets/css/search.css" -}} + {{ if hugo.IsProduction -}} {{- $sassOptions = merge $sassOptions (dict "outputStyle" "compressed") -}} {{- end -}} -{{- $style := resources.Get "scss/docs.scss" | toCSS $sassOptions | postCSS $postcssOptions }} +{{- $docsCss := resources.Get "scss/docs.scss" | toCSS (merge (dict "targetPath" $targetDocsCssPath) $sassOptions) | postCSS $postcssOptions -}} +{{- $searchCss := resources.Get "scss/search.scss" | toCSS (merge (dict "targetPath" $targetSearchCssPath) $sassOptions) | postCSS $postcssOptions -}} - + + {{- end }}