From ec77a6a598774cb7b2da4709d2b6113b044792af Mon Sep 17 00:00:00 2001 From: delucis Date: Wed, 14 Dec 2022 19:34:57 +0100 Subject: [PATCH 01/11] Add SVG file icon helper based on Seti UI --- src/components/internal/file-tree-icons.ts | 753 +++++++++++++++++++++ 1 file changed, 753 insertions(+) create mode 100644 src/components/internal/file-tree-icons.ts diff --git a/src/components/internal/file-tree-icons.ts b/src/components/internal/file-tree-icons.ts new file mode 100644 index 0000000000000..1c36fac255ffc --- /dev/null +++ b/src/components/internal/file-tree-icons.ts @@ -0,0 +1,753 @@ +/** + * 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. + */ + +const rawDefinitions = { + files: { + COMMIT_EDITMSG: ['git', 'ignore'], + MERGE_MSG: ['git', 'ignore'], + 'karma.conf.js': ['karma', 'green'], + 'karma.conf.coffee': ['karma', 'green'], + 'README.md': ['info', 'blue'], + 'README.txt': ['info', 'blue'], + README: ['info', 'blue'], + 'CHANGELOG.md': ['clock', 'blue'], + 'CHANGELOG.txt': ['clock', 'blue'], + CHANGELOG: ['clock', 'blue'], + 'CHANGES.md': ['clock', 'blue'], + 'CHANGES.txt': ['clock', 'blue'], + CHANGES: ['clock', 'blue'], + 'VERSION.md': ['clock', 'blue'], + 'VERSION.txt': ['clock', 'blue'], + VERSION: ['clock', 'blue'], + mvnw: ['maven', 'red'], + 'tsconfig.json': ['tsconfig', 'blue'], + 'swagger.json': ['json', 'green'], + 'swagger.yml': ['json', 'green'], + 'swagger.yaml': ['json', 'green'], + 'mime.types': ['config', 'grey-light'], + Jenkinsfile: ['jenkins', 'red'], + 'babel.config.js': ['babel', 'yellow'], + 'babel.config.json': ['babel', 'yellow'], + 'babel.config.cjs': ['babel', 'yellow'], + BUILD: ['bazel', 'green'], + 'BUILD.bazel': ['bazel', 'green'], + WORKSPACE: ['bazel', 'green'], + 'WORKSPACE.bazel': ['bazel', 'green'], + 'bower.json': ['bower', 'orange'], + 'Bower.json': ['bower', 'orange'], + 'firebase.json': ['firebase', 'orange'], + geckodriver: ['firefox', 'orange'], + 'Gruntfile.js': ['grunt', 'orange'], + 'gruntfile.babel.js': ['grunt', 'orange'], + 'Gruntfile.babel.js': ['grunt', 'orange'], + 'gruntfile.js': ['grunt', 'orange'], + 'Gruntfile.coffee': ['grunt', 'orange'], + 'gruntfile.coffee': ['grunt', 'orange'], + 'ionic.config.json': ['ionic', 'blue'], + 'Ionic.config.json': ['ionic', 'blue'], + 'ionic.project': ['ionic', 'blue'], + 'Ionic.project': ['ionic', 'blue'], + 'platformio.ini': ['platformio', 'orange'], + 'rollup.config.js': ['rollup', 'red'], + 'sass-lint.yml': ['sass', 'pink'], + 'stylelint.config.js': ['stylelint', 'white'], + 'stylelint.config.cjs': ['stylelint', 'white'], + 'yarn.clean': ['yarn', 'blue'], + 'yarn.lock': ['yarn', 'blue'], + 'webpack.config.js': ['webpack', 'blue'], + 'webpack.config.cjs': ['webpack', 'blue'], + 'webpack.config.ts': ['webpack', 'blue'], + 'webpack.config.build.js': ['webpack', 'blue'], + 'webpack.config.build.cjs': ['webpack', 'blue'], + 'webpack.config.build.ts': ['webpack', 'blue'], + 'webpack.common.js': ['webpack', 'blue'], + 'webpack.common.cjs': ['webpack', 'blue'], + 'webpack.common.ts': ['webpack', 'blue'], + 'webpack.dev.js': ['webpack', 'blue'], + 'webpack.dev.cjs': ['webpack', 'blue'], + 'webpack.dev.ts': ['webpack', 'blue'], + 'webpack.prod.js': ['webpack', 'blue'], + 'webpack.prod.cjs': ['webpack', 'blue'], + 'webpack.prod.ts': ['webpack', 'blue'], + 'npm-debug.log': ['npm_ignored', 'ignore'], + }, + extensions: { + '.astro': ['astro', 'red'], + '.bsl': ['bsl', 'red'], + '.mdo': ['mdo', 'red'], + '.cls': ['salesforce', 'blue'], + '.apex': ['salesforce', 'blue'], + '.asm': ['asm', 'red'], + '.s': ['asm', 'red'], + '.bicep': ['bicep', 'blue'], + '.bzl': ['bazel', 'green'], + '.bazel': ['bazel', 'green'], + '.BUILD': ['bazel', 'green'], + '.WORKSPACE': ['bazel', 'green'], + '.bazelignore': ['bazel', 'green'], + '.bazelversion': ['bazel', 'green'], + '.c': ['c', 'blue'], + '.h': ['c', 'purple'], + '.m': ['c', 'yellow'], + '.cs': ['c-sharp', 'blue'], + '.cshtml': ['html', 'blue'], + '.aspx': ['html', 'blue'], + '.ascx': ['html', 'green'], + '.asax': ['html', 'yellow'], + '.master': ['html', 'yellow'], + '.cc': ['cpp', 'blue'], + '.cpp': ['cpp', 'blue'], + '.cxx': ['cpp', 'blue'], + '.c++': ['cpp', 'blue'], + '.hh': ['cpp', 'purple'], + '.hpp': ['cpp', 'purple'], + '.hxx': ['cpp', 'purple'], + '.h++': ['cpp', 'purple'], + '.mm': ['cpp', 'yellow'], + '.clj': ['clojure', 'green'], + '.cljs': ['clojure', 'green'], + '.cljc': ['clojure', 'green'], + '.edn': ['clojure', 'blue'], + '.cfc': ['coldfusion', 'blue'], + '.cfm': ['coldfusion', 'blue'], + '.coffee': ['coffee', 'yellow'], + '.litcoffee': ['coffee', 'yellow'], + '.config': ['config', 'grey-light'], + '.cfg': ['config', 'grey-light'], + '.conf': ['config', 'grey-light'], + '.cr': ['crystal', 'white'], + '.ecr': ['crystal_embedded', 'white'], + '.slang': ['crystal_embedded', 'white'], + '.cson': ['json', 'yellow'], + '.css': ['css', 'blue'], + '.css.map': ['css', 'blue'], + '.sss': ['css', 'blue'], + '.csv': ['csv', 'green'], + '.xls': ['xls', 'green'], + '.xlsx': ['xls', 'green'], + '.cu': ['cu', 'green'], + '.cuh': ['cu', 'purple'], + '.hu': ['cu', 'purple'], + '.cake': ['cake', 'red'], + '.ctp': ['cake_php', 'red'], + '.d': ['d', 'red'], + '.doc': ['word', 'blue'], + '.docx': ['word', 'blue'], + '.ejs': ['ejs', 'yellow'], + '.ex': ['elixir', 'purple'], + '.exs': ['elixir_script', 'purple'], + '.elm': ['elm', 'blue'], + '.ico': ['favicon', 'yellow'], + '.fs': ['f-sharp', 'blue'], + '.fsx': ['f-sharp', 'blue'], + '.gitignore': ['git', 'ignore'], + '.gitconfig': ['git', 'ignore'], + '.gitkeep': ['git', 'ignore'], + '.gitattributes': ['git', 'ignore'], + '.gitmodules': ['git', 'ignore'], + '.go': ['go2', 'blue'], + '.slide': ['go', 'blue'], + '.article': ['go', 'blue'], + '.gd': ['godot', 'blue'], + '.godot': ['godot', 'red'], + '.tres': ['godot', 'yellow'], + '.tscn': ['godot', 'purple'], + '.gradle': ['gradle', 'blue'], + '.groovy': ['grails', 'green'], + '.gsp': ['grails', 'green'], + '.gql': ['graphql', 'pink'], + '.graphql': ['graphql', 'pink'], + '.graphqls': ['graphql', 'pink'], + '.hack': ['hacklang', 'orange'], + '.haml': ['haml', 'red'], + '.handlebars': ['mustache', 'orange'], + '.hbs': ['mustache', 'orange'], + '.hjs': ['mustache', 'orange'], + '.hs': ['haskell', 'purple'], + '.lhs': ['haskell', 'purple'], + '.hx': ['haxe', 'orange'], + '.hxs': ['haxe', 'yellow'], + '.hxp': ['haxe', 'blue'], + '.hxml': ['haxe', 'purple'], + '.html': ['html', 'orange'], + '.jade': ['jade', 'red'], + '.java': ['java', 'red'], + '.class': ['java', 'blue'], + '.classpath': ['java', 'red'], + '.properties': ['java', 'red'], + '.js': ['javascript', 'yellow'], + '.js.map': ['javascript', 'yellow'], + '.spec.js': ['javascript', 'orange'], + '.test.js': ['javascript', 'orange'], + '.es': ['javascript', 'yellow'], + '.es5': ['javascript', 'yellow'], + '.es6': ['javascript', 'yellow'], + '.es7': ['javascript', 'yellow'], + '.jinja': ['jinja', 'red'], + '.jinja2': ['jinja', 'red'], + '.json': ['json', 'yellow'], + '.jl': ['julia', 'purple'], + '.kt': ['kotlin', 'orange'], + '.kts': ['kotlin', 'orange'], + '.dart': ['dart', 'blue'], + '.less': ['less', 'blue'], + '.liquid': ['liquid', 'green'], + '.ls': ['livescript', 'blue'], + '.lua': ['lua', 'blue'], + '.markdown': ['markdown', 'blue'], + '.md': ['markdown', 'blue'], + '.argdown': ['argdown', 'blue'], + '.ad': ['argdown', 'blue'], + '.mustache': ['mustache', 'orange'], + '.stache': ['mustache', 'orange'], + '.nim': ['nim', 'yellow'], + '.nims': ['nim', 'yellow'], + '.github-issues': ['github', 'white'], + '.ipynb': ['notebook', 'blue'], + '.njk': ['nunjucks', 'green'], + '.nunjucks': ['nunjucks', 'green'], + '.nunjs': ['nunjucks', 'green'], + '.nunj': ['nunjucks', 'green'], + '.njs': ['nunjucks', 'green'], + '.nj': ['nunjucks', 'green'], + '.npm-debug.log': ['npm', 'ignore'], + '.npmignore': ['npm', 'red'], + '.npmrc': ['npm', 'red'], + '.ml': ['ocaml', 'orange'], + '.mli': ['ocaml', 'orange'], + '.cmx': ['ocaml', 'orange'], + '.cmxa': ['ocaml', 'orange'], + '.odata': ['odata', 'orange'], + '.pl': ['perl', 'blue'], + '.php': ['php', 'purple'], + '.php.inc': ['php', 'purple'], + '.pipeline': ['pipeline', 'orange'], + '.pddl': ['pddl', 'purple'], + '.plan': ['plan', 'green'], + '.happenings': ['happenings', 'blue'], + '.ps1': ['powershell', 'blue'], + '.psd1': ['powershell', 'blue'], + '.psm1': ['powershell', 'blue'], + '.prisma': ['prisma', 'blue'], + '.pug': ['pug', 'red'], + '.pp': ['puppet', 'yellow'], + '.epp': ['puppet', 'yellow'], + '.purs': ['purescript', 'white'], + '.py': ['python', 'blue'], + '.jsx': ['react', 'blue'], + '.spec.jsx': ['react', 'orange'], + '.test.jsx': ['react', 'orange'], + '.cjsx': ['react', 'blue'], + '.spec.tsx': ['react', 'orange'], + '.test.tsx': ['react', 'orange'], + '.re': ['reasonml', 'red'], + '.res': ['rescript', 'red'], + '.resi': ['rescript', 'pink'], + '.R': ['R', 'blue'], + '.rmd': ['R', 'blue'], + '.rb': ['ruby', 'red'], + '.erb': ['html_erb', 'red'], + '.erb.html': ['html_erb', 'red'], + '.html.erb': ['html_erb', 'red'], + '.rs': ['rust', 'grey-light'], + '.sass': ['sass', 'pink'], + '.scss': ['sass', 'pink'], + '.springBeans': ['spring', 'green'], + '.slim': ['slim', 'orange'], + '.smarty.tpl': ['smarty', 'yellow'], + '.tpl': ['smarty', 'yellow'], + '.sbt': ['sbt', 'blue'], + '.scala': ['scala', 'red'], + '.sol': ['ethereum', 'blue'], + '.styl': ['stylus', 'green'], + '.svelte': ['svelte', 'red'], + '.swift': ['swift', 'orange'], + '.sql': ['db', 'pink'], + '.soql': ['db', 'blue'], + '.tf': ['terraform', 'purple'], + '.tf.json': ['terraform', 'purple'], + '.tfvars': ['terraform', 'purple'], + '.tfvars.json': ['terraform', 'purple'], + '.tex': ['tex', 'blue'], + '.sty': ['tex', 'yellow'], + '.dtx': ['tex', 'orange'], + '.ins': ['tex', 'white'], + '.txt': ['default', 'white'], + '.toml': ['config', 'grey-light'], + '.twig': ['twig', 'green'], + '.ts': ['typescript', 'blue'], + '.tsx': ['typescript', 'blue'], + '.spec.ts': ['typescript', 'orange'], + '.test.ts': ['typescript', 'orange'], + '.vala': ['vala', 'grey-light'], + '.vapi': ['vala', 'grey-light'], + '.component': ['html', 'orange'], + '.vue': ['vue', 'green'], + '.wasm': ['wasm', 'purple'], + '.wat': ['wat', 'purple'], + '.xml': ['xml', 'orange'], + '.yml': ['yml', 'purple'], + '.yaml': ['yml', 'purple'], + '.pro': ['prolog', 'orange'], + '.zig': ['zig', 'orange'], + '.jar': ['zip', 'red'], + '.zip': ['zip', 'grey-light'], + '.wgt': ['wgt', 'blue'], + '.ai': ['illustrator', 'yellow'], + '.psd': ['photoshop', 'blue'], + '.pdf': ['pdf', 'red'], + '.eot': ['font', 'red'], + '.ttf': ['font', 'red'], + '.woff': ['font', 'red'], + '.woff2': ['font', 'red'], + '.avif': ['image', 'purple'], + '.gif': ['image', 'purple'], + '.jpg': ['image', 'purple'], + '.jpeg': ['image', 'purple'], + '.png': ['image', 'purple'], + '.pxm': ['image', 'purple'], + '.svg': ['svg', 'purple'], + '.svgx': ['image', 'purple'], + '.tiff': ['image', 'purple'], + '.webp': ['image', 'purple'], + '.sublime-project': ['sublime', 'orange'], + '.sublime-workspace': ['sublime', 'orange'], + '.code-search': ['code-search', 'purple'], + '.sh': ['shell', 'green'], + '.zsh': ['shell', 'green'], + '.fish': ['shell', 'green'], + '.zshrc': ['shell', 'green'], + '.bashrc': ['shell', 'green'], + '.mov': ['video', 'pink'], + '.ogv': ['video', 'pink'], + '.webm': ['video', 'pink'], + '.avi': ['video', 'pink'], + '.mpg': ['video', 'pink'], + '.mp4': ['video', 'pink'], + '.mp3': ['audio', 'purple'], + '.ogg': ['audio', 'purple'], + '.wav': ['audio', 'purple'], + '.flac': ['audio', 'purple'], + '.3ds': ['svg', 'blue'], + '.3dm': ['svg', 'blue'], + '.stl': ['svg', 'blue'], + '.obj': ['svg', 'blue'], + '.dae': ['svg', 'blue'], + '.bat': ['windows', 'blue'], + '.cmd': ['windows', 'blue'], + '.babelrc': ['babel', 'yellow'], + '.babelrc.js': ['babel', 'yellow'], + '.babelrc.cjs': ['babel', 'yellow'], + '.bazelrc': ['bazel', 'grey'], + '.bowerrc': ['bower', 'orange'], + '.codeclimate.yml': ['code-climate', 'green'], + '.eslintrc': ['eslint', 'purple'], + '.eslintrc.js': ['eslint', 'purple'], + '.eslintrc.cjs': ['eslint', 'purple'], + '.eslintrc.yaml': ['eslint', 'purple'], + '.eslintrc.yml': ['eslint', 'purple'], + '.eslintrc.json': ['eslint', 'purple'], + '.eslintignore': ['eslint', 'grey'], + '.firebaserc': ['firebase', 'orange'], + '.gitlab-ci.yml': ['gitlab', 'orange'], + '.jshintrc': ['javascript', 'blue'], + '.jscsrc': ['javascript', 'blue'], + '.stylelintrc': ['stylelint', 'white'], + '.stylelintrc.json': ['stylelint', 'white'], + '.stylelintrc.yaml': ['stylelint', 'white'], + '.stylelintrc.yml': ['stylelint', 'white'], + '.stylelintrc.js': ['stylelint', 'white'], + '.stylelintignore': ['stylelint', 'grey'], + '.direnv': ['config', 'grey-light'], + '.env': ['config', 'grey-light'], + '.static': ['config', 'grey-light'], + '.editorconfig': ['config', 'grey-light'], + '.slugignore': ['config', 'grey-light'], + '.tmp': ['clock', 'grey-light'], + '.htaccess': ['config', 'grey-light'], + '.key': ['lock', 'green'], + '.cert': ['lock', 'green'], + '.cer': ['lock', 'green'], + '.crt': ['lock', 'green'], + '.pem': ['lock', 'green'], + '.DS_Store': ['ignored', 'ignore'], + }, + partials: [ + ['TODO.md', ['todo', 'blue']], + ['TODO.txt', ['todo', 'blue']], + ['TODO', ['todo', 'blue']], + ['Procfile', ['heroku', 'purple']], + ['cmakelists.txt', ['makefile', 'blue']], + ['CMakeLists.txt', ['makefile', 'blue']], + ['CMAKELISTS.txt', ['makefile', 'blue']], + ['CMAKELISTS.TXT', ['makefile', 'blue']], + ['omakefile', ['makefile', 'grey-light']], + ['OMakefile', ['makefile', 'grey-light']], + ['OMAKEFILE', ['makefile', 'grey-light']], + ['qmakefile', ['makefile', 'purple']], + ['QMakefile', ['makefile', 'purple']], + ['QMAKEFILE', ['makefile', 'purple']], + ['makefile', ['makefile', 'orange']], + ['Makefile', ['makefile', 'orange']], + ['MAKEFILE', ['makefile', 'orange']], + ['CONTRIBUTING.md', ['license', 'red']], + ['CONTRIBUTING.txt', ['license', 'red']], + ['CONTRIBUTING', ['license', 'red']], + ['COMPILING.md', ['license', 'orange']], + ['COMPILING.txt', ['license', 'orange']], + ['COMPILING', ['license', 'orange']], + ['COPYING.md', ['license', 'yellow']], + ['COPYING.txt', ['license', 'yellow']], + ['COPYING', ['license', 'yellow']], + ['LICENCE.md', ['license', 'yellow']], + ['LICENSE.md', ['license', 'yellow']], + ['LICENCE.txt', ['license', 'yellow']], + ['LICENSE.txt', ['license', 'yellow']], + ['LICENCE', ['license', 'yellow']], + ['LICENSE', ['license', 'yellow']], + ['gulpfile.js', ['gulp', 'red']], + ['gulpfile', ['gulp', 'red']], + ['Gulpfile', ['gulp', 'red']], + ['GULPFILE', ['gulp', 'red']], + ['docker-compose.override.yaml', ['docker', 'pink']], + ['docker-compose.override.yml', ['docker', 'pink']], + ['docker-compose.yaml', ['docker', 'pink']], + ['docker-compose.yml', ['docker', 'pink']], + ['docker-healthcheck', ['docker', 'green']], + ['.dockerignore', ['docker', 'grey']], + ['DOCKERFILE', ['docker', 'blue']], + ['Dockerfile', ['docker', 'blue']], + ['dockerfile', ['docker', 'blue']], + ['gemfile', ['ruby', 'red']], + ['Gemfile', ['ruby', 'red']], + ['mix', ['hex', 'red']], + ], + default: ['default', 'white'], +}; + +const rawIcons = { + astro: + '', + bsl: '', + mdo: '', + salesforce: + '', + asm: '', + bicep: + '', + bazel: + '', + c: '', + 'c-sharp': + '', + html: '', + cpp: '', + clojure: + '', + coldfusion: + '', + coffee: + '', + config: + '', + crystal: + '', + crystal_embedded: + '', + json: '', + css: '', + csv: '', + xls: '', + cu: '', + cake: '', + cake_php: + '', + d: '', + word: '', + ejs: '', + elixir: + '', + elixir_script: + '', + hex: '', + elm: '', + favicon: + '', + 'f-sharp': + '', + git: '', + go2: '', + go: '', + godot: + '', + gradle: + '', + grails: + '', + graphql: + '', + hacklang: + '', + haml: '', + mustache: + '', + haskell: + '', + haxe: '', + jade: '', + java: '', + javascript: + '', + jinja: + '', + julia: + '', + karma: + '', + kotlin: + '', + dart: '', + less: '', + liquid: + '', + livescript: + '', + lua: '', + markdown: + '', + argdown: + '', + info: '', + clock: + '', + maven: + '', + nim: '', + github: + '', + notebook: + '', + nunjucks: + '', + npm: '', + ocaml: + '', + odata: + '', + perl: '', + php: '', + pipeline: + '', + pddl: '', + plan: '', + happenings: + '', + powershell: + '', + prisma: + '', + pug: '', + puppet: + '', + purescript: + '', + python: + '', + react: + '', + reasonml: + '', + rescript: + '', + R: '', + ruby: '', + html_erb: + '', + rust: '', + sass: '', + spring: + '', + slim: '', + smarty: + '', + sbt: '', + scala: + '', + ethereum: + '', + stylus: + '', + svelte: + '', + swift: + '', + db: '', + terraform: + '', + tex: '', + default: + '', + twig: '', + typescript: + '', + tsconfig: + '', + vala: '', + vue: '', + wasm: '', + wat: '', + xml: '', + yml: '', + prolog: + '', + zig: '', + zip: '', + wgt: '', + illustrator: + '', + photoshop: + '', + pdf: '', + font: '', + image: + '', + svg: '', + sublime: + '', + 'code-search': + '', + shell: + '', + video: + '', + audio: + '', + windows: + '', + jenkins: + '', + babel: + '', + bower: + '', + docker: + '', + 'code-climate': + '', + eslint: + '', + firebase: + '', + firefox: + '', + gitlab: + '', + grunt: + '', + gulp: '', + ionic: + '', + platformio: + '', + rollup: + '', + stylelint: + '', + yarn: '', + webpack: + '', + lock: '', + license: + '', + makefile: + '', + heroku: + '', + todo: '', + npm_ignored: + '', + ignored: + '', +}; + +type IconDetails = [string, string]; + +interface SetiTheme { + blue: string; + grey: string; + 'grey-light': string; + green: string; + orange: string; + pink: string; + purple: string; + red: string; + white: string; + yellow: string; + ignore: string; +} + +type Color = keyof SetiTheme; + +interface Icon { + svg: string; + color: Color; +} + +const definitions = rawDefinitions as unknown as { + default: IconDetails; + extensions: { [extension: string]: IconDetails }; + files: { [file: string]: IconDetails }; + partials: [string, IconDetails][]; +}; +const icons = rawIcons as unknown as { + [icon: string]: string; +}; + +const getDetails = (fileName: string): IconDetails => { + if (definitions.files[fileName]) { + return definitions.files[fileName]; + } + let extension = fileName.slice(fileName.indexOf('.')); + while (extension !== '') { + if (definitions.extensions[extension]) { + return definitions.extensions[extension]; + } + // look for next "." + extension = extension.slice(1); + extension = extension.slice(extension.indexOf('.')); + } + for (const partial of definitions.partials) { + if (fileName.indexOf(partial[0]) > -1) { + return partial[1]; + } + } + return definitions.default; +}; + +export const getIcon = (fileName: string): Icon => { + const [icon, color] = getDetails(fileName); + return { svg: icons[icon], color } as Icon; +}; From 882b2a6ae93ed1da55619af3e010bb0b7fa45410 Mon Sep 17 00:00:00 2001 From: delucis Date: Wed, 14 Dec 2022 19:36:00 +0100 Subject: [PATCH 02/11] Add rehype plugin that transforms an unordered list into a file tree --- package.json | 2 + pnpm-lock.yaml | 19 ++++ src/components/internal/rehype-file-tree.ts | 114 ++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 src/components/internal/rehype-file-tree.ts diff --git a/package.json b/package.json index a594fec776bf1..d890a5cfae5e8 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "fast-glob": "^3.2.11", "github-slugger": "^1.5.0", "gray-matter": "^4.0.3", + "hast-util-from-html": "^1.0.0", "hast-util-to-string": "^2.0.0", "hastscript": "^7.0.2", "html-escaper": "^3.0.3", @@ -70,6 +71,7 @@ "prettier": "^2.8.1", "prettier-plugin-astro": "^0.7.0", "prompts": "^2.4.2", + "rehype": "^12.0.1", "remark": "^14.0.2", "remark-custom-heading-id": "^1.0.0", "remark-directive": "^2.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c3aaa704da1b8..67c45da517671 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,7 @@ specifiers: fast-glob: ^3.2.11 github-slugger: ^1.5.0 gray-matter: ^4.0.3 + hast-util-from-html: ^1.0.0 hast-util-to-string: ^2.0.0 hastscript: ^7.0.2 html-escaper: ^3.0.3 @@ -51,6 +52,7 @@ specifiers: prettier: ^2.8.1 prettier-plugin-astro: ^0.7.0 prompts: ^2.4.2 + rehype: ^12.0.1 rehype-autolink-headings: ^6.1.1 rehype-slug: ^5.0.1 remark: ^14.0.2 @@ -109,6 +111,7 @@ devDependencies: fast-glob: 3.2.11 github-slugger: 1.5.0 gray-matter: 4.0.3 + hast-util-from-html: 1.0.0 hast-util-to-string: 2.0.0 hastscript: 7.0.2 html-escaper: 3.0.3 @@ -126,6 +129,7 @@ devDependencies: prettier: 2.8.1 prettier-plugin-astro: 0.7.0 prompts: 2.4.2 + rehype: 12.0.1 remark: 14.0.2 remark-custom-heading-id: 1.0.0 remark-directive: 2.0.1 @@ -2930,6 +2934,15 @@ packages: web-namespaces: 2.0.1 dev: true + /hast-util-from-html/1.0.0: + resolution: {integrity: sha512-tXYPhk28aMtDjGb4xNDaxtGKqlyZAEPGjN12jPCjczWppdLSrG/0r604a3FMvrd+9nV1HclILQiVqMnuPxN0WQ==} + dependencies: + '@types/hast': 2.3.4 + hast-util-from-parse5: 7.1.0 + parse5: 7.1.2 + vfile: 5.3.4 + dev: true + /hast-util-from-parse5/7.1.0: resolution: {integrity: sha512-m8yhANIAccpU4K6+121KpPP55sSl9/samzQSQGpb0mTExcNh2WlvjtMwSWFhg6uqD4Rr6Nfa8N6TMypQM51rzQ==} dependencies: @@ -4216,6 +4229,12 @@ packages: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} dev: true + /parse5/7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.4.0 + dev: true + /path-browserify/1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} dev: true diff --git a/src/components/internal/rehype-file-tree.ts b/src/components/internal/rehype-file-tree.ts new file mode 100644 index 0000000000000..baf38b55ab8f9 --- /dev/null +++ b/src/components/internal/rehype-file-tree.ts @@ -0,0 +1,114 @@ +import { rehype } from 'rehype'; +import { visit, CONTINUE, SKIP } from 'unist-util-visit'; +import { fromHtml } from 'hast-util-from-html'; +import { toString } from 'hast-util-to-string'; +import { h } from 'hastscript'; +import type { Element, HChild } from 'hastscript/lib/core'; +import { getIcon } from './file-tree-icons'; + +/** Make a text node with the pass string as its contents. */ +const Text = (value = ''): { type: 'text'; value: string } => ({ type: 'text', value }); + +/** Convert an HTML string containing an SVG into a HAST element node. */ +const makeSVGIcon = (svgString: string) => { + const root = fromHtml(svgString, { fragment: true }); + const svg = root.children[0] as Element; + svg.properties = { + ...svg.properties, + width: 16, + height: 16, + class: 'tree-icon', + 'aria-hidden': 'true', + }; + return svg; +}; + +const FileIcon = (filename: string) => { + const { svg } = getIcon(filename); + return makeSVGIcon(svg); +}; + +const FolderIcon = makeSVGIcon( + '' +); + +export const fileTreeProcessor = rehype().use(function fileTree() { + return (tree, file) => { + const { directoryLabel } = file.data as { directoryLabel: string }; + 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) + ); + + if (node.tagName !== 'li') return CONTINUE; + + // Ensure node has properties so we can assign classes later. + if (!node.properties) node.properties = {}; + + const [firstChild, ...otherChildren] = node.children; + + const comment: HChild[] = []; + if (firstChild.type === 'text') { + const [filename, ...fragments] = firstChild.value.split(' '); + firstChild.value = filename; + comment.push(fragments.join(' ')); + } + 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 = toString(firstChild); + + const isDirectory = /\/\s*$/.test(firstChildTextContent); + const isPlaceholder = /^\s*(\.{3}|…)\s*$/.test(firstChildTextContent); + const isHighlighted = firstChild.type === 'element' && firstChild.tagName === 'strong'; + const hasContents = otherChildren.length > 0; + + const fileExtension = isDirectory + ? 'dir' + : firstChildTextContent.trim().split('.').pop() || ''; + + const icon = h('span', isDirectory ? FolderIcon : FileIcon(firstChildTextContent)); + if (!icon.properties) icon.properties = {}; + if (isDirectory) { + icon.properties['aria-label'] = directoryLabel; + } + + node.properties.class = isDirectory ? 'directory' : 'file'; + if (isPlaceholder) node.properties.class += ' empty'; + node.properties['data-filetype'] = fileExtension; + + const treeEntry = h( + 'span', + { class: 'tree-entry' }, + h('span', { class: isHighlighted ? 'highlight' : '' }, [ + isPlaceholder ? null : icon, + firstChild, + ]), + Text(comment.length > 0 ? ' ' : ''), + comment.length > 0 ? h('span', { class: 'comment' }, ...comment) : Text() + ); + + if (isDirectory) { + 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; + }); + }; +}); From 37db38f7adc55d73cf3c0e055be316fff072e7f2 Mon Sep 17 00:00:00 2001 From: delucis Date: Wed, 14 Dec 2022 19:36:26 +0100 Subject: [PATCH 03/11] Create `` component to run rehype transform and inject styles --- src/components/FileTree.astro | 135 ++++++++++++++++++++++++++++++++++ src/i18n/en/ui.ts | 2 + 2 files changed, 137 insertions(+) create mode 100644 src/components/FileTree.astro diff --git a/src/components/FileTree.astro b/src/components/FileTree.astro new file mode 100644 index 0000000000000..303d2ee5acb3d --- /dev/null +++ b/src/components/FileTree.astro @@ -0,0 +1,135 @@ +--- +import { useTranslations } from '../i18n/util'; +import { fileTreeProcessor } from './internal/rehype-file-tree'; + +const content = await Astro.slots.render('default'); +if (!/^\s*
    /.test(content)) { + throw new Error( + ` component expects its content to be an unordered list but found HTML starting with “${content.slice( + 0, + 20 + )}...”` + ); +} + +const t = useTranslations(Astro); + +const processedContent = await fileTreeProcessor.process({ + value: content, + data: { directoryLabel: t('fileTree.directoryLabel') }, +}); +--- + + + + diff --git a/src/i18n/en/ui.ts b/src/i18n/en/ui.ts index 7438f2225cb78..82322c2787cee 100644 --- a/src/i18n/en/ui.ts +++ b/src/i18n/en/ui.ts @@ -84,4 +84,6 @@ export default { 'tutorial.getReady': 'Get ready to…', // Feedback Fish widget 'feedback.button': 'Give us feedback', + // `` component + 'fileTree.directoryLabel': 'Directory', }; From 2a2acf7e97831ef3aa1d67e2533bc8f5357e08fe Mon Sep 17 00:00:00 2001 From: delucis Date: Wed, 14 Dec 2022 19:50:55 +0100 Subject: [PATCH 04/11] Add icon association for `.cjs` and `.mjs` files --- src/components/internal/file-tree-icons.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/internal/file-tree-icons.ts b/src/components/internal/file-tree-icons.ts index 1c36fac255ffc..2156d5c31a5f8 100644 --- a/src/components/internal/file-tree-icons.ts +++ b/src/components/internal/file-tree-icons.ts @@ -206,6 +206,8 @@ const rawDefinitions = { '.es5': ['javascript', 'yellow'], '.es6': ['javascript', 'yellow'], '.es7': ['javascript', 'yellow'], + '.cjs': ['javascript', 'yellow'], + '.mjs': ['javascript', 'yellow'], '.jinja': ['jinja', 'red'], '.jinja2': ['jinja', 'red'], '.json': ['json', 'yellow'], From f29e4f5f134f7e41de849d5bd85a314adbd1e87b Mon Sep 17 00:00:00 2001 From: delucis Date: Wed, 14 Dec 2022 20:05:09 +0100 Subject: [PATCH 05/11] Replace ASCII art file trees with component in English docs --- .../en/core-concepts/project-structure.md | 49 ++++++++++--------- src/pages/en/core-concepts/routing.md | 42 ++++++++-------- src/pages/en/guides/cms/contentful.md | 33 +++++++------ src/pages/en/guides/cms/storyblok.md | 29 +++++------ src/pages/en/guides/cms/wordpress.md | 20 ++++---- src/pages/en/install/manual.md | 27 +++++----- src/pages/en/reference/publish-to-npm.md | 36 +++++++------- 7 files changed, 122 insertions(+), 114 deletions(-) diff --git a/src/pages/en/core-concepts/project-structure.md b/src/pages/en/core-concepts/project-structure.md index 1c63dd24adf58..0b538b51a9f3e 100644 --- a/src/pages/en/core-concepts/project-structure.md +++ b/src/pages/en/core-concepts/project-structure.md @@ -3,6 +3,8 @@ layout: ~/layouts/MainLayout.astro title: Project Structure description: Learn how to structure a project with Astro. i18nReady: true +setup: | + import FileTree from '~/components/FileTree.astro' --- Your new Astro project generated from the `create-astro` CLI wizard already includes some files and folders. Others, you will create yourself and add to Astro's existing file structure. @@ -23,30 +25,29 @@ Astro leverages an opinionated folder layout for your project. Every Astro proje A common Astro project directory might look like this: -``` -├── src/ -│ ├── components/ -│ │ ├── Header.astro -│ │ └-─ Button.jsx -│ ├── layouts/ -│ │ └-─ PostLayout.astro -│ └── pages/ -│ │ ├── posts/ -│ │ │ ├── post1.md -│ │ │ ├── post2.md -│ │ │ └── post3.md -│ │ └── index.astro -│ └── styles/ -│ └-─ global.css -├── public/ -│ ├── robots.txt -│ ├── favicon.svg -│ └-─ social-image.png -├── astro.config.mjs -├── package.json -└── tsconfig.json - -``` + +- public/ + - robots.txt + - favicon.svg + - social-image.png +- src/ + - components/ + - Header.astro + - Button.jsx + - layouts/ + - PostLayout.astro + - pages/ + - posts/ + - post1.md + - post2.mdx + - post3.md + - index.astro + - styles/ + - global.css +- astro.config.mjs +- package.json +- tsconfig.json + ### `src/` diff --git a/src/pages/en/core-concepts/routing.md b/src/pages/en/core-concepts/routing.md index c66d53015a316..2dc6f7758e879 100644 --- a/src/pages/en/core-concepts/routing.md +++ b/src/pages/en/core-concepts/routing.md @@ -3,6 +3,8 @@ layout: ~/layouts/MainLayout.astro title: Routing description: An intro to routing with Astro. i18nReady: true +setup: | + import FileTree from '~/components/FileTree.astro' --- Astro uses **file-based routing** to generate your build URLs based on the file layout of your project `src/pages/` directory. When a file is added to the `src/pages` directory of your project, it is automatically available as a route based on its filename. @@ -221,14 +223,13 @@ const { title, text } = page; It's possible for multiple routes to match the same URL path. For example each of these routes would match `/posts/create`: -``` -└── pages/ -│ ├── posts/ -│ │ ├── create.astro -│ │ ├── [pid].astro -│ │ └── [...slug].astro - -``` + +- src/pages/ + - posts/ + - create.astro + - [pid].astro + - [...slug].astro + Astro needs to know which route should be used to build the page. To do so, it sorts them according to the following rules: @@ -381,16 +382,15 @@ This allows you to create private pages, and also to co-locate tests, utilities, In this example, only `src/pages/index.astro` and `src/pages/posts/post1.md` will be built as page routes and HTML files. -```md mark="post1.md" mark="index.astro" -src/ -└── pages/ - ├── _hidden-directory/ - │ ├── page1.md - │ └── page2.md - ├── _hidden-page.astro - ├── index.astro - └── posts/ - ├── _SomeComponent.astro - ├── _utils.js - └── post1.md -``` + +- src/pages/ + - _hidden-directory/ + - page1.md + - page2.md + - _hidden-page.astro + - **index.astro** + - posts/ + - _SomeComponent.astro + - _utils.js + - **post1.md** + diff --git a/src/pages/en/guides/cms/contentful.md b/src/pages/en/guides/cms/contentful.md index c4abe21adb24c..ec87dd7a4c70f 100644 --- a/src/pages/en/guides/cms/contentful.md +++ b/src/pages/en/guides/cms/contentful.md @@ -2,6 +2,7 @@ title: Contentful & Astro description: Add content to your Astro project using Contentful as a CMS setup: | + import FileTree from '~/components/FileTree.astro' import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro' layout: ~/layouts/CMSLayout.astro service: Contentful @@ -54,13 +55,13 @@ Read more about [using environment variables](/en/guides/environment-variables/) Your root directory should now include these new files: -```ini title="Project Structure" ins={2-3} -├── src/ -│ └── env.d.ts -├── .env -├── astro.config.mjs -└── package.json -``` + +- src/ + - **env.d.ts** +- **.env** +- astro.config.mjs +- package.json + ### Installing dependencies @@ -111,15 +112,15 @@ At build time, your content will be fetched from the **Contentful delivery API** Finally, your root directory should now include these new files: -```ini ins={3-4} -├── src/ -│ └── env.d.ts -│ └── lib/ -│ └── contentful.ts -├── .env -├── astro.config.mjs -└── package.json -``` + +- src/ + - env.d.ts + - lib/ + - **contentful.ts** +- .env +- astro.config.mjs +- package.json + ### Fetching data diff --git a/src/pages/en/guides/cms/storyblok.md b/src/pages/en/guides/cms/storyblok.md index 5af313613962c..63d680a6b938c 100644 --- a/src/pages/en/guides/cms/storyblok.md +++ b/src/pages/en/guides/cms/storyblok.md @@ -4,6 +4,7 @@ description: Add content to your Astro project using Storyblok as a CMS layout: ~/layouts/CMSLayout.astro service: Storyblok setup: | + import FileTree from '~/components/FileTree.astro' import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro' stub: false --- @@ -36,12 +37,12 @@ Now, you should be able to use these environment variables in your project. Your root directory should now include this new file: -```ini title="Project Structure" ins={2} -├── src/ -├── .env -├── astro.config.mjs -└── package.json -``` + +- src/ +- **.env** +- astro.config.mjs +- package.json + ### Installing dependencies @@ -148,14 +149,14 @@ To render our content, the integration provides utility functions such as: Your root directory should include this new file: -```ini title="Project Structure" ins={3} -├── src/ -│ └── storyblok/ -│ └── BlogPost.astro -├── .env -├── astro.config.mjs -└── package.json -``` + +- src/ + - storyblok/ + - **BlogPost.astro** +- .env +- astro.config.mjs +- package.json + Finally, to connect the `blogPost` Blok to the `BlogPost` component, add a new property to your components object in your Astro config file. diff --git a/src/pages/en/guides/cms/wordpress.md b/src/pages/en/guides/cms/wordpress.md index 38d8c901e29db..58243337a189e 100644 --- a/src/pages/en/guides/cms/wordpress.md +++ b/src/pages/en/guides/cms/wordpress.md @@ -4,6 +4,7 @@ description: Add content to your Astro project using WordPress as a CMS layout: ~/layouts/CMSLayout.astro stub: false service: WordPress +setup: import FileTree from '~/components/FileTree.astro' --- [WordPress](https://wordpress.org/) is a content management system that includes its own frontend, but can also be used as a headless CMS to provide content to your Astro project. @@ -73,15 +74,16 @@ This example fetches data from a WordPress site whose content types have already The page `src/pages/index.astro` lists each dinosaur, with a description and link to its own page. -```ini title="Project Structure" {3} -├── src/ -├── pages/ -│ └── index.astro -│ └── dinos/ -│ └── [slug].astro -├── astro.config.mjs -└── package.json -``` + +- src/ + - pages/ + - **index.astro** + - dinos/ + - [slug].astro +- astro.config.mjs +- package.json + + Fetching via the API returns an object that includes the properties: - `title.rendered` - Contains the HTML rendering of the title of the post. diff --git a/src/pages/en/install/manual.md b/src/pages/en/install/manual.md index 9dd3760385ed0..a603a32b41066 100644 --- a/src/pages/en/install/manual.md +++ b/src/pages/en/install/manual.md @@ -3,6 +3,7 @@ title: Install Astro manually description: How to install Astro manually with NPM, PNPM, or Yarn. layout: ~/layouts/MainLayout.astro setup: | + import FileTree from '~/components/FileTree.astro'; import InstallGuideTabGroup from '~/components/TabGroup/InstallGuideTabGroup.astro'; import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro' i18nReady: true @@ -172,19 +173,19 @@ Finally, create `src/env.d.ts` to let TypeScript know about ambient types availa If you have followed the steps above, your project directory should now look like this: -``` -├── node_modules/ -├── public/ -│ └── robots.txt -├── src/ -│ ├── pages/ -│ │ └── index.astro -│ └── env.d.ts -├── astro.config.mjs -├── package-lock.json (or: yarn.lock, pnpm-lock.yaml, etc.) -├── package.json -└── tsconfig.json -``` + +- node_modules/ +- public/ + - robots.txt +- src/ + - pages/ + - index.astro + - env.d.ts +- astro.config.mjs +- package-lock.json or `yarn.lock`, `pnpm-lock.yaml`, etc. +- package.json +- tsconfig.json + Congratulations, you're now set up to use Astro! diff --git a/src/pages/en/reference/publish-to-npm.md b/src/pages/en/reference/publish-to-npm.md index d0d7e149961a1..192a5b17bac1a 100644 --- a/src/pages/en/reference/publish-to-npm.md +++ b/src/pages/en/reference/publish-to-npm.md @@ -3,6 +3,8 @@ layout: ~/layouts/MainLayout.astro title: Publish to NPM description: Learn how to publish Astro components to NPM i18nReady: true +setup: | + import FileTree from '~/components/FileTree.astro' --- Building a new Astro component? **Publish it to [npm!](https://npmjs.com/)** @@ -41,17 +43,17 @@ Before diving in, it will help to have a basic understanding of: To create a new package we strongly recommend configuring your development enviroment to use **workspaces** within your project. This will allow you to develop your component alongside a working copy of Astro. -``` -my-new-component-directory/ -├─ demo/ -| └─ ... for testing and demonstration -├─ package.json -└─ packages/ - └─ my-component/ - ├─ index.js - ├─ package.json - └─ ... additional files used by the package -``` + +- my-new-component-directory/ + - demo/ + - ... for testing and demonstration + - package.json + - packages/ + - my-component/ + - index.js + - package.json + - ... additional files used by the package + In this example, named `my-project`, we create a project with a single package, named `my-component`, and a `demo/` directory for testing and demonstrating the component. @@ -238,12 +240,12 @@ In the meantime, our current recommendation for testing is: 3. Each page should include some different component usage that you'd like to test. 4. Run `astro build` to build your fixtures, then compare the output of the `dist/__fixtures__/` directory to what you expected. -```bash -my-project/demo/src/pages/__fixtures__/ - ├─ test-name-01.astro - ├─ test-name-02.astro - └─ test-name-03.astro -``` + +- my-project/demo/src/pages/\_\_fixtures\_\_/ + - test-name-01.astro + - test-name-02.astro + - test-name-03.astro + ## Publishing your component From 0814b2ae20432bb8d9cf86076e0b42c50198c71d Mon Sep 17 00:00:00 2001 From: delucis Date: Fri, 16 Dec 2022 20:15:43 +0100 Subject: [PATCH 06/11] Add file association for MDX --- src/components/internal/file-tree-icons.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/internal/file-tree-icons.ts b/src/components/internal/file-tree-icons.ts index 2156d5c31a5f8..d4da0197b67c2 100644 --- a/src/components/internal/file-tree-icons.ts +++ b/src/components/internal/file-tree-icons.ts @@ -221,6 +221,7 @@ const rawDefinitions = { '.lua': ['lua', 'blue'], '.markdown': ['markdown', 'blue'], '.md': ['markdown', 'blue'], + '.mdx': ['markdown', 'blue'], '.argdown': ['argdown', 'blue'], '.ad': ['argdown', 'blue'], '.mustache': ['mustache', 'orange'], From 7edda7a4b335d99373f1f4e112f5595fdbdbf6f2 Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Fri, 16 Dec 2022 20:16:36 +0100 Subject: [PATCH 07/11] Revert project structure file to `.md` --- src/pages/en/core-concepts/project-structure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/en/core-concepts/project-structure.md b/src/pages/en/core-concepts/project-structure.md index 0b538b51a9f3e..6591f3a1af474 100644 --- a/src/pages/en/core-concepts/project-structure.md +++ b/src/pages/en/core-concepts/project-structure.md @@ -39,7 +39,7 @@ A common Astro project directory might look like this: - pages/ - posts/ - post1.md - - post2.mdx + - post2.md - post3.md - index.astro - styles/ From a9051313cb947bcbdf22329a9fd75af361bbc4bf Mon Sep 17 00:00:00 2001 From: delucis Date: Fri, 16 Dec 2022 20:20:17 +0100 Subject: [PATCH 08/11] Robustness: support directories without trailing slash if they have contents --- src/components/internal/rehype-file-tree.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/internal/rehype-file-tree.ts b/src/components/internal/rehype-file-tree.ts index baf38b55ab8f9..b7fb95158b889 100644 --- a/src/components/internal/rehype-file-tree.ts +++ b/src/components/internal/rehype-file-tree.ts @@ -64,7 +64,10 @@ export const fileTreeProcessor = rehype().use(function fileTree() { const firstChildTextContent = toString(firstChild); - const isDirectory = /\/\s*$/.test(firstChildTextContent); + // 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'); const isPlaceholder = /^\s*(\.{3}|…)\s*$/.test(firstChildTextContent); const isHighlighted = firstChild.type === 'element' && firstChild.tagName === 'strong'; const hasContents = otherChildren.length > 0; From f8fe4c358c89165775ea0256883b3c26cbe20675 Mon Sep 17 00:00:00 2001 From: delucis Date: Fri, 16 Dec 2022 20:26:10 +0100 Subject: [PATCH 09/11] Fix folder icon centering --- src/components/internal/rehype-file-tree.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/internal/rehype-file-tree.ts b/src/components/internal/rehype-file-tree.ts index b7fb95158b889..d9a6a381caf47 100644 --- a/src/components/internal/rehype-file-tree.ts +++ b/src/components/internal/rehype-file-tree.ts @@ -29,7 +29,7 @@ const FileIcon = (filename: string) => { }; const FolderIcon = makeSVGIcon( - '' + '' ); export const fileTreeProcessor = rehype().use(function fileTree() { From c4b894263078723aa097b6c0a0bbefe2d4a244d8 Mon Sep 17 00:00:00 2001 From: delucis Date: Fri, 16 Dec 2022 20:29:16 +0100 Subject: [PATCH 10/11] Fix subdirectory left border position --- src/components/FileTree.astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/FileTree.astro b/src/components/FileTree.astro index 303d2ee5acb3d..514790f9f21ae 100644 --- a/src/components/FileTree.astro +++ b/src/components/FileTree.astro @@ -67,7 +67,7 @@ const processedContent = await fileTreeProcessor.process({ docs-file-tree ul:is(ul), docs-file-tree .directory > details ul:is(ul) { margin: 0; - margin-inline-start: 0.93em; + margin-inline-start: calc(1em - 1px); border-inline-start: 2px solid var(--theme-divider); padding: 0; list-style: none; From 4c361bc8a8f18017affb8759543ff496580cf750 Mon Sep 17 00:00:00 2001 From: delucis Date: Fri, 16 Dec 2022 20:56:44 +0100 Subject: [PATCH 11/11] Tweak horizontal alignment of folders & files --- src/components/FileTree.astro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/FileTree.astro b/src/components/FileTree.astro index 514790f9f21ae..278e48b796490 100644 --- a/src/components/FileTree.astro +++ b/src/components/FileTree.astro @@ -48,7 +48,7 @@ const processedContent = await fileTreeProcessor.process({ docs-file-tree .directory > details > summary, docs-file-tree .directory > details[open] > summary { border: 0; - padding: var(--y-pad) 0.4em; + padding: var(--y-pad) 0.3em; font-weight: normal; color: var(--theme-text); max-width: 100%;