{{- /* Renders an interactive file tree structure from inline content, resources, data files, or filesystem See https://fixit.lruihao.cn/documentation/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 -}}