Statiq uses an IO abstraction layer designed to provide flexibility and consistency when dealing with files, directories, and path information.
Notional files and paths are generally represented in Statiq by the
NormalizedPath struct. Think of it as a more standardized way of representing a path as a string. Paths can be either absolute (I.e., starting from the root of the file system) or relative. They can be easily joined together and otherwise manipulated.
Virtual File System
File and directory classes (implementations of
IDirectory) point directly to a potential file or directory within a given file system. They are usually obtained using a normalized path that points to them. Each provider implements their own file and directory classes as appropriate for that provider. File and directory implementations often provide functionality for reading and writing files, creating directories, and otherwise manipulating the file system.
The link between paths, file providers, and files and paths is managed by a virtual file system available through the execution context as the
FileSystem property. It stores all the root, input, and output paths and provides methods to join them with relative paths to get
The root path is an absolute path that acts as a starting point for all other relative paths. By default the root path is set to the working path on the underlying file system from where you execute Statiq.
Statiq uses multiple input paths that together comprise a virtual aggregated set of input files. This lets us do things like specify a set of canonical input files to use for a theme but then selectively override the theme files by putting replacements in an alternate input path with higher precedence.
Input paths are stored in an ordered list. When checking for files, the paths at the end of the list take precedence over those at the start of the list. For example, if path "A" is at index 0, path "B" is at index 1, and they both have a file named "foo.md", the one from path "B" will be used. Further, all paths are aggregated so searching for files or evaluating globbing expressions will consider all files and directories in all input paths. In the example above, getting all input files will result in a set of files from both path "A" and path "B" (with files of the same name from path "B" replacing those from path "A").
By default a single input path of
input is set.
The output path is where Statiq will place output files by default. Note that many modules have the ability to manually specify an output path, so this behavior can be modified on a module by module basis.
By default the output path is set to
Globbing (or globs) is a particular syntax for specifying files or directories using wildcards and other path-based search criteria. Statiq uses a sophisticated globbing engine to give you a lot of flexibility when searching for files. Even better, the globbing engine works with any file provider, be it the local file system or something else.
To demonstrate, let's assume the following files exist in our file provider:
The globbing engine supports the following syntax:
This represents any number of characters at a specific depth. For example,
Note that a wildcard can also be used in the file name. For example,
This represents any number of characters at multiple depths. For example,
This represents multiple expansions for the pattern. For example,
Leaving the last option blank indicates any match at that position. For example,
This represents exclusion and is useful in combination with multiple expansions. For example,
Note that relative globbing patterns are often evaluated from the perspective of your
input folder and not necessarily from where your config file resides, especially if the pattern is telling Statiq where to find certain files for processing. If you're having problems and a globbing pattern isn't returning the files you think it should, try adjusting it to start from the
Because the new IO abstraction includes support for virtual file systems, it can be used to greatly simplify testing your custom modules by providing files that don't actually have to exist on disk. Several classes in the
Statiq.Testing library are provided to help with this.