Files
FixIt/layouts/_shortcodes/file-tree.html
T
2026-07-13 15:10:42 +08:00

130 lines
5.9 KiB
HTML

{{- /*
Renders an interactive file tree structure from inline content, resources, data files, or filesystem
See https://fixit.lruihao.cn/docs/content-management/shortcodes/extended/file-tree/
@param {String} [path="/"] - The path to scan in filesystem (relative to project root or contentDir)
@param {Int} [level=1] - The expand level of the tree (expand all: -1, collapse all: 0)
@param {Boolean} [folder_slash=false] - Whether to append a trailing "/" to folder names.
@param {String} [file] - The path of a data file in page resources or assets. (JSON/YAML/TOML)
@param {String} [data] - The name of the data file in data/filetree/ directory. (JSON/YAML/TOML)
@param {String} [ignore_list=""] - List of file or folder names to ignore, separated by commas
@param {String} [highlight_list=""] - List of file or folder names to highlight, separated by commas
@param {String} [name] - Project name for the root node, if set to `{path}`, uses the full root path
Priority order (highest to lowest):
1. Inline content (shortcode body) - Parse tree data from shortcode body
2. Resources files (file parameter) - Read data file from page bundle or asset
3. Data files (data parameter) - Load data file from data/filetree/ directory
4. Actual Filesystem (path parameter) - Scan actual directory structure (default)
Fallback mechanism: If the current mode fails (e.g., file not found, invalid format),
the shortcode will automatically fall back to the next available mode in the priority order.
@example
{{< file-tree "content" 2 />}}
{{< file-tree path="content" level=2 folder_slash=true />}}
{{< file-tree file="data/example.yml" />}}
{{< file-tree data="example" />}}
{{< file-tree >}}
- name: my-project
type: dir
children:
- name: src
type: dir
- name: package.json
type: file
{{< /file-tree >}}
Data format note: YAML and JSON support direct array format, while TOML requires a root key 'filetree' due to format limitations.
Example TOML structure:
```file-tree
[[filetree]]
name = "src"
type = "dir"
[[filetree.children]]
name = "index.ts"
type = "file"
[[filetree]]
name = "README.md"
type = "file"
```
*/ -}}
{{- $config := dict "Page" .Page "Key" "filetree" | partial "function/param.html" -}}
{{- $root := cond .IsNamedParams (.Get "path") (.Get 0) | default "/" -}}
{{- $level := cond .IsNamedParams (.Get "level") (.Get 1) -}}
{{- $config = cond ((eq $level 0) | or $level) (dict "level" $level | merge $config) $config -}}
{{- $level = cond (isset $config "level") ($config.level | int) 1 -}}
{{- $folderSlash := cond .IsNamedParams (.Get "folder_slash" | default (.Get "folderSlash")) (.Get 2) | default $config.folder_slash | default false -}}
{{- if .IsNamedParams | and (.Get "folderSlash") -}}
{{- warnidf "v1-deprecated-file-tree-param" "[%s]: The parameter `folderSlash` is deprecated since v1.0.0, use `folder_slash` instead. See %s" .Name .Position -}}
{{- end -}}
{{- $fileName := .Get "file" -}}
{{- $dataName := .Get "data" -}}
{{- $supportExts := slice ".yml" ".yaml" ".json" ".toml" -}}
{{- $ignoreList := union (apply (split (.Get "ignore_list" | default (.Get "ignoreList") | default "") ",") "trim" "." " ") $config.ignore_list -}}
{{- $highlightList := union (apply (split (.Get "highlight_list" | default (.Get "highlightList") | default "") ",") "trim" "." " ") $config.highlight_list -}}
{{- if .IsNamedParams | and (.Get "ignoreList") -}}
{{- warnidf "v1-deprecated-file-tree-param" "[%s]: The parameter `ignoreList` is deprecated since v1.0.0, use `ignore_list` instead. See %s" .Name .Position -}}
{{- end -}}
{{- if .IsNamedParams | and (.Get "highlightList") -}}
{{- warnidf "v1-deprecated-file-tree-param" "[%s]: The parameter `highlightList` is deprecated since v1.0.0, use `highlight_list` instead. See %s" .Name .Position -}}
{{- end -}}
{{- /* Shortcode body */ -}}
{{- $content := strings.TrimSpace .Inner | default "" -}}
{{- /* File Data */ -}}
{{- if $fileName | and (eq $content "") -}}
{{- $ext := path.Ext $fileName | lower -}}
{{- if in $supportExts $ext -}}
{{- with dict "Path" $fileName "Resources" $.Page.Resources | partial "function/resource.html" }}
{{- $content = .Content -}}
{{- else -}}
{{- warnidf "warning-file-tree" "[%s]: no such data file: %s. See %s" $.Name $fileName $.Position -}}
{{- end -}}
{{- else -}}
{{- warnidf "warning-file-tree" "[%s]: Unsupported file format '%s'. Use %s. See %s" $.Name $ext (delimit $supportExts ", " " or ") $.Position -}}
{{- end -}}
{{- end -}}
{{- /* Parse structured data from content or file */ -}}
{{- $treeData := slice -}}
{{- with $content -}}
{{- $treeData = . | unmarshal -}}
{{- if reflect.IsMap $treeData -}}
{{- $treeData = $treeData.filetree -}}
{{- end -}}
{{- end -}}
{{- /* Hugo Data: load from data/filetree/ */ -}}
{{- if $dataName | and (not $treeData) -}}
{{- with index hugo.Data.filetree (printf "%v.%v" $dataName .Page.Language) | default (index hugo.Data.filetree $dataName) -}}
{{- $treeData = . -}}
{{- else -}}
{{- $exts := delimit (apply $supportExts "trim" "." "\\.") "|" -}}
{{- warnidf "warning-file-tree" "[%s]: Data file 'data/filetree/%s.{%s}' not found. See %s" $.Name $dataName $exts $.Position -}}
{{- end -}}
{{- end -}}
{{- /* Filesystem mode: build structured tree data from filesystem */ -}}
{{- if not $treeData -}}
{{- $buildOptions := dict "root" $root "ignore_list" $ignoreList "name" (.Get "name") "lang" .Page.Language -}}
{{- with partial "function/get-file-tree.html" $buildOptions -}}
{{- $treeData = . -}}
{{- else -}}
{{- warnidf "warning-file-tree" "[%s]: The root path does not exist: %s. See %s" .Name $root .Position -}}
{{- end -}}
{{- end -}}
{{- /* Render the file tree */ -}}
{{- $options := dict
"items" $treeData
"level" $level
"folder_slash" $folderSlash
"ignore_list" $ignoreList
"highlight_list" $highlightList
-}}
{{- partial "plugin/file-tree.html" $options -}}