From: Julien Déramond Date: Sat, 24 May 2025 09:19:46 +0000 (+0200) Subject: Docs: add `FileTree` Astro component and use it in pages X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=394a7c9964469b8b33c6f7aa033009b07cc2588d;p=thirdparty%2Fbootstrap.git Docs: add `FileTree` Astro component and use it in pages --- diff --git a/package-lock.json b/package-lock.json index 668c8de38b..d8e668ba2a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,6 +54,7 @@ "github-slugger": "^2.0.0", "globby": "^14.1.0", "hammer-simulator": "0.0.1", + "hast-util-select": "^6.0.4", "htmlparser2": "^10.0.0", "image-size": "^2.0.2", "ip": "^2.0.1", @@ -5197,6 +5198,17 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/big-integer": { "version": "1.6.52", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", @@ -5304,6 +5316,13 @@ "dev": true, "license": "MIT" }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, "node_modules/boxen": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", @@ -6369,6 +6388,23 @@ "node": ">=12 || >=16" } }, + "node_modules/css-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.1.2.tgz", + "integrity": "sha512-WfUcL99xWDs7b3eZPoRszWVfbNo8ErCF15PTvVROjkShGlAfjIkG6hlfj/sl6/rfo5Q9x9ryJ3VqVnAZDA+gcw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, "node_modules/css-tree": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", @@ -6733,6 +6769,20 @@ "node": ">=8" } }, + "node_modules/direction": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", + "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==", + "dev": true, + "license": "MIT", + "bin": { + "direction": "cli.js" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -8904,6 +8954,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-has-property": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", + "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-heading-rank": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", @@ -8988,6 +9052,34 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-select": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", + "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "bcp-47-match": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "css-selector-parser": "^3.0.0", + "devlop": "^1.0.0", + "direction": "^2.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "nth-check": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-estree": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", @@ -9100,6 +9192,20 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/hast-util-to-string": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-text": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", @@ -13697,6 +13803,19 @@ "node": ">=8" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", diff --git a/package.json b/package.json index 62a045cd87..1c465ab517 100644 --- a/package.json +++ b/package.json @@ -143,6 +143,7 @@ "github-slugger": "^2.0.0", "globby": "^14.1.0", "hammer-simulator": "0.0.1", + "hast-util-select": "^6.0.4", "htmlparser2": "^10.0.0", "image-size": "^2.0.2", "ip": "^2.0.1", diff --git a/site/src/components/FileTree.astro b/site/src/components/FileTree.astro new file mode 100644 index 0000000000..a00b967515 --- /dev/null +++ b/site/src/components/FileTree.astro @@ -0,0 +1,137 @@ +--- +import { processFileTree } from './rehype-file-tree'; + +const fileTreeHtml = await Astro.slots.render('default'); +const html = processFileTree(fileTreeHtml, 'Directory'); +--- + + + + diff --git a/site/src/components/Icons.ts b/site/src/components/Icons.ts new file mode 100644 index 0000000000..f35f8023ed --- /dev/null +++ b/site/src/components/Icons.ts @@ -0,0 +1,202 @@ +import { FileIcons } from './file-tree-icons' + +export const BuiltInIcons = { + 'up-caret': + '', + 'down-caret': + '', + 'right-caret': + '', + 'left-caret': + '', + 'up-arrow': + '', + 'down-arrow': + '', + 'right-arrow': + '', + 'left-arrow': + '', + bars: '', + translate: + '', + pencil: + '', + pen: '', + document: + '', + 'add-document': + '', + setting: + '', + external: + '', + download: + '', + 'cloud-download': + '', + moon: '', + sun: '', + laptop: + '', + 'open-book': + '', + information: + '', + magnifier: + '', + 'forward-slash': + '', + close: + '', + error: + '', + warning: + '', + 'approve-check-circle': + '', + 'approve-check': + '', + rocket: + '', + star: '', + puzzle: + '', + 'list-format': + '', + random: + '', + comment: + '', + 'comment-alt': + '', + heart: + '', + github: + '', + gitlab: + '', + bitbucket: + '', + codePen: + '', + farcaster: + '', + discord: + '', + gitter: + '', + twitter: + '', + 'x.com': + '', + mastodon: + '', + codeberg: + '', + youtube: + '', + threads: + '', + linkedin: + '', + twitch: + '', + azureDevOps: + '', + microsoftTeams: + '', + instagram: + '', + stackOverflow: + '', + telegram: + '', + rss: '', + facebook: + '', + email: + '', + phone: + '', + reddit: + '', + patreon: + '', + signal: + '', + slack: + '', + matrix: + '', + hackerOne: + '', + openCollective: + '', + blueSky: + '', + discourse: + '', + zulip: + '', + pinterest: + '', + tiktok: + '', + astro: + '', + alpine: '', + pnpm: '', + biome: + '', + bun: '', + mdx: '', + apple: + '', + linux: + '', + homebrew: + '', + nix: '', + starlight: + '', + pkl: '', + node: '', + cloudflare: + '', + vercel: '', + netlify: + '', + deno: '', + jsr: '', + nostr: + '', + backstage: + '', + confluence: + '', + jira: '', + storybook: + '', + vscode: + '', + jetbrains: + '', + zed: '', + vim: '', + figma: + '', + sketch: + '', + npm: '', + sourcehut: + '', + substack: '' +} + +export const Icons = { + ...BuiltInIcons, + ...FileIcons +} + +export type StarlightIcon = keyof typeof Icons diff --git a/site/src/components/file-tree-icons.ts b/site/src/components/file-tree-icons.ts new file mode 100644 index 0000000000..1c1c99518f --- /dev/null +++ b/site/src/components/file-tree-icons.ts @@ -0,0 +1,782 @@ +/** + * This file was generated by the `file-icons-generator` package. + * Do not edit this file directly as it will be overwritten. + */ + +import type { Definitions } from './rehype-file-tree.ts' + +/** + * Based on https://github.com/elviswolcott/seti-icons which + * is derived from https://github.com/jesseweed/seti-ui/ + * + * Copyright (c) 2014 Jesse Weed + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +export const definitions: Definitions = { + files: { + 'astro.config.js': 'astro', + 'astro.config.mjs': 'astro', + 'astro.config.cjs': 'astro', + 'astro.config.ts': 'astro', + 'pnpm-debug.log': 'pnpm', + 'pnpm-lock.yaml': 'pnpm', + 'pnpm-workspace.yaml': 'pnpm', + 'biome.json': 'biome', + 'bun.lockb': 'bun', + COMMIT_EDITMSG: 'seti:git', + MERGE_MSG: 'seti:git', + 'karma.conf.js': 'seti:karma', + 'karma.conf.cjs': 'seti:karma', + 'karma.conf.mjs': 'seti:karma', + 'karma.conf.coffee': 'seti:karma', + 'README.md': 'seti:info', + 'README.txt': 'seti:info', + README: 'seti:info', + 'CHANGELOG.md': 'seti:clock', + 'CHANGELOG.txt': 'seti:clock', + CHANGELOG: 'seti:clock', + 'CHANGES.md': 'seti:clock', + 'CHANGES.txt': 'seti:clock', + CHANGES: 'seti:clock', + 'VERSION.md': 'seti:clock', + 'VERSION.txt': 'seti:clock', + VERSION: 'seti:clock', + mvnw: 'seti:maven', + 'pom.xml': 'seti:maven', + 'tsconfig.json': 'seti:tsconfig', + 'vite.config.js': 'seti:vite', + 'vite.config.ts': 'seti:vite', + 'vite.config.mjs': 'seti:vite', + 'vite.config.mts': 'seti:vite', + 'vite.config.cjs': 'seti:vite', + 'vite.config.cts': 'seti:vite', + 'swagger.json': 'seti:json', + 'swagger.yml': 'seti:json', + 'swagger.yaml': 'seti:json', + 'mime.types': 'seti:config', + Jenkinsfile: 'seti:jenkins', + 'babel.config.js': 'seti:babel', + 'babel.config.json': 'seti:babel', + 'babel.config.cjs': 'seti:babel', + BUILD: 'seti:bazel', + 'BUILD.bazel': 'seti:bazel', + WORKSPACE: 'seti:bazel', + 'WORKSPACE.bazel': 'seti:bazel', + 'bower.json': 'seti:bower', + 'Bower.json': 'seti:bower', + 'eslint.config.js': 'seti:eslint', + 'firebase.json': 'seti:firebase', + geckodriver: 'seti:firefox', + 'Gruntfile.js': 'seti:grunt', + 'gruntfile.babel.js': 'seti:grunt', + 'Gruntfile.babel.js': 'seti:grunt', + 'gruntfile.js': 'seti:grunt', + 'Gruntfile.coffee': 'seti:grunt', + 'gruntfile.coffee': 'seti:grunt', + 'ionic.config.json': 'seti:ionic', + 'Ionic.config.json': 'seti:ionic', + 'ionic.project': 'seti:ionic', + 'Ionic.project': 'seti:ionic', + 'platformio.ini': 'seti:platformio', + 'rollup.config.js': 'seti:rollup', + 'sass-lint.yml': 'seti:sass', + 'stylelint.config.js': 'seti:stylelint', + 'stylelint.config.cjs': 'seti:stylelint', + 'stylelint.config.mjs': 'seti:stylelint', + 'yarn.clean': 'seti:yarn', + 'yarn.lock': 'seti:yarn', + 'webpack.config.js': 'seti:webpack', + 'webpack.config.cjs': 'seti:webpack', + 'webpack.config.mjs': 'seti:webpack', + 'webpack.config.ts': 'seti:webpack', + 'webpack.config.build.js': 'seti:webpack', + 'webpack.config.build.cjs': 'seti:webpack', + 'webpack.config.build.mjs': 'seti:webpack', + 'webpack.config.build.ts': 'seti:webpack', + 'webpack.common.js': 'seti:webpack', + 'webpack.common.cjs': 'seti:webpack', + 'webpack.common.mjs': 'seti:webpack', + 'webpack.common.ts': 'seti:webpack', + 'webpack.dev.js': 'seti:webpack', + 'webpack.dev.cjs': 'seti:webpack', + 'webpack.dev.mjs': 'seti:webpack', + 'webpack.dev.ts': 'seti:webpack', + 'webpack.prod.js': 'seti:webpack', + 'webpack.prod.cjs': 'seti:webpack', + 'webpack.prod.mjs': 'seti:webpack', + 'webpack.prod.ts': 'seti:webpack', + 'npm-debug.log': 'seti:npm_ignored' + }, + extensions: { + '.astro': 'astro', + '.mdx': 'mdx', + '.pkl': 'pkl', + '.bsl': 'seti:bsl', + '.mdo': 'seti:mdo', + '.cls': 'seti:salesforce', + '.apex': 'seti:salesforce', + '.asm': 'seti:asm', + '.s': 'seti:asm', + '.bicep': 'seti:bicep', + '.bzl': 'seti:bazel', + '.bazel': 'seti:bazel', + '.BUILD': 'seti:bazel', + '.WORKSPACE': 'seti:bazel', + '.bazelignore': 'seti:bazel', + '.bazelversion': 'seti:bazel', + '.c': 'seti:c', + '.h': 'seti:c', + '.m': 'seti:c', + '.cs': 'seti:c-sharp', + '.cshtml': 'seti:html', + '.aspx': 'seti:html', + '.ascx': 'seti:html', + '.asax': 'seti:html', + '.master': 'seti:html', + '.cc': 'seti:cpp', + '.cpp': 'seti:cpp', + '.cxx': 'seti:cpp', + '.c++': 'seti:cpp', + '.hh': 'seti:cpp', + '.hpp': 'seti:cpp', + '.hxx': 'seti:cpp', + '.h++': 'seti:cpp', + '.mm': 'seti:cpp', + '.clj': 'seti:clojure', + '.cljs': 'seti:clojure', + '.cljc': 'seti:clojure', + '.edn': 'seti:clojure', + '.cfc': 'seti:coldfusion', + '.cfm': 'seti:coldfusion', + '.coffee': 'seti:cjsx', + '.litcoffee': 'seti:cjsx', + '.config': 'seti:config', + '.cfg': 'seti:config', + '.conf': 'seti:config', + '.cr': 'seti:crystal', + '.ecr': 'seti:crystal_embedded', + '.slang': 'seti:crystal_embedded', + '.cson': 'seti:json', + '.css': 'seti:css', + '.css.map': 'seti:css', + '.sss': 'seti:css', + '.csv': 'seti:csv', + '.xls': 'seti:xls', + '.xlsx': 'seti:xls', + '.cu': 'seti:cu', + '.cuh': 'seti:cu', + '.hu': 'seti:cu', + '.cake': 'seti:cake', + '.ctp': 'seti:cake_php', + '.d': 'seti:d', + '.doc': 'seti:word', + '.docx': 'seti:word', + '.ejs': 'seti:ejs', + '.ex': 'seti:elixir', + '.exs': 'seti:elixir_script', + '.elm': 'seti:elm', + '.ico': 'seti:favicon', + '.fs': 'seti:f-sharp', + '.fsx': 'seti:f-sharp', + '.gitignore': 'seti:git', + '.gitconfig': 'seti:git', + '.gitkeep': 'seti:git', + '.gitattributes': 'seti:git', + '.gitmodules': 'seti:git', + '.go': 'seti:go', + '.slide': 'seti:go', + '.article': 'seti:go', + '.gd': 'seti:godot', + '.godot': 'seti:godot', + '.tres': 'seti:godot', + '.tscn': 'seti:godot', + '.gradle': 'seti:gradle', + '.groovy': 'seti:grails', + '.gsp': 'seti:grails', + '.gql': 'seti:graphql', + '.graphql': 'seti:graphql', + '.graphqls': 'seti:graphql', + '.hack': 'seti:hacklang', + '.haml': 'seti:haml', + '.handlebars': 'seti:mustache', + '.hbs': 'seti:mustache', + '.hjs': 'seti:mustache', + '.hs': 'seti:haskell', + '.lhs': 'seti:haskell', + '.hx': 'seti:haxe', + '.hxs': 'seti:haxe', + '.hxp': 'seti:haxe', + '.hxml': 'seti:haxe', + '.html': 'seti:html', + '.jade': 'seti:jade', + '.java': 'seti:java', + '.class': 'seti:java', + '.classpath': 'seti:java', + '.properties': 'seti:java', + '.js': 'seti:javascript', + '.js.map': 'seti:javascript', + '.cjs': 'seti:javascript', + '.cjs.map': 'seti:javascript', + '.mjs': 'seti:javascript', + '.mjs.map': 'seti:javascript', + '.spec.js': 'seti:javascript', + '.spec.cjs': 'seti:javascript', + '.spec.mjs': 'seti:javascript', + '.test.js': 'seti:javascript', + '.test.cjs': 'seti:javascript', + '.test.mjs': 'seti:javascript', + '.es': 'seti:javascript', + '.es5': 'seti:javascript', + '.es6': 'seti:javascript', + '.es7': 'seti:javascript', + '.jinja': 'seti:jinja', + '.jinja2': 'seti:jinja', + '.json': 'seti:json', + '.jl': 'seti:julia', + '.kt': 'seti:kotlin', + '.kts': 'seti:kotlin', + '.dart': 'seti:dart', + '.less': 'seti:json', + '.liquid': 'seti:liquid', + '.ls': 'seti:livescript', + '.lua': 'seti:lua', + '.markdown': 'seti:markdown', + '.md': 'seti:markdown', + '.argdown': 'seti:argdown', + '.ad': 'seti:argdown', + '.mustache': 'seti:mustache', + '.stache': 'seti:mustache', + '.nim': 'seti:nim', + '.nims': 'seti:nim', + '.github-issues': 'seti:github', + '.ipynb': 'seti:notebook', + '.njk': 'seti:nunjucks', + '.nunjucks': 'seti:nunjucks', + '.nunjs': 'seti:nunjucks', + '.nunj': 'seti:nunjucks', + '.njs': 'seti:nunjucks', + '.nj': 'seti:nunjucks', + '.npm-debug.log': 'seti:npm', + '.npmignore': 'seti:npm', + '.npmrc': 'seti:npm', + '.ml': 'seti:ocaml', + '.mli': 'seti:ocaml', + '.cmx': 'seti:ocaml', + '.cmxa': 'seti:ocaml', + '.odata': 'seti:odata', + '.pl': 'seti:perl', + '.php': 'seti:php', + '.php.inc': 'seti:php', + '.pipeline': 'seti:pipeline', + '.pddl': 'seti:pddl', + '.plan': 'seti:plan', + '.happenings': 'seti:happenings', + '.ps1': 'seti:powershell', + '.psd1': 'seti:powershell', + '.psm1': 'seti:powershell', + '.prisma': 'seti:prisma', + '.pug': 'seti:pug', + '.pp': 'seti:puppet', + '.epp': 'seti:puppet', + '.purs': 'seti:purescript', + '.py': 'seti:python', + '.jsx': 'seti:react', + '.spec.jsx': 'seti:react', + '.test.jsx': 'seti:react', + '.cjsx': 'seti:react', + '.tsx': 'seti:react', + '.spec.tsx': 'seti:react', + '.test.tsx': 'seti:react', + '.res': 'seti:rescript', + '.resi': 'seti:rescript', + '.R': 'seti:R', + '.rmd': 'seti:R', + '.rb': 'seti:ruby', + '.erb': 'seti:html', + '.erb.html': 'seti:html', + '.html.erb': 'seti:html', + '.rs': 'seti:rust', + '.sass': 'seti:sass', + '.scss': 'seti:sass', + '.springBeans': 'seti:spring', + '.slim': 'seti:slim', + '.smarty.tpl': 'seti:smarty', + '.tpl': 'seti:smarty', + '.sbt': 'seti:sbt', + '.scala': 'seti:scala', + '.sol': 'seti:ethereum', + '.styl': 'seti:stylus', + '.svelte': 'seti:svelte', + '.swift': 'seti:swift', + '.sql': 'seti:db', + '.soql': 'seti:db', + '.tf': 'seti:terraform', + '.tf.json': 'seti:terraform', + '.tfvars': 'seti:terraform', + '.tfvars.json': 'seti:terraform', + '.tex': 'seti:tex', + '.sty': 'seti:tex', + '.dtx': 'seti:tex', + '.ins': 'seti:tex', + '.txt': 'seti:default', + '.toml': 'seti:config', + '.twig': 'seti:twig', + '.ts': 'seti:typescript', + '.spec.ts': 'seti:typescript', + '.test.ts': 'seti:typescript', + '.vala': 'seti:vala', + '.vapi': 'seti:vala', + '.component': 'seti:html', + '.vue': 'seti:vue', + '.wasm': 'seti:wasm', + '.wat': 'seti:wat', + '.xml': 'seti:xml', + '.yml': 'seti:yml', + '.yaml': 'seti:yml', + '.pro': 'seti:prolog', + '.zig': 'seti:zig', + '.jar': 'seti:zip', + '.zip': 'seti:zip', + '.wgt': 'seti:wgt', + '.ai': 'seti:illustrator', + '.psd': 'seti:photoshop', + '.pdf': 'seti:pdf', + '.eot': 'seti:font', + '.ttf': 'seti:font', + '.woff': 'seti:font', + '.woff2': 'seti:font', + '.otf': 'seti:font', + '.avif': 'seti:image', + '.gif': 'seti:image', + '.jpg': 'seti:image', + '.jpeg': 'seti:image', + '.png': 'seti:image', + '.pxm': 'seti:image', + '.svg': 'seti:svg', + '.svgx': 'seti:image', + '.tiff': 'seti:image', + '.webp': 'seti:image', + '.sublime-project': 'seti:sublime', + '.sublime-workspace': 'seti:sublime', + '.code-search': 'seti:code-search', + '.sh': 'seti:shell', + '.zsh': 'seti:shell', + '.fish': 'seti:shell', + '.zshrc': 'seti:shell', + '.bashrc': 'seti:shell', + '.mov': 'seti:video', + '.ogv': 'seti:video', + '.webm': 'seti:video', + '.avi': 'seti:video', + '.mpg': 'seti:video', + '.mp4': 'seti:video', + '.mp3': 'seti:audio', + '.ogg': 'seti:audio', + '.wav': 'seti:audio', + '.flac': 'seti:audio', + '.3ds': 'seti:svg', + '.3dm': 'seti:svg', + '.stl': 'seti:svg', + '.obj': 'seti:svg', + '.dae': 'seti:svg', + '.bat': 'seti:windows', + '.cmd': 'seti:windows', + '.babelrc': 'seti:babel', + '.babelrc.js': 'seti:babel', + '.babelrc.cjs': 'seti:babel', + '.bazelrc': 'seti:bazel', + '.bowerrc': 'seti:bower', + '.codeclimate.yml': 'seti:code-climate', + '.eslintrc': 'seti:eslint', + '.eslintrc.js': 'seti:eslint', + '.eslintrc.cjs': 'seti:eslint', + '.eslintrc.yaml': 'seti:eslint', + '.eslintrc.yml': 'seti:eslint', + '.eslintrc.json': 'seti:eslint', + '.eslintignore': 'seti:eslint', + '.firebaserc': 'seti:firebase', + '.gitlab-ci.yml': 'seti:gitlab', + '.jshintrc': 'seti:javascript', + '.jscsrc': 'seti:javascript', + '.stylelintrc': 'seti:stylelint', + '.stylelintrc.json': 'seti:stylelint', + '.stylelintrc.yaml': 'seti:stylelint', + '.stylelintrc.yml': 'seti:stylelint', + '.stylelintrc.js': 'seti:stylelint', + '.stylelintignore': 'seti:stylelint', + '.direnv': 'seti:config', + '.env': 'seti:config', + '.static': 'seti:config', + '.editorconfig': 'seti:config', + '.slugignore': 'seti:config', + '.tmp': 'seti:clock', + '.htaccess': 'seti:config', + '.key': 'seti:lock', + '.cert': 'seti:lock', + '.cer': 'seti:lock', + '.crt': 'seti:lock', + '.pem': 'seti:lock', + '.DS_Store': 'seti:ignored' + }, + partials: { + mix: 'seti:hex', + Gemfile: 'seti:ruby', + gemfile: 'seti:ruby', + dockerfile: 'seti:docker', + Dockerfile: 'seti:docker', + DOCKERFILE: 'seti:docker', + '.dockerignore': 'seti:docker', + 'docker-healthcheck': 'seti:docker', + 'docker-compose.yml': 'seti:docker', + 'docker-compose.yaml': 'seti:docker', + 'docker-compose.override.yml': 'seti:docker', + 'docker-compose.override.yaml': 'seti:docker', + GULPFILE: 'seti:gulp', + Gulpfile: 'seti:gulp', + gulpfile: 'seti:gulp', + 'gulpfile.js': 'seti:gulp', + LICENSE: 'seti:license', + LICENCE: 'seti:license', + 'LICENSE.txt': 'seti:license', + 'LICENCE.txt': 'seti:license', + 'LICENSE.md': 'seti:license', + 'LICENCE.md': 'seti:license', + COPYING: 'seti:license', + 'COPYING.txt': 'seti:license', + 'COPYING.md': 'seti:license', + COMPILING: 'seti:license', + 'COMPILING.txt': 'seti:license', + 'COMPILING.md': 'seti:license', + CONTRIBUTING: 'seti:license', + 'CONTRIBUTING.txt': 'seti:license', + 'CONTRIBUTING.md': 'seti:license', + MAKEFILE: 'seti:makefile', + Makefile: 'seti:makefile', + makefile: 'seti:makefile', + QMAKEFILE: 'seti:makefile', + QMakefile: 'seti:makefile', + qmakefile: 'seti:makefile', + OMAKEFILE: 'seti:makefile', + OMakefile: 'seti:makefile', + omakefile: 'seti:makefile', + 'CMAKELISTS.TXT': 'seti:makefile', + 'CMAKELISTS.txt': 'seti:makefile', + 'CMakeLists.txt': 'seti:makefile', + 'cmakelists.txt': 'seti:makefile', + Procfile: 'seti:heroku', + TODO: 'seti:todo', + 'TODO.txt': 'seti:todo', + 'TODO.md': 'seti:todo' + } +} + +export const FileIcons = { + 'seti:folder': + '', + 'seti:bsl': + '', + 'seti:mdo': + '', + 'seti:salesforce': + '', + 'seti:asm': + '', + 'seti:bicep': + '', + 'seti:bazel': + '', + 'seti:c': + '', + 'seti:c-sharp': + '', + 'seti:html': + '', + 'seti:cpp': + '', + 'seti:clojure': + '', + 'seti:coldfusion': + '', + 'seti:config': + '', + 'seti:crystal': + '', + 'seti:crystal_embedded': + '', + 'seti:json': + '', + 'seti:css': + '', + 'seti:csv': + '', + 'seti:xls': + '', + 'seti:cu': + '', + 'seti:cake': + '', + 'seti:cake_php': + '', + 'seti:d': + '', + 'seti:word': + '', + 'seti:elixir': + '', + 'seti:elixir_script': + '', + 'seti:hex': + '', + 'seti:elm': + '', + 'seti:favicon': + '', + 'seti:f-sharp': + '', + 'seti:git': + '', + 'seti:go': + '', + 'seti:godot': + '', + 'seti:gradle': + '', + 'seti:grails': + '', + 'seti:graphql': + '', + 'seti:hacklang': + '', + 'seti:haml': + '', + 'seti:mustache': + '', + 'seti:haskell': + '', + 'seti:haxe': + '', + 'seti:jade': + '', + 'seti:java': + '', + 'seti:javascript': + '', + 'seti:jinja': + '', + 'seti:julia': + '', + 'seti:karma': + '', + 'seti:kotlin': + '', + 'seti:dart': + '', + 'seti:liquid': + '', + 'seti:livescript': + '', + 'seti:lua': + '', + 'seti:markdown': + '', + 'seti:argdown': + '', + 'seti:info': + '', + 'seti:clock': + '', + 'seti:maven': + '', + 'seti:nim': + '', + 'seti:github': + '', + 'seti:notebook': + '', + 'seti:nunjucks': + '', + 'seti:npm': + '', + 'seti:ocaml': + '', + 'seti:odata': + '', + 'seti:perl': + '', + 'seti:php': + '', + 'seti:pipeline': + '', + 'seti:pddl': + '', + 'seti:plan': + '', + 'seti:happenings': + '', + 'seti:powershell': + '', + 'seti:prisma': + '', + 'seti:pug': + '', + 'seti:puppet': + '', + 'seti:purescript': + '', + 'seti:python': + '', + 'seti:react': + '', + 'seti:rescript': + '', + 'seti:R': + '', + 'seti:ruby': + '', + 'seti:rust': + '', + 'seti:sass': + '', + 'seti:spring': + '', + 'seti:slim': + '', + 'seti:smarty': + '', + 'seti:sbt': + '', + 'seti:scala': + '', + 'seti:ethereum': + '', + 'seti:stylus': + '', + 'seti:svelte': + '', + 'seti:swift': + '', + 'seti:db': + '', + 'seti:terraform': + '', + 'seti:tex': + '', + 'seti:default': + '', + 'seti:twig': + '', + 'seti:typescript': + '', + 'seti:tsconfig': + '', + 'seti:vala': + '', + 'seti:vite': + '', + 'seti:vue': + '', + 'seti:wasm': + '', + 'seti:wat': + '', + 'seti:xml': + '', + 'seti:yml': + '', + 'seti:prolog': + '', + 'seti:zig': + '', + 'seti:zip': + '', + 'seti:wgt': + '', + 'seti:illustrator': + '', + 'seti:photoshop': + '', + 'seti:pdf': + '', + 'seti:font': + '', + 'seti:image': + '', + 'seti:svg': + '', + 'seti:sublime': + '', + 'seti:code-search': + '', + 'seti:shell': + '', + 'seti:video': + '', + 'seti:audio': + '', + 'seti:windows': + '', + 'seti:jenkins': + '', + 'seti:babel': + '', + 'seti:bower': + '', + 'seti:docker': + '', + 'seti:code-climate': + '', + 'seti:eslint': + '', + 'seti:firebase': + '', + 'seti:firefox': + '', + 'seti:gitlab': + '', + 'seti:grunt': + '', + 'seti:gulp': + '', + 'seti:ionic': + '', + 'seti:platformio': + '', + 'seti:rollup': + '', + 'seti:stylelint': + '', + 'seti:yarn': + '', + 'seti:webpack': + '', + 'seti:lock': + '', + 'seti:license': + '', + 'seti:makefile': + '', + 'seti:heroku': + '', + 'seti:todo': + '', + 'seti:ignored': + '' +} diff --git a/site/src/components/rehype-file-tree.ts b/site/src/components/rehype-file-tree.ts new file mode 100644 index 0000000000..8c952df1ec --- /dev/null +++ b/site/src/components/rehype-file-tree.ts @@ -0,0 +1,245 @@ +import { AstroError } from 'astro/errors' +import type { Element, ElementContent, Text } from 'hast' +import { type Child, h, s } from 'hastscript' +import { select } from 'hast-util-select' +import { fromHtml } from 'hast-util-from-html' +import { toString } from 'hast-util-to-string' +import { rehype } from 'rehype' +import { CONTINUE, SKIP, visit } from 'unist-util-visit' +import { Icons, type StarlightIcon } from './Icons' +import { definitions } from './file-tree-icons' + +declare module 'vfile' { + interface DataMap { + directoryLabel: string + } +} + +const folderIcon = makeSVGIcon(Icons['seti:folder']) +const defaultFileIcon = makeSVGIcon(Icons['seti:default']) + +/** + * Process the HTML for a file tree to create the necessary markup for each file and directory + * including icons. + * @param html Inner HTML passed to the `` component. + * @param directoryLabel The localized label for a directory. + * @returns The processed HTML for the file tree. + */ +export function processFileTree(html: string, directoryLabel: string) { + const file = fileTreeProcessor.processSync({ data: { directoryLabel }, value: html }) + + return file.toString() +} + +/** Rehype processor to extract file tree data and turn each entry into its associated markup. */ +const fileTreeProcessor = rehype() + .data('settings', { fragment: true }) + .use(function fileTree() { + return (tree: Element, file) => { + const { directoryLabel } = file.data + + validateFileTree(tree) + + visit(tree, 'element', (node) => { + // Strip nodes that only contain newlines. + node.children = node.children.filter( + (child) => child.type === 'comment' || child.type !== 'text' || !/^\n+$/.test(child.value) + ) + + // Skip over non-list items. + if (node.tagName !== 'li') return CONTINUE + + const [firstChild, ...otherChildren] = node.children + + // Keep track of comments associated with the current file or directory. + const comment: Child[] = [] + + // Extract text comment that follows the file name, e.g. `README.md This is a comment` + if (firstChild?.type === 'text') { + const [filename, ...fragments] = firstChild.value.split(' ') + firstChild.value = filename || '' + const textComment = fragments.join(' ').trim() + if (textComment.length > 0) { + comment.push(fragments.join(' ')) + } + } + + // Comments may not always be entirely part of the first child text node, + // e.g. `README.md This is an __important__ comment` where the `__important__` and `comment` + // nodes would also be children of the list item node. + const subTreeIndex = otherChildren.findIndex((child) => child.type === 'element' && child.tagName === 'ul') + const commentNodes = subTreeIndex > -1 ? otherChildren.slice(0, subTreeIndex) : [...otherChildren] + otherChildren.splice(0, subTreeIndex > -1 ? subTreeIndex : otherChildren.length) + comment.push(...commentNodes) + + const firstChildTextContent = firstChild ? toString(firstChild) : '' + + // Decide a node is a directory if it ends in a `/` or contains another list. + const isDirectory = + /\/\s*$/.test(firstChildTextContent) || + otherChildren.some((child) => child.type === 'element' && child.tagName === 'ul') + // A placeholder is a node that only contains 3 dots or an ellipsis. + const isPlaceholder = /^\s*(\.{3}|…)\s*$/.test(firstChildTextContent) + // A node is highlighted if its first child is bold text, e.g. `**README.md**`. + const isHighlighted = firstChild?.type === 'element' && firstChild.tagName === 'strong' + + // Create an icon for the file or directory (placeholder do not have icons). + const icon = h('span', isDirectory ? folderIcon : getFileIcon(firstChildTextContent)) + if (isDirectory) { + // Add a screen reader only label for directories before the icon so that it is announced + // as such before reading the directory name. + icon.children.unshift(h('span', { class: 'visually-hidden' }, directoryLabel)) + } + + // Add classes and data attributes to the list item node. + node.properties.class = isDirectory ? 'directory' : 'file' + if (isPlaceholder) node.properties.class += ' empty' + + // Create the tree entry node that contains the icon, file name and comment which will end up + // as the list item’s children. + const treeEntryChildren: Child[] = [ + h('span', { class: isHighlighted ? 'highlighted' : '' }, [isPlaceholder ? null : icon, firstChild]) + ] + + if (comment.length > 0) { + treeEntryChildren.push(makeText(' '), h('span', { class: 'comment' }, ...comment)) + } + + const treeEntry = h('span', { class: 'tree-entry' }, ...treeEntryChildren) + + if (isDirectory) { + const hasContents = otherChildren.length > 0 + + node.children = [ + h('details', { open: hasContents }, [ + h('summary', treeEntry), + ...(hasContents ? otherChildren : [h('ul', h('li', '…'))]) + ]) + ] + + // Continue down the tree. + return CONTINUE + } + + node.children = [treeEntry, ...otherChildren] + + // Files can’t contain further files or directories, so skip iterating children. + return SKIP + }) + } + }) + +/** Make a text node with the pass string as its contents. */ +function makeText(value = ''): Text { + return { type: 'text', value } +} + +/** Make a node containing an SVG icon from the passed HTML string. */ +function makeSVGIcon(svgString: string) { + return s( + 'svg', + { + width: 16, + height: 16, + class: 'tree-icon', + 'aria-hidden': 'true', + viewBox: '0 0 24 24' + }, + fromHtml(svgString, { fragment: true }) + ) +} + +/** Return the icon for a file based on its file name. */ +function getFileIcon(fileName: string) { + const name = getFileIconName(fileName) + if (!name) return defaultFileIcon + if (name in Icons) { + const path = Icons[name as StarlightIcon] + return makeSVGIcon(path) + } + return defaultFileIcon +} + +/** Return the icon name for a file based on its file name. */ +function getFileIconName(fileName: string) { + let icon: string | undefined = definitions.files[fileName] + if (icon) return icon + icon = getFileIconTypeFromExtension(fileName) + if (icon) return icon + for (const [partial, partialIcon] of Object.entries(definitions.partials)) { + if (fileName.includes(partial)) return partialIcon + } + return icon +} + +/** + * Get an icon from a file name based on its extension. + * Note that an extension in Seti is everything after a dot, so `README.md` would be `.md` and + * `name.with.dots` will try to look for an icon for `.with.dots` and then `.dots` if the first one + * is not found. + */ +function getFileIconTypeFromExtension(fileName: string) { + const firstDotIndex = fileName.indexOf('.') + if (firstDotIndex === -1) return + let extension = fileName.slice(firstDotIndex) + while (extension !== '') { + const icon = definitions.extensions[extension] + if (icon) return icon + const nextDotIndex = extension.indexOf('.', 1) + if (nextDotIndex === -1) return + extension = extension.slice(nextDotIndex) + } + return +} + +/** Validate that the user provided HTML for a file tree is valid. */ +function validateFileTree(tree: Element) { + const rootElements = tree.children.filter(isElementNode) + const [rootElement] = rootElements + + if (rootElements.length === 0) { + throwFileTreeValidationError( + 'The `` component expects its content to be a single unordered list but found no child elements.' + ) + } + + if (rootElements.length !== 1) { + throwFileTreeValidationError( + `The \`\` component expects its content to be a single unordered list but found multiple child elements: ${rootElements + .map((element) => `\`<${element.tagName}>\``) + .join(' - ')}.` + ) + } + + if (!rootElement || rootElement.tagName !== 'ul') { + throwFileTreeValidationError( + `The \`\` component expects its content to be an unordered list but found the following element: \`<${rootElement?.tagName}>\`.` + ) + } + + const listItemElement = select('li', rootElement) + + if (!listItemElement) { + throwFileTreeValidationError( + 'The `` component expects its content to be an unordered list with at least one list item.' + ) + } +} + +function isElementNode(node: ElementContent): node is Element { + return node.type === 'element' +} + +/** Throw a validation error for a file tree linking to the documentation. */ +function throwFileTreeValidationError(message: string): never { + throw new AstroError( + message, + 'To learn more about the `` component, see https://starlight.astro.build/components/file-tree/' + ) +} + +export interface Definitions { + files: Record + extensions: Record + partials: Record +} diff --git a/site/src/content/docs/customize/sass.mdx b/site/src/content/docs/customize/sass.mdx index 6352de4025..3564da40e8 100644 --- a/site/src/content/docs/customize/sass.mdx +++ b/site/src/content/docs/customize/sass.mdx @@ -4,6 +4,8 @@ description: Utilize our source Sass files to take advantage of variables, maps, toc: true --- +import FileTree from '../../../components/FileTree.astro'; + Utilize our source Sass files to take advantage of variables, maps, mixins, and more. @@ -14,28 +16,32 @@ Sass deprecation warnings are shown when compiling source Sass files with the la Whenever possible, avoid modifying Bootstrap’s core files. For Sass, that means creating your own stylesheet that imports Bootstrap so you can modify and extend it. Assuming you’re using a package manager like npm, you’ll have a file structure that looks like this: -```text -your-project/ -├── scss/ -│ └── custom.scss -└── node_modules/ -│ └── bootstrap/ -│ ├── js/ -│ └── scss/ -└── index.html -``` + + +- your-project/ + - scss/ + - custom.scss + - node_modules/ + - bootstrap/ + - js/ + - scss/ + - index.html + + If you’ve downloaded our source files and aren’t using a package manager, you’ll want to manually create something similar to that structure, keeping Bootstrap’s source files separate from your own. -```text -your-project/ -├── scss/ -│ └── custom.scss -├── bootstrap/ -│ ├── js/ -│ └── scss/ -└── index.html -``` + + +- your-project/ + - scss/ + - custom.scss + - bootstrap/ + - js/ + - scss/ + - index.html + + ## Importing diff --git a/site/src/content/docs/getting-started/contents.mdx b/site/src/content/docs/getting-started/contents.mdx index 6377d7af47..5ced08f2c9 100644 --- a/site/src/content/docs/getting-started/contents.mdx +++ b/site/src/content/docs/getting-started/contents.mdx @@ -2,65 +2,67 @@ title: Contents description: Discover what’s included in Bootstrap, including our compiled and source code flavors. toc: true - -# TODO: possible to replace the tree by something like https://docs.astro.build/en/guides/content-collections/#what-are-content-collections? --- +import FileTree from '../../../components/FileTree.astro'; + ## Compiled Bootstrap Once downloaded, unzip the compressed folder and you’ll see something like this: {/* NOTE: This info is intentionally duplicated in the README. Copy any changes made here over to the README too, but be sure to keep in mind to add the `dist` folder. */} -```text -bootstrap/ -├── css/ -│ ├── bootstrap-grid.css -│ ├── bootstrap-grid.css.map -│ ├── bootstrap-grid.min.css -│ ├── bootstrap-grid.min.css.map -│ ├── bootstrap-grid.rtl.css -│ ├── bootstrap-grid.rtl.css.map -│ ├── bootstrap-grid.rtl.min.css -│ ├── bootstrap-grid.rtl.min.css.map -│ ├── bootstrap-reboot.css -│ ├── bootstrap-reboot.css.map -│ ├── bootstrap-reboot.min.css -│ ├── bootstrap-reboot.min.css.map -│ ├── bootstrap-reboot.rtl.css -│ ├── bootstrap-reboot.rtl.css.map -│ ├── bootstrap-reboot.rtl.min.css -│ ├── bootstrap-reboot.rtl.min.css.map -│ ├── bootstrap-utilities.css -│ ├── bootstrap-utilities.css.map -│ ├── bootstrap-utilities.min.css -│ ├── bootstrap-utilities.min.css.map -│ ├── bootstrap-utilities.rtl.css -│ ├── bootstrap-utilities.rtl.css.map -│ ├── bootstrap-utilities.rtl.min.css -│ ├── bootstrap-utilities.rtl.min.css.map -│ ├── bootstrap.css -│ ├── bootstrap.css.map -│ ├── bootstrap.min.css -│ ├── bootstrap.min.css.map -│ ├── bootstrap.rtl.css -│ ├── bootstrap.rtl.css.map -│ ├── bootstrap.rtl.min.css -│ └── bootstrap.rtl.min.css.map -└── js/ - ├── bootstrap.bundle.js - ├── bootstrap.bundle.js.map - ├── bootstrap.bundle.min.js - ├── bootstrap.bundle.min.js.map - ├── bootstrap.esm.js - ├── bootstrap.esm.js.map - ├── bootstrap.esm.min.js - ├── bootstrap.esm.min.js.map - ├── bootstrap.js - ├── bootstrap.js.map - ├── bootstrap.min.js - └── bootstrap.min.js.map -``` + + +- bootstrap/ + - css/ + - bootstrap-grid.css + - bootstrap-grid.css.map + - bootstrap-grid.min.css + - bootstrap-grid.min.css.map + - bootstrap-grid.rtl.css + - bootstrap-grid.rtl.css.map + - bootstrap-grid.rtl.min.css + - bootstrap-grid.rtl.min.css.map + - bootstrap-reboot.css + - bootstrap-reboot.css.map + - bootstrap-reboot.min.css + - bootstrap-reboot.min.css.map + - bootstrap-reboot.rtl.css + - bootstrap-reboot.rtl.css.map + - bootstrap-reboot.rtl.min.css + - bootstrap-reboot.rtl.min.css.map + - bootstrap-utilities.css + - bootstrap-utilities.css.map + - bootstrap-utilities.min.css + - bootstrap-utilities.min.css.map + - bootstrap-utilities.rtl.css + - bootstrap-utilities.rtl.css.map + - bootstrap-utilities.rtl.min.css + - bootstrap-utilities.rtl.min.css.map + - bootstrap.css + - bootstrap.css.map + - bootstrap.min.css + - bootstrap.min.css.map + - bootstrap.rtl.css + - bootstrap.rtl.css.map + - bootstrap.rtl.min.css + - bootstrap.rtl.min.css.map + - js/ + - bootstrap.bundle.js + - bootstrap.bundle.js.map + - bootstrap.bundle.min.js + - bootstrap.bundle.min.js.map + - bootstrap.esm.js + - bootstrap.esm.js.map + - bootstrap.esm.min.js + - bootstrap.esm.min.js.map + - bootstrap.js + - bootstrap.js.map + - bootstrap.min.js + - bootstrap.min.js.map + + This is the most basic form of Bootstrap: compiled files for quick drop-in usage in nearly any web project. We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). [Source maps](https://web.dev/articles/source-maps) (`bootstrap.*.map`) are available for use with certain browsers’ developer tools. Bundled JS files (`bootstrap.bundle.js` and minified `bootstrap.bundle.min.js`) include [Popper](https://popper.js.org/docs/v2/). @@ -92,19 +94,21 @@ Similarly, we have options for including some or all of our compiled JavaScript. The Bootstrap source code download includes the compiled CSS and JavaScript assets, along with source Sass, JavaScript, and documentation. More specifically, it includes the following and more: -```text -bootstrap/ -├── dist/ -│ ├── css/ -│ └── js/ -├── site/ -│ └──content/ -│ └── docs/ -│ └── [[config:docs_version]]/ -│ └── examples/ -├── js/ -└── scss/ -``` + + +- bootstrap/ + - dist/ + - css/ + - js/ + - site/ + - content/ + - docs/ + - [[config:docs_version]]/ + - examples/ + - js/ + - scss/ + + The `scss/` and `js/` are the source code for our CSS and JavaScript. The `dist/` folder includes everything listed in the compiled download section above. The `site/content/docs/` folder includes the source code for our hosted documentation, including our live examples of Bootstrap usage. diff --git a/site/src/content/docs/getting-started/parcel.mdx b/site/src/content/docs/getting-started/parcel.mdx index 97a721ea4a..efa1153918 100644 --- a/site/src/content/docs/getting-started/parcel.mdx +++ b/site/src/content/docs/getting-started/parcel.mdx @@ -5,6 +5,8 @@ toc: true thumbnail: guides/bootstrap-parcel@2x.png --- +import FileTree from '../../../components/FileTree.astro'; + @@ -51,17 +53,19 @@ touch src/index.html src/js/main.js src/scss/styles.scss When you’re done, your complete project should look like this: -```text -my-project/ -├── src/ -│ ├── js/ -│ │ └── main.js -│ ├── scss/ -│ │ └── styles.scss -│ └── index.html -├── package-lock.json -└── package.json -``` + + +- my-project/ + - src/ + - js/ + - main.js + - scss/ + - styles.scss + - index.html + - package-lock.json + - package.json + + At this point, everything is in the right place, but Parcel needs an HTML page and npm script to start our server. diff --git a/site/src/content/docs/getting-started/vite.mdx b/site/src/content/docs/getting-started/vite.mdx index ad691c79b1..36f8624b84 100644 --- a/site/src/content/docs/getting-started/vite.mdx +++ b/site/src/content/docs/getting-started/vite.mdx @@ -8,6 +8,8 @@ added: version: "5.2" --- +import FileTree from '../../../components/FileTree.astro'; + @@ -60,18 +62,20 @@ touch src/index.html src/js/main.js src/scss/styles.scss vite.config.js When you’re done, your complete project should look like this: -```text -my-project/ -├── src/ -│ ├── js/ -│ │ └── main.js -│ └── scss/ -│ | └── styles.scss -| └── index.html -├── package-lock.json -├── package.json -└── vite.config.js -``` + + +- my-project/ + - src/ + - js/ + - main.js + - scss/ + - styles.scss + - index.html + - package-lock.json + - package.json + - vite.config.js + + At this point, everything is in the right place, but Vite won’t work because we haven’t filled in our `vite.config.js` yet. diff --git a/site/src/content/docs/getting-started/webpack.mdx b/site/src/content/docs/getting-started/webpack.mdx index b8ae166020..338abe2036 100644 --- a/site/src/content/docs/getting-started/webpack.mdx +++ b/site/src/content/docs/getting-started/webpack.mdx @@ -5,6 +5,8 @@ toc: true thumbnail: guides/bootstrap-webpack@2x.png --- +import FileTree from '../../../components/FileTree.astro'; + @@ -57,18 +59,20 @@ touch src/index.html src/js/main.js src/scss/styles.scss webpack.config.js When you’re done, your complete project should look like this: -```text -my-project/ -├── src/ -│ ├── js/ -│ │ └── main.js -│ ├── scss/ -│ │ └── styles.scss -│ └── index.html -├── package-lock.json -├── package.json -└── webpack.config.js -``` + + +- my-project/ + - src/ + - js/ + - main.js + - scss/ + - styles.scss + - index.html + - package-lock.json + - package.json + - webpack.config.js + + At this point, everything is in the right place, but Webpack won’t work because we haven’t filled in our `webpack.config.js` yet.