- Added a
DocumentSourceComparerclass that implementsIEqualityComparer<IDocument>and can be used to compare documents by source path. - Added a
IEnumerable<IDocument>.ContainsBySource()extension method to check if a collection of documents contains a document with a given source path. - Added an improved warning message and early exit out of recursive settings expansion.
- Added a
MediaTypes.IsMediaType()method to help determine if a given path matches specified media type(s).
- Modified the behavior of computed metadata values to cache the value for a given document when using the
=>prefix. The previous behavior that evaluates a computed value every time it's accessed can still be used by prefixing with->instead. In theory this change shouldn't result in any differences in behavior since documents are immutable in the first place (so caching wouldn't be any different from re-evaluating), but if you have computed metadata values that consider state outside the document (such as something likeDateTime.Now), you'll need to switch those to use the->prefix instead. - Updated JavaScriptEngineSwitcher.Core and JavaScriptEngineSwitcher.Jint.
- Updated
highlight.jsused inStatiq.Highlight(#269).
- Updated Markdig to 0.31.0 to fix an upstream bug when using alt text on images (#267).
- Updated Spectre.Console (#247, thanks @devlead).
- Updated JavaScriptEngineSwitcher (#246, thanks @devlead).
- Updated Microsoft.Data.SqlClient (#248, thanks @devlead).
- Updated System.Linq.Async (#249, thanks @devlead).
- Updated YamlDotNet (#263, thanks @NikoMix).
- Updated NetEscapades.Configuration.Yaml in reaction to update to YamlDotNet.
- Ensures that the
GenerateFeedsmodule always sets a feed title, even if one isn't provided. - Added a warning to
GenerateFeedsif a feed link isn't set, either through theHostsetting or otherwise.
- Added a configurator for the
IEngineManagerand a corresponding bootstrapperConfigureEngineManager()extension method to allow customizing the engine manager used in most commands just prior to it executing the engine (useful for last-minute pipeline customization and some other niche use cases).
- Improved the
HttpClient.SendWithRetryAsync()extension to log retries at the information level since they may indicate other problems, and to retry during internalHttpClienttimeouts. - Improved exception logging to the console by making sure internal cancellations and timeout exceptions are logged (previously they were silent, which could create the impression nothing went wrong).
- Fixed a bug that still resulted in file cleaning even when
CleanMode.Noneis set (I.e.--noclean). RenderMarkdownno longer escapes@characters insidemailtolinks (#254).- Added a
EscapeAtInMarkdownsetting that can control@escaping in Markdown files by theRenderMarkdownmodule on a file-by-file basis (#254).
- Fixed a bug in
ExtractFrontMatterto ensure front matter is extracted when the delimiter is on the last line of the file.
- Added a new pipeline
PostProcessHasDependenciesproperty that indicates the post-process phase of a pipeline should depend on the post-process phase(s) of the pipeline dependencies. This is helpful in certain situations where you need a pipeline to run after other post-process phases from dependencies. - Added a
GenerateRedirects.AlwaysCreateAdditionalOutput()method to allow creating additional redirect files even if no redirects are specified (I.e. if redirects are also being generated from another source). - Added additional overloads to
GenerateRedirects.WithAdditionalOutput()that can accept the execution context in the delegate and/or return aTask.
- Fixed
ElseIfwhenPredicate.RequiresDocumentis false inExecuteIfmodule (#255, #256, thanks @nils-a). - Adds the ability to configure a specific date/time as "current". All code and themes should now use
IExecutionState.GetCurrentDateTime()instead ofDateTime.Now, etc. - Removes console background color for better compatibility with different console themes (#257).
- Outputs the configured log level on execution.
- Fixed generation of document source paths for symbols in
AnalyzeCSharpto use the symbol ID and generate shorter names so very long symbols don't create paths that are too long (#244).
- Changed
Statiq.App.propstoStatiq.App.targetsto resolve some import ordering bugs. - Added a
Keys.IgnoreExternalDestinationssetting to ignore when document destinations are not relative to the output path since some use cases may require writing documents elsewhere.
- Updated the referenced version of ImageSharp in the Statiq.Images library (#242, thanks @olevett).
- Fixed some
HtmlKeyscopy-paste errors (#240, thanks @pascalberger).
- Added support for surfacing tuple information in the
AnalyzeCSharpmodule.
- Added support for regular expressions to the
ExtractFrontMattermodule (#231). - Added
IPipelineOutputs.ExceptPipelines()extension method to get outputs from all but a set of specified pipelines. IPipelineOutputs.ExceptPipeline()now returns documents in natural order likeIPipelineOutputs.FromPipeline()does.- Added
AnalyzeCSharp.IncludeEmptyNamespaces()option to control whether recursively empty namespaces are output.
- Updated Buildalyzer in
Statiq.CodeAnalysisto 4.1.0 which removes some dependencies on .NET Framework and resolves some package resolution problems.
- Added support for "raw" code fences to the
RenderMarkdownmodule that bypasses markdown processing. - Fixed a bug when instantiating a
ShortcodeResultfrom the bootstrapper due to lack of availability of an execution context (since the engine hasn't been created yet). - Added
WithNestedElements()to theGatherHeadingsmodule to control whether nested HTML element content is included in the heading text (the default is now that it is not, other than links). - Fixed a bug with certain modules double-encoding character references (statiqdev/Statiq#981).
- Added a new
StartProcessArgumentclass andWithArgument()/WithArguments()methods to theStartProcessmodule that makes it easier to define multiple arguments inside a single config delegate.
- Added
DocumentList<TDocument>.GetDestination(NormalizedPath destinationPath),.GetSource(NormalizedPath sourcePath), and.GetRelativeSource(NormalizedPath sourcePath)to better provide single document results from a document list. - Added
IPipelineOutputs.GetDestination(NormalizedPath destinationPath),.GetSource(NormalizedPath sourcePath), and.GetRelativeSource(NormalizedPath sourcePath)to better provide single document results from pipeline output collections. - Added
IDocument.Timestampthat holds a timestamp of document instantiation and is useful for ordering documents based on "most recent" semantics. - Uses the new
IDocument.Timestampproperty to order certain document results like thePipelineOutputsenumerator,PipelineOutputs.ExceptPipeline(),IEnumerable<IDocument>.FilterDestinations(), andIEnumerable<IDocument>.FilterSources()in descending creation order (in other words, document results that otherwise don't have a natural order are ordered by timestamp now) (#226). - Fixed a bug when multiple modules call
IEngine.GetJavaScriptEnginePool()for the first time concurrently. - Added
CodeAnalysisKeys.Implementsto the documents produced by theAnalyzeCSharpmodule to represent the interface member(s) being implemented by properties, events, and methods. - Added the ability to inject Sass variables via metadata by prefixing with "Sass_" which should make providing theme customizations a lot easier.
- Added a new
MarkdownExtensionsmetadata key that can add Markdown (I.e. Markdig) extension types per-document or per-execution using metadata/settings (#222). - Removed the recently added
PathCollection.RemoveDefault()method and instead allow optionally specifying whether paths that get added to aPathCollectionare removable (the default istrue). - Removed the recently added notion of "initial settings" due to being confusing and instead moved settings initialization up in the order of bootstrapper operations (this shouldn't result in a breaking change, but be on the lookout for problems).
- Added a new
RetryModulesmodule that provides simple retry behavior for it's child modules (it essentially wraps module execution with Polly). - Added a new
PathCollection.RemoveDefault()method that only removes the default paths, and used it to clear only default paths when alternate input paths are specified on the command line.
- Breaking change:
IFileSystemmust now be injected and passed toBaseCommandwhen creating custom commands that derive from it. - Breaking change:
IEngine.FileSystemis now aIReadOnlyFileSysteminstead ofIFileSystem(I.e. the file system can no longer be edited one the engine has been created). - Breaking change: The file system can no longer be configured through
Bootstrapper.ConfigureEngine()and must be done throughBootstrapper.ConfigureFileSystem()or one of the other more specific file system bootstrapper extensions likeBootstrapper.SetRootPath(). - Changed the
Statiq.RazorRazor compilers to use collectible assemblies in a custom load context for better memory usage and caching behavior. This isn't a breaking change but was somewhat risky so keep an eye out for any problems related to Razor compilation and please open issues if you notice any regressions. - Updated
MarkdiginStatiq.Markdownto 0.26.0. - Fixed a number of inconsistencies with the way the
@symbol was being escaped in Markdown documents (using\@should now work reliably, see statiqdev/Discussions#109). Enginenow accepts aIReadOnlyFileSystemas a constructor argument (a new file system will be created if one is not provided).- Added bootstrapper support for "initial" settings which are set before other parts of the bootstrapper (like the file system or services). Use these new initial settings bootstrapper extensions when you need to add a setting very early in the bootstrapper process just after reading configuration files (for most use cases the existing settings extensions continue to be preferred).
- Updated
BuildalyzerinStatiq.CodeAnalysisto 3.2.6. - Updated
Microsoft.CodeAnalysis.CSharpinStatiq.Coreto 3.11.0. - Improved diagnostic logging of compilation message in
Statiq.Razor. - Made the output ordering of the
ReadFilesmodule deterministic which will help certain caching scenarios where cache codes are generated by combining output files including order. - Added a
CacheDocuments.WithoutSourceMapping()extension to toggle a new mode for theCacheDocumentsmodule where all inputs are mapped to all outputs and the entire cache is invalidated when one input changes. - Changed dynamic Razor assemblies to use the path and file name in their assembly names instead of a random file name (#220).
- Added a warning when a Razor partial or view uses a
@modeldirective that could be overridden by a@inheritsdirective in an import.
- Made it easier to override certain interfaces used by the engine by registering alternate implementations in the service collection passed to the engine. Alternate implementations of the following can now be provided:
IApplicationState,IMemoryStreamFactory,ILinkGenerator,INamespacesCollection,IScriptHelper,IDocumentFactory, andIFileCleaner. In addition, the default implementations of these interfaces have been refactored to make deriving from them easier (I.e. marked interface members asvirtual). - Refactored the default
LinkGeneratorto use strings instead ofNormalizedPathwhich could result in poor results in some edge cases like trailing slashes (#218). - Added toggle for keeping trailing slash when hiding a page in
LinkGeneratorand related extensions, also exposed via a newKeys.LinkHiddenPageTrailingSlashsetting (#218). - Updated Spectre.Console reference in Statiq.App to 0.43.0.
- Fixed a bug with backwards compatability of the
HtmlKeysfile not being in the original namespace (#973).
- Breaking change: Removed
Statiq.Htmlextension and moved all functionality into eitherStatiq.Common(helpers and utilities) orStatiq.Core(modules). All modules are still available throughStatiq.Coreand you should remove references toStatiq.Html. - Added a reference to
AngleSharpinStatiq.Common. - Added all keys from
HtmlKeystoKeysinStatiq.Commonbut keptHtmlKeysand marked it obsolete for backwards-compatibility. - Changed the behavior of HTML parsing and formatting (I.e. both reading and writing) to preserve any originally encoded character references (#213).
- Added a new
IExecutionContext.GetContentProvider()extension that accepts an AngleSharpIMarkupFormattable(such asIHtmlDocument). - Added
WithAutoHighlightUnspecifiedLanguage()to theHighlightCodemodule to avoid time-consuming generation-time code highlighting when the language is unknown (#210, thanks @Turnerj). - Changed the
HighlightShortcodemodule to add a<pre>element when there are new lines in the content or when specified using a newAddPreshortcode argument (#215).
- Breaking change: The
LinkGeneratorclass is no longer static and now needs to be accessed through a newIExecutionState.LinkGeneratororIExecutionContext.LinkGeneratorproperty. - Added the
cachedirectory to the excluded list inStatiq.App.props. - Fixed a bug with
DocumentFileProviderand documents with a nullDestination. - Fixed a bug in the Razor engine when run under .NET 6 RC runtimes (#204, thanks @phil-scott-78).
- Updated several dependencies (#199, #201, #202, thanks @devlead).
- Added the ability to cache Razor partials using new
CachedPartial()andCachedPartialAsync()HTML helpers. (#205)
- Added
GenerateLunrIndex.WithClientNamemethod to allow setting the name of the client object in the generated JavaScript file. - Fixed a bug in
GenerateLunrIndexwhen no documents contain a given search field. - Added
GenerateLunrIndex.WithStemmingmethods to control stemming behavior and changed default to no stemming. - Added support for typeahead style searching to the generated client JavaScript search file by default (I.e. automatically adds trailing wildcards).
- Breaking change: Renamed the erroneous
Statiq.SearchIndexnamespace in theStatiq.Lunrpackage toStatiq.Lunr. - Breaking change: Completely rewrote the
GenerateLunrIndexmodule to build and output a search index at generation time and add a bunch of new features (#192). - Fixed a bug with the reflected namespace collection when dealing with objects in the global namespace (#191).
- Fixed a bug when getting outputs from a valid pipeline that didn't produce any (it now returns an empty collection instead of throwing and exception) (#172).
- Fixed a bug in the
GenerateSiteMapmodule when using theLinkRootsetting that included the link root twice (#158, #193, thanks @kkato233). - Added support for named strongly-typed pipelines (#173).
- Fixed a bug in
MirrorResourcesto prevent it from mirroring links with "rel" values that don't specify artifacts (#190). - Fixed a bug in
MirrorResourcesto prevent it from mirroring resources from the current host whenHostis specified (#190). - Added a
ReadExcelmodule to Statiq.Tables that can read an Excel file into metadata as aIReadOnlyList<IReadOnlyList<string>>. - Added a
ReadCsvmodule to Statiq.Tables that can read a CSV file into metadata as aIReadOnlyList<IReadOnlyList<string>>.
- Fixed several bugs related to caching in the
CopyFilesmodule (#189).
- Breaking change: Fixed a bug with Razor layouts and partials and explicit model types. Previously all layouts and partials were assuming
the model type was an
IDocument. This meant that extension methods and otherIDocumentoriented functionality worked in a layout or partial when using the@Modelproperty to access the document, but it also meant they didn't work for alternate models. Layouts and partials are supposed to generally handle all model types (since different views can call them), so now the model isdynamicfor layouts and partials unless explicitly specified. This has the side-effect of making some@Modelaccess likeIDocumentextension methods that used to work fail. If you see "does not contain a definition" error messages in Razor compilation, try changing@Modelproperty access to@Documentin your layouts and partials, or using an explicit@modeldirective at the top of the layout pr partial file to explicitly specify the model type for that layout or partial. - Fixed a bug when changing the
CleanModesetting via the bootstrapper. - Improved compilation failure exception messages for Razor layouts and partials.
- Fixed a bug with using statements not being added to Razor layouts and partials (#953).
- Breaking change: Deleted
IFile.GetCacheHashCodeAsync()and replaced it with an implementation ofICacheCode. - Breaking change: Renamed
IContentProvider.GetCacheHashCodeAsync()and replaced it with an implementation ofICacheCode. - Breaking change: Renamed
IDocument.GetCacheHashCodeAsync()and replaced it with an implementation ofICacheCode. - Added a new "cache" folder that contains caching artifacts to improve performance, deleting it won't harm anything but it should be left if possible to improve initial generation performance. Also note that the "cache" folder likely shouldn't be committed to a repository, though it's designed to support that scenario when warranted (I.e. relative paths, etc.).
- Compiled Razor assemblies (including layouts and partials) are now cached to disk which dramatically improved initial generation performance by not recompiling files that haven't changed.
- Added
IFile.ReadAllBytesAsync()andIFile.WriteAllBytesAsync(). - Added
IFile.WriteFromAsync(),IFile.AppendFromAsync(), andIFile.CopyToAsync()extension methods to more easily copy a file from/to a stream. - Added
IReadOnlyFileSystem.CachePathand related extensions, methods, etc. to provide a path where cache files should be stored and set to "cache" by default (which should be excluded in.gitignore). - The write tracking data is now cached in a file so if the output folder has not changed and the content is the same, files don't need to be written even on the first execution.
- Added an
ICacheCodeinterface to provide a standard deterministic.GetCacheCodeAsync()method and implemented it inIDocument,IContentProvider, andIFile. - Changed the console output encoding and the
ProcessLauncherchild process console encodings to UTF-8 so emoji and other Unicode characters will render correctly from child processes. - Fixed a bug with the
--helpCLI option and command description escaping (#186). - Added ability to set the temp and cache paths via the CLI.
- Added support for the
PATHandPATHEXTenvironment variables to theProcessLauncherso it can resolve file names more likecmd.exe. - Added better error messages when process launching fails.
- Added
CleanMode.Unwrittenthat will wait to clean the output folder after each execution and tries to avoid writing duplicate files to the file system (this is the new default). - Added
IFile.GetCacheHashCodeAsync()which can be used to get a hash code representing the current state of a file. - Refactored
FileContent.GetCacheHashCodeAsync()to use the newIFile.GetCacheHashCodeAsync()instead of attempting to read the entire file content.
- Several optimizations to file IO and the
WriteFilesandCopyFilesmodules.
- Fixed a bug with link generation for non http/https links in Markdown (#179, #184, thanks @JoshClose).
- Fixed a bug with the
ConsoleListeneron MacOS that prevented signaling from the main thread (used for thepreviewcommand in Statiq Web) (#182, #183, thanks @devlead). - Fixed a bug with the CLI
--helpoutput that caused the app to crash (#180, #181, thanks @matkoch). - Added caching for
IEnumerable<TDocument>.GetDestinationTree()andIEnumerable<TDocument>.GetSourceTree()which results in a significant performance improvement in some cases for large sites. - Improved logging messages related to timing.
- Added
IFileextensions to serialize and deserialize JSON. - Added
IFileextensions to serialize and deserialize YAML. - Added
NormalizedPath.ThrowIfRealtive()andNormalizedPath.ThrowIfAbsolute()helper methods. - Added a
IDirectory.MoveTo()method. - Fixed a bug that caused an input phase overload of an
ExecutionPipelinenot to execute.
- Fixed a bug when both a debugger was attached and the log level was set to debug by removing the
DebugLogger(#176). - Added a
RedirectTometadata value to documents output fromGenerateRedirects. - Fixed a regression with the
DocumentLink()HTML helper in Razor (#177).
- Updated Buildalyzer to the most recent version and resolves Roslyn version incompatibilities in the
AnalyzeCSharpmodule (#174, thanks @mholo65). - Added an optional
makeAbsoluteparameter toLinkGenerator.GetLink()that allows keeping links as relative (#170). - Fixed fragment support in the Markdown link rewriter (#170, #175, thanks @JoshClose).
- Fixed
LinkGeneratorbehavior when using query and/or fragment components (#170). - Added
makeAbsoluteparameters toIExecutionState.GetLink()extension methods and others as appropriate (#170).
- Removed the
UrlResolutionTagHelperfrom Razor processing so that~/links don't get processed (#170). - Added support for
~/link resolution to Markdown files, note that this is an interim feature and will be removed again in favor of a new module that handles~/links for all template engines soon (#170, #171, thanks @JoshClose).
- Added better error logging of Razor rendering failures.
- Changed the default Razor model type to
IDocumentfromdynamicif no explicit model or base type is specified.
- Added ability to "map" input folders to subfolders in the virtual folder hierarchy (so not every input folder has to be at the root now).
- Added the
GenerateJsonmodule back in (it got dropped a while ago when Statiq.Json was merged with Statiq.Core). - Added a utility
LoggerFactoryLoggerWrapperclass that can wrap the context (or any otherILogger) and provide it as anILoggerFactorythat always logs to the underlying logger. - Fixed a bug with the generated doctype element in redirects (#160, #161, thanks @gep13).
- Fixed a bug with virtual input directories when getting a parent directory from a file produced by one (it wasn't getting the original virtual directory).
- Breaking change: Refactored the
IExecutionContext.GetContentProviderAsync(string)extension (and overloads) to be non-async and unified related extensions that get content providers. - Breaking change: Refactored
IDocument.CloseAsync(string)and related extensions to be non-async and unified related clone methods into a single set of overloads. - Breaking change: Removed the
UseStringContentFilesoption because it's no longer relevant with the new string and stream processing. - Updated the Razor engine from 3.0.0 to 3.1.10.
- Updated the Roslyn libraries from 3.4.0 to 3.8.0.
- Changed the precedence of environment variables to overwrite configuration from settings files to match expected ASP.NET Core conventions (#154).
- Fixed some bugs with the
ProcessLauncheron Linux and Mac by ensuring the entire process tree is killed (#156). - Added some performance caching for
IExecutionProcess.OutputPages. - Refactored
NormalizedPathto reduce use of strings. - Added some performance enhancements to caching of AngleSharp HTML documents.
- Added some additional retry policies to file operations to avoid file lock exceptions under certain conditions (#151).
- Added ability to customize the body of meta-refresh redirect HTML files using the
RedirectBodykey (#153). - Added
.fhtmlas a media type to mean HTML fragments (needed so that we can treat full HTML and HTML fragments differently when applying layouts in Statiq Web).
- Added a new
CleanModeenumeration and corresponding setting to control which output files are cleaned on execution (#152). - Added a
--clean-modecommand-line option to control the cleaning mode. - Changed the default cleaning behavior to
CleanMode.Selfwhich only cleans files written during execution and not those written by external processes, for example. - Added the
IServiceProviderto thePipelineBuilderso services are available when building pipelines (#150). - Added new
IReadOnlyFileSystem.GetRootPath()extensions. - Added
ProcessLauncher.WaitForRunningProcesses()that allows waiting until all running processes have exited. - Added a
IBootstrapper.Commandproperty that can get the command that was run (provided it inherits fromBaseCommand<TSettings>).
- Added a new
interactivecommand that provides a REPL (read-eval-print prompt) after execution, useful for inspecting the state of the engine and debugging the generation.
- Added a
.PreserveFrontMatter()configuration method to theExtractFrontMattermodule that preserves the front matter content. - Fixed a bug with gathered headings where HTML was included in the heading text (#142).
- Added support for specifying
ViewDatain theRenderRazormodule (#145, #146, thanks @alanta). - Added a new
BeforeDeploymentevent that gets raised before any deployment pipelines are run (or at the end of execution if there are no deployment pipelines). - Added a new
ProcessLauncherutility class toStatiq.Commonthat does what theStartProcessmodule does, but in a way that can be used outside of the module since it's such a general use case.
- Fixed a bug with deployment pipelines getting document outputs from non-deployment pipelines.
- Fixed a bug where deployment pipeline input phases were starting with outputs from non-deployment pipelines (input phases should always start empty).
- Improved exception logging when in a module to include pipeline, phase, and module name.
- Fixed an unnecessary pipeline dependency check for deployment pipelines that prevented setting up dependency chains involving deployment pipelines and only dependent non-deployment pipelines.
- Breaking change: Removed the
Statiq.Html.ValidateLinksmodule in favor of analyzers in Statiq Web (which have already been improved beyond the module). If you still need access to this module directly, copy the code from a previous version into your own project and reference theStatiq.Htmlpackage and it should continue to work. - Updated ImageSharp in
Statiq.Imagesto stable version 1.0.1 (thanks @JimBobSquarePants, #138). - Improved logging, all error and warning messages are now output on Azure Pipelines and GitHub Actions as checks.
- Added
StartProcess.LogErrors()to configure whether standard error output is logged as debug or error messages. - Added
IContentProvider.GetCacheHashCodeAsync()to get and cache a hash code for a given content provider. - Updated AngleSharp to 0.14.0 (#135, #136, thanks @alanta).
- Added
RenderMarkdown.WithMarkdownDocumentKey(string markdownDocumentKey)to indicate where theMarkdownDocumentshould be saved, or not at all. - Removed
DocumentAnalyzerandSyncDocumentAnalyzerin favor of combining into alternate overloads inAnalyzerandSyncAnalyzersimilar to howModulehandles it (this lets analyzers provide functionality before documents are processed individually). - Renamed
IInitializertoIBootstrapperInitializer. - Added
IEngineInitializerwhich will be instantiated and called when an engine first starts up (for example, lets you hook engine events from extensions). - Moved engine event classes like
BeforeEngineExecutiontoStatiq.Commonso they can be subscribed by extensions using aIEngineInitializer. - Removed documents from the
IAnalyzermethods, addedIExecutionContextas a base interface forIAnalyzerContext, and analyzer documents now passed asIAnalyzerContext.Inputssimilar to modules. - Added
IAnalyzer.BeforeEngineExecutionAsync(IEngine engine, Guid executionId)to get called one-per-instance for each analyzer prior to each engine execution (for resetting caches, etc.). - Changed analyzer pipeline and phase specification to be a collection of
KeyValuePair<string, Phase>instead of distinct pipeline and phase arrays. - Changed deployment pipelines so that none of their phases are executed until all phases of non-deployment pipelines are completed (I.e. deployment pipelines now don't start executing until all non-deployment pipelines are done).
- Non-deployment pipelines can no longer have a dependency on deployment pipelines (this didn't really make sense before, but now it's enforced).
- Removed a debugging break statement that snuck into the last release.
- Fixed a bug with the
ValidateLinksmodule when using a<base>element on the page. - Added
IExecutionState.LogBuildServerWarning()andIExecutionState.LogBuildServerError()extensions to log messages to the console in a format build servers can recognize for build checks (GitHub Actions and Azure Pipelines). - Fixed bugs with relative link validation (#128, #134, thanks @mholo65).
- Added a
StartProcess.HideArguments()method to hide arguments when logging process commands. - Fixed several bugs related to cancellation and error codes.
- Fixed a bug with
NormalizedPath.GetTitle()when the file name contains multiple extensions (#130, #131, thanks @devlead). - Added support for analyzers (#104).
- Added
Analyzer,SyncAnalyzer,DocumentAnalyzer, andSyncDocumentAnalyzerbase analyzer classes (#104). - Added
Bootstrapper.Analyze()andBootstrapper.AnalyzeDocument()for defining delegate-based analyzers (#104). - Fixed a bug in the console logger when logging with
LogLevel.None. - Added a
--failure-log-level <LEVEL>CLI command to fail generation and return a non-zero exit code if any log messages exceed the provided threshold (I.e.--failure-log-level Warning) (#101). - Added a
Bootstrapper.SetFailureLogLevel()extension to set the failure log level from code (#101). - The
RenderMarkdownmodule now addsMarkdownDocumentmetadata that contains the MarkdigMarkdownDocumentcreated during processing. - Added Scriban (Liquid) support via new
RenderScribanmodule (#120, thanks @mholo65). - Added
ExecuteDestinationsandExecuteSourcesmodules to filter documents by destination or source and then execute modules on the filtered documents.
- Added some optimizations for async file I/O.
- Added overloads to
FilterSourcesandFilterDestinationsmodules that acceptConfig<IEnumerable<string>>for the patterns. - Fixed
IDirectory.GetFiles()andIDirectory.GetDirectories()to make sure excluded paths are excluded from the results. - Creating a
ReadFilesmodule without any patterns now returns all files. - Added
ExtractFrontMatter.RequireStartDelimiter()to require the front matter to start with a specified delimiter on the first line (for example,/*as the opening of a comment block). - Added
IMetadata.ToJson()utility extensions to serialize anIMetadataobject to JSON. - Fixed a bug where the
EvaluateScriptmodule would reset the document media type for content return values. - Added a new
glob evalcommand to evaluate a globbing pattern against a specified directory and report all the matches. - Added a new
glob testcommand to test a specified path against a globbing pattern to see if it matches. - Removes subresource attributes in
MirrorResource(#127). - Updated Spectre.Cli CLI library for better console help messages.
- Added a new
ReadApimodule for generally reading from an API client (#126, thanks @unchase). - Added
IBootstrapper.ModifyPipeline()to make it easier to modify an existing pipeline via the bootstrapper. - Added collection initializer and list support to the
ExecuteBranchmodule.
- Breaking change: Removed the
IDocument.GetParent(),IDocument.HasChildren(),IDocument.GetDescendants(), andIDocument.GetDescendantsAndSelf()extension methods (IDocument.GetChildren()still remains since it's fetching actual metadata values). Instead, the appropriate tree concept can now be accessed via an implementation of theIDocumentTree<TDocument>interface. This change may break navigation, soOutputsorOutputPagesshould be considered for generating navigation instead. - Added an
OutputPagesproperty to the engine and execution context to make it easier to filter outputs by "pages" (by default, documents with a destination path ending in ".htm" or ".html"). This is what you should use to generate navigation going forward. - Added
Outputs.Get()andOutputPages.Get()to support getting a single document from those collections by destination path, which is faster than globbing. - Added a
IDocumentTree<TDocument>interface to encapsulate different kinds of document tree traversal logic. - Added a
DocumentMetadataTree<TDocument>implementation to represent document trees as the result of metadata containing child documents. - Added a
DocumentPathTree<TDocument>implementation to represent document trees as the result of file paths. - Added a
IEnumerable<TDocument>.AsMetadataTree()extension method to get aDocumentMetadataTree<TDocument>instance that creates a tree from document metadata containing child documents. - Added a
IEnumerable<TDocument>.AsDestinationTree()extension method to get aDocumentPathTree<TDocument>instance that creates a tree from document destination paths. - Added a
IEnumerable<TDocument>.AsSourceTree()extension method to get aDocumentPathTree<TDocument>instance that creates a tree from document source paths. - Added a new
FilteredDocumentList<TDocument>return type forIEnumerable<TDocument>.FilterDestinations()andIEnumerable<TDocument>.FilterSources()calls (includingOutputs[string[] patterns]) which implements the newIDocumentTree<TDocument>and lets you treat the resulting filtered documents as a tree from the filter return. - Added the
IDocumentTree<TDocument>interface toIPipelineOutputswith default implementations that operate on document destination paths. This means you can call methods likeOutputs.GetChildren(doc)to get all the children across all pipelines of the given document, etc. - Added a new
IndexFileNamesetting to control the default file name of index files (defaults toindex.html). - Added a new
PageFileExtensionssetting to control the default file extensions of "pages" for things likeOutputPagesfiltering and link generation (defaults to ".html" and ".htm"). - Added a new constructor to the
SetDestinationmodule that will change the destination of documents to the first value of thePageFileExtensionssetting (default of ".html"). - Added a new
MinimumStatiqFrameworkVersionkey to perform a check for the minimum allowed version of Statiq Framework. If this is set to something higher than the current version of Statiq Framework, an error will be logged and execution will stop. Any setting that starts will this key will be considered, so it's recommended the use of this key be suffixed with a unique identifier to avoid conflicts between components (for exampleMinimumStatiqFrameworkVersion-MySite). - Refactored settings and configuration implementations. You shouldn't notice anything usage-wise, but keep an eye out for anything that doesn't work as expected
- Lots of under-the-hood refactoring to make things faster.
- Fix for invalid URIs in the
ValidateLinksmodule (#119).
- Breaking change: Changed the IPipelineOutputs
indexer to filter documents by destination path from all pipelines instead of get documents from a specified pipeline. To use the previous behavior, callIPipelineOutputs.FromPipeline(string). This will make the more common case (finding a document or documents among all pipelines) easier. To refactor your code to match the old behavior, do a string search for "Outputs[" and replace withOutputs.FromPipeline()`. - Breaking change: Changed the
DocumentList<TDocument>indexer to return all matching documents instead of the first matching document. To refactor your code to match the old behavior add a.FirstOrDefault()after the call to the indexer. - Breaking change: Removed the
CompileScriptmodule in favor of global script caching (so using theEvaluateScriptmodule will also cache the script compilation, removing the need for a separate cached assembly). - Breaking change: Removed all but a single string-based evaluation method from
IScriptHelperto promote global script compilation caching. - Breaking change: Removed global metadata properties from scripted documents, metadata, and shortcodes due to performance penalty and inability to cache across documents.
Uses of global properties that refer to other metadata will have to be replaced with
Get()variants. For example, a scripted metadata value=> Fooshould become=> Get("Foo"). - Breaking change: Renamed the
AbsolutizeLinksmodule toMakeLinksAbsolutefor clarity and to match with the newMakeLinksRootRelativemodule. - Added a new
MakeLinksRootRelativemodule. - Added a
IEnumerable<IDocument>.ContainsById(IDocument)extension method to determine if a sequence contains an equivalent document by ID. - Added a new
ConcurrentCache<TKey, TValue>helper class that usesLazy<T>, which improves performance of internals by avoiding duplicate value factory evaluation. - Script compilations are now globally cached, dramatically improving performance of scripted documents, metadata, and shortcodes.
- Fixed some bugs with the
CacheDocumentsmodule and document hash code generation. - Added a
IComparer<T>.ToConvertingComparer()extension method that converts a typed comparer into aIComparer<object>that performs type conversions. - Added a
IEqualityComparer<T>.ToConvertingComparer()extension method that converts a typed comparer into aIComparer<object>that performs type conversions. - Added a
RemoveTreePlaceholdersmodule to remove tree placeholder documents without flattening. - The
MergeMetadataandMergeDocumentsmodules no longer merge settings (since they're inherited by the document regardless). - Added
IMetadata.WithoutSettings()to return filtered metadata without any settings values. - Added the key being requested to
IMetadataValue.Get()so that metadata values can use it if needed. - Added recursive metadata expansion detection of
IMetadataValuemetadata values (it will now throw an error so you know which key is recursively expanding). - Added a
RenderSectionOrPartial(string sectionName, string partialName)helper to the base Razor page. - Added feed metadata to the output documents from
GenerateFeeds. - Added a new
AddRtlSupportmodule inStatiq.Htmlthat automatically adds RTL attributes to HTML elements (#113, #15, thanks @encrypt0r). - Added a
IEnumerable<IDocument>.RemoveTreePlaceholders()extension method. - Added an option to remove tree placeholder documents in the
FlattenTreemodule and theIEnumerable<IDocument>.Flatten()extension methods. - Added
settingsas a default settings file name (with support for JSON, YAML, or XML formats). - Added support for
appsettingsandstatiqYAML (.ymland.yaml) and XML (.xml) configuration files. - Added containing types to the symbol ID for nested symbols in the
AnalyzeCSharpmodule (#116). - Added a message about using a higher log level when an error occurs (#115).
- Fixed a bug on engine reruns (I.e. the Statiq.Web preview command).
- Made
RenderRazor.WithLayout()take precedence over an available_ViewStart.cshtmlfile (by ignoring the_ViewStart.cshtmlfile entirely which previously took precedence in this case). - Fixed some bugs with input-relative path finding for Razor layouts and partials (#102).
- Added
NormalizedPath.ContainsDescendantOrSelf(). - Added
NormalizedPath.ContainsChildOrSelf(). - Fixed several bugs with the implementation of
NormalizedPath.GetRelativeOutputPath(). - Added a
IReadOnlyFileSystem.GetRelativeOutputPath()extension. - Added a
IReadOnlyFileSystem.GetRelativeInputPath()extension. - Added
IFileSystem.ExcludedPathsto indicate input paths that should be excluded from processing. - Added
.GetInstance(Type)and.GetInstance<TType>()methods to theClassCatalog. - Fixed a bug where custom commands were being added twice (#103).
- Fixed a bug in the
GenerateRedirectsmodule for original files ending in.htm(#105). - Updated
Spectre.Clito version 0.35.0 with better internal command registration (#110, thanks @patriksvensson). - Removed restriction on only using
IDocumentmodels in Razor (#108, #23, thanks @alanta).
- Added the new
Statiq.App.propsfile to abuildTransitivefolder in the package so it flows transitively to consumers.
- Fixed a bug with async context-based
Configdelegates not indicating that they don't require a document. - Added a
IReadOnlyPipelineCollection IExecutionState.ExecutingPipelinesproperty that provides the currently executing pipelines. - Added a new
ThrowExceptionIfmodule that throws an exception if a condition is true. - Added a
Config<bool>.IsFalse()extension method. - Added a
Config.ContainsAnySettings()extension method. - Added
IReadOnlyDictionary<K, V>.ContainsAnyKeys()extension methods. - Fixed a bug regarding disposal of a content stream in the
StartProcessmodule. - Fixed a bug that required feed items to have URI IDs when the specification indicates they can also be arbitrary strings.
- Added a props file to the Statiq.App package to automatically set the default output exclusion and input content MSBuild props.
- Fixed a bug with the
OrderDocumentsmodule sorting by string value for default keys. - Changed
GatherHeadingsto take aConfig<int>for specifying the level.
- Removed the
StreamContentcontent provider in favor of the newMemoryContentcontent provider (should also provide a nice performance boost since there's no more stream locking). - Added
IExecutionContext.GetContentProvider()extensions that take abyte[]buffer. - Added new
MemoryContentcontent provider that wraps abyte[]buffer. - Changed
IEngine.Settingsto be mutable, settings can now be added directly to the engine after instantiation. - Fixed a bug with case-insensitive settings from the command line.
- Fixed a bug with computed metadata settings from the command line.
- Added document flattening by default when using the
DocumentFileProvider. - Added document flattening by default when using
IEnumerable<TDocument>.FilterSources()andIEnumerable<TDocument>.FilterDestinations()extensions. - Added a
IReadOnlyDictionary<TKey, TValue>.ContainsKeys()extension utility method. - Added multiple key test to the
ExecuteIfmodule.
- Fixed the
ProcessSidecarFilemodule to pass the media type to child modules. - Added
IBootstrapper.RunTestAsync()extensions to assist with testing entire bootstrappers. - Added
AsDependencyOf()methods toPipelineBuilder. - Added a collection initializer to
TestFileProviderto make adding test files easier. - Added full
NormalizedPathsupport toTestFileProviderinternals.
- Better engine and pipeline exception handling and log messages.
- Added a new
--debugCLI flag to launch a debugger and attach it.
- Fix not to reuse a
HttpRequestduring retry, changed theHttpClient.SendWithRetryAsync()and related methods to take a factory instead of a single request (#98). - Fix for a
PipelineBuilderwith no actions to return an empty pipeline. - Added
IBootstrapper.AddDeploymentPipeline()overloads.
- Added
IReadOnlyDictionary<string, Type>implementation toClassCatalog. - Optimized
ScriptMetadataValuemetadata caching for big performance gains in certain scenarios. - Ensures that document metadata can't override the properties from
IDocument(Id,Source,Destination, andContentProvider). - Removed the
ApplyDirectoryMetadatamodule in favor of a more specific/powerful capability in Statiq Web (it never really made sense in Framework anyway). - Fixed default
GenerateSitemapdocument destination to "sitemap.xml".
- Added a
IDocument.GetParent()overload that uses the current execution context and doesn't require passing in a set of candidate documents. - The
GenerateFeedsmodule now replaces relative links in item descriptions and content. - Added a new
AbsolutizeLinksmodule toStatiq.Htmlto turn all links in a document to absolute.
- Refactored the
ValidateLinksmodule to acceptConfig<bool>settings. - Changed shortcode semantics to only pass new metadata down (metadata is no longer merged up to host document, even though no existing shortcodes did that anyway).
- Refactored shortcodes to return a new
ShortcodeResultobject that includes content and nested metadata. - Consolidated shortcode base types to only return variations of
ShortcodeResult(instead ofStreamandstringversions as well). - Added the
ILoggerinterface toIDocumentalong with default implementations to support easier document logging with a document prefix (usually the source path).
- Added a
Markdownshortcode to render Markdown content anywhere (for example, in another templating language like Razor).
- Added Handlebars media types.
- Added
WithInputDocument()to theEnumerateValuesmodule to include the original input document in the enumeration. - Fixed some edge-case bugs in
LazyDocumentMetadataValue. - Added
<?#^ ... /?>as special syntax for theIncludeshortcode with the "^" character. - Added support for HTTP/HTTPS schemes to the
Includeshortcode for including web content. - Added
HttpClient.SendWithRetryAsync()extension methods to send an HTTP request with a retry policy when aHttpClientis available. - Added
IExecutionState.SendHttpRequestWithRetryAsync()methods to send an HTTP request with a retry policy without needing anHttpClient. - Removed the
ProcessIncludesmodule in favor of theIncludeshortcode.
- The
OrderDocumentsmodule will now attempt to convert incompatible values. - Improved document path error messages to include path.
- Added support to
IDocument.ToDocument()extensions to return or clone the original object if it's anIDocument.
- Changed the
GenerateFeedsmodule to order by descending publish date to meet feed conventions and adds aGenerateFeeds.PreserveOrdering(bool)method to revert to old behavior (#92). - Fixed a bug with the
OptimizeFileNamestripping the path when optimizing the destination file name (#93). - Added support for casting the dynamic object returned from
IDocument.AsDynamic()back to anIDocument. - Added a new
IReadOnlyPipelineCollectionobject and exposed it viaIExecutionState.Pipelinesto provide the current set of read-only pipelines during execution. - Added
IPipeline.GetAllDependencies()extension methods to get the full set ofIPipeline.DependencyOfandIPipeline.Dependenciesfor a given pipeline. - Added
IPipeline.DependencyOfto allow specifying which pipelines a given pipeline is a dependency of (the reverse ofIPipeline.Dependencies). - Tweaked the way
NormalizedPath.OptimizeFileName()handles dashes (it no longer removes them and does a better job of collapsing them). - Fixed
object.ToDocument()andobject.ToDocuments()extensions to construct theObjectDocument<T>from the actual type of the object. - Added
IDocument.AsDynamic()(moved from theRenderHandlebarsmodule, thanks @mholo65).
- Added Statiq.Handlebars and a
RenderHandlebarsmodule (#67, #90, thanks @mholo65). - Refactored the
OptimizeFileNamemodule and added some extra configuration methods. - Added
NormalizedPath.OptimizeFileName()as both an instance method and static helper to clean up and optimize file names for the web. - Moved
ForEachDocumentandForAllDocumentsmodules to Statiq.Common so they can be used as base module classes for extensions. - Fixed a bug with the
SetDestinationmodule when a string-based path is used that starts with a "." but isn't an extension. - Fixed an unusual edge-case bug when evaluating scripts with assemblies that have the same simple name (I.e. LINQPad queries).
- Added
IHtmlHelper.DocumentLink()HTML helper extensions to Statiq.Razor. - Removed "theme" from the set of default input paths (added by default only in Statiq Web).
- Changed
CommandUtilitiesin Statiq.App public. - Moved the serve command to Statiq Web.
- Moved the preview command to Statiq Web.
- Moved Statiq.Hosting to Statiq Web as Statiq.Web.Hosting.
- Moved Statiq.Aws to Statiq Web as Statiq.Web.Aws.
- Moved Statiq.Azure to Statiq Web as Statiq.Web.Azure.
- Moved Statiq.Netlify to Statiq Web as Statiq.Web.Netlify.
- Moved Statiq.GitHub to Statiq Web as Statiq.Web.GitHub.
- Moved
ActionFileSystemWatcherto Statiq.Common and made it public. - Moved
InterlockedBoolto Statiq.Common and made it public. - Added
ShortcodeHelperstatic class to Statiq.Common and moved shortcode argument parsing helper method there. - Moved HTML-based shortcodes to Statiq.Web.
- Removed the need to pass
IExecutionContextto a bunch of different extension methods that can rely onIExecutionContext.Current. - Added
IExecutionContext.HasCurrentto check if a current execution context is available. - Changed
IExecutionContext.Currentto throw if no execution context is available. - Added
IDocumentextensions to clone documents from string orStreamcontent. - Added
IExecutionContextextensions to create documents from string orStreamcontent. - Added
DocumentShortcodeandSyncDocumentShortcodeas base classes for single document-based shortcodes. - Added
ContentShortcodeandSyncContentShortcodeas base classes for simple string-based shortcodes. - Renamed
IMetadata.GetDocumentList()toIMetadata.GetDocuments()and added a newIMetadata.GetDocumentList()that returns aDocumentList<IDocument>. - Changed
IPipelineOutputsandIEnumerable<IDocument>extensions to returnDocumentList<TDocument>. - Added
DocumentList<TDocument>which wraps a set of documents, eliminating nulls, and provides an indexer for filtering destinations. - Added
IEnumerable<IDocument>.FirstOrDefaultSource()andIEnumerable<IDocument>.FirstOrDefaultDestination()extensions.
- Moved a bunch of
IBootstrapperextensions to Statiq.Common so they're available from extension libraries in anIInitializer. - Renamed
IConfigurableBootstrappertoIBootstrapper. - Added a new
IInitializerinterface that can be used for library/module initialization (but only when using theBootstrapper). - Refactored the
RenderRazormodule to use the built-in service collection when possible. - Added a new
IServiceCollection.AddRazor()extension to register Razor services out-of-band. - Refactored the
ClassCatalogtoStatiq.Commonand exposed it via theIExecutionStateinterface. - Added
.WithSource()to thePaginateDocumentsandGroupDocumentsmodules. - Added a new
Keys.Orderkey and made theOrderDocumentsmodule support it. - Added a
keepExistingparameter to theGenerateExcerptmodule. - Removed some ambiguous
IShortcodeColletion.Add()extensions. - Added a bunch of
Bootstrapper.AddShortcode()extensions. - Added a new
ForAllDocumentsmodule that can act as a parent module to arbitrary child modules. - Added a new
Ifshortcode (#789). - Added a new
ForEachshortcode (#789). - Added a
TypeHelper.TryConvert()method that takes a targetType. - Added support for "script strings" to metadata get extensions (if the key starts with "=>" it will be treated as a script and evaluated instead of getting the metadata value directly).
- Refactored
IShortcodeto return multiple shortcode result documents and concatenates their content. - Modified
CreateTreesort delegate to include theIExecutionContextand to sort by input document order by default (instead of path/file name). - Added a
IDocument.IdEquals()extension method. - Added a
IDocument.GetLink()extension method that callsIExecutionContext.GetLink(). - Added a
IDocument.HasChildren()extension method. - Added an empty constructor to
OrderDocumentsthat orders documents by theKeys.Indexvalue and then the file name by default. - Added a
IConfig.Cast<TValue>()convenience extension method.
- Added
ctxanddocshorthand properties to the scripted metadata script host. - Ensured that scripted metadata uses a strongly-typed property in the script host for metadata properties like
SourceandDestination. - Added ".yml" to file extensions mapped to the "text/yaml" media type.
- Added ability to include all inputs in generated feeds from
GenerateFeedsby setting maximum items to 0 - Refactored Statiq.Hosting usage of Newtonsoft.Json to System.Text.Json.
- Moved the
ParseJsonmodule into Statiq.Core, refactored it to use System.Text.Json, and removed theStatiq.Jsonextension library. - Renamed
IMetadata.GetNestedMetadata()toIMetadata.GetMetadata(). - Added
TypeHelper.RegisterTypeConverter()methods to register type converters at runtime. - Added a type converter that can convert
IMetadatatoIDocument.
- Added support to
MergeDocumentsandMergeMetadatafor keeping existing metadata when merging. - Added a new
MergeContentmodule that merges content from child modules to input documents. - Added an overload to the
SetContentmodule that accepts a fullIContentProvider. - Fixed a small bug with
MetadataDictionaryinitialization when items contentIMetadataValueorConfig<T>values. - Added several new document metadata outputs to the
Paginatemodule includePreviousandNext. - Added a new
LazyDocumentMetadataValuethat can be used to lazily find a given document as a metadata value (I.e. after cloning). - Renamed the "Transform" phase to "PostProcess" to better reflect the intended semantics and make it easier to explain.
- Added a phase timeline graphic to the execution summary output.
- Added some
Span<char>.Replace()extension methods. - Added
NormalizedPath.ReplaceInvalidFileNameChars()andNormalizedPath.ReplaceInvalidPathChars()static methods. - Added
IMetadata.GetRawEnumerable()and anIMetadata.GetRawEnumerable()extension method to make enumerating raw key-value pairs easier. - Added a new
ExecuteBranchmodule that can execute multiple branches of modules. - Added config overrides to the modules that operate on document sets.
- Fixes a bug with
MirrorResourcesand files that contain "index" in their name. - Combines
FilePathandDirectoryPathinto a single consolidated `NormalizedPath (#79). - Fixes a race condition in
Process.WaitForExit(int)calls (thanks @duncanawoods).
- Added support for object-based settings to the bootstrapper (as opposed to just initial string-based configuration).
- Added support for
IConfigmetadata values. - Added
LastWriteTimeandCreationTimetoIFileSystemEntry. - Fixed a race condition in
ScriptMetadataValue. - Changed behavior of
SetDestinationwhen using a config value to makeDestinationPath,DestinationFileName, andDestinationExtensiontake precedence (with an option to override). - Added a
Contextproperty for the currentIExecutionContextto the available script properties (I.e., for use in metadata value scripts via "=>" notation).
- Added new
ProcessHtmlmodule for more flexible processing of DOM nodes. - Added new
IEnumerable<IDocument>.Flatten()extension to flatten document trees. - Added new
IEnumerable<IDocument>.FilterSources()andIEnumerable<IDocument>.FilterDestinations()extension methods. - Added a new
FilterDestinationsmodule to filter documents by destination path. - Added a
Config.ContainsSettings(params string[] keys)config factory to return whether the settings contain all the specified keys. - Refactored some methods from
IExecutionContextintoIExecutionStateand moved implementation toEngine. - Added new
EnumerateValuesmodule that will clone or create documents for each item in an enumeration. - Added
Keys.ExcludeFromEvaluationthat can exclude all or some metadata values from automatic script evaluation. - Added
IMetadata.GetNestedMetadata()to get a nested metadata value (not calledIMetadata.GetMetadata()to avoid conflicts with the old previous method of that name). - Renamed
IMetadata.GetMetadata()toIMetadata.FilterMetadata()which now returns aFilteredMetadatainstance. - Added new
FilteredMetadataclass to filter underlying metadata items by key(s). - Refactored a bunch of default interface implementations back to extension methods (turns out default interface implementations are a little awkward to maintain).
- Moved scripting support and the
CompileScriptandEvaluateScriptmodules toStatiq.Core. - Added
Microsoft.CodeAnalysistoStatiq.Core. - Metadata and configuration settings that are a string starting with "=>" are now considered "scripted" and the content to the right of the arrow will be lazily evaluated as C# code - this is a big deal and the use cases will become apparent over time (I have lots of big ideas around this feature).
- Removed the
InterpolateMetadatamodule in favor of more robust built-in scripted metadata. - Removed the
Statiq.CodeAnalysis.IDocumentExtensions.Interpolate()extension method in favor of more robust built-in scripted metadata. - Changed
CancellationTokenSourceuses inside the engine toCancellationTokensince the engine does not itself cancel execution. - Surfaced the
CancellationTokenfor a given execution through theIExecutionState. - Added a check to ensure the engine is only performing one execution at a time (the outer execution loop is not concurrently safe).
- Major refactoring involving engine and execution context interfaces, added a new
IExecutionStateinterface that essentially represents a run-time engine. - Added a new
DocumentIdComparerto compare documents by ID (#69, thanks @mholo65). - Removed
IParallelModule.WithSequentialExecution()and standardized on.WithParallelExecution(false)instead to make default behavior of running in parallel clearer (I.e., you have to turn it off). - Added additional configuration methods to
CacheDocumentsproviding more control over when to invalidate cached documents (#78). - Added
IReadOnlyPipelinefor runtime access to pipeline data without changing modules. - Added
IExecutionContext.Pipelineto get the currently executing pipeline from the execution context. - Removed
IBootstrapperand refactored to the one trueBootstrapper. - Added a
BootstrapperFactoryavailable viaBootstrapper.Factoryto create bootstrappers (this will make specialized creation extensions easier to discover).
- Changing target for all projects to .NET Core 3.1 LTS.
- New
Evalshortcode (#37, #68, thanks @ProH4Ck). - Fixes the
CacheDocumentsmodule and excludesIDocument.Idfrom hash calculation (#74, thanks @mholo65).
- Fixes a bug with
MirrorResourcesand relative links (#72, thanks @dafergu2). - The
PhaseOutputscollection now returns output documents from the most recent available phase or an empty result set if no phases were defined. - Adds .wasm as a supported media type (required for WebAssembly streaming).
- Fixes a bug with parallel modules when they return a null enumerable.
- Adds
AnalyzeCSharp.WithCompilationAssemblyName()to set the name of the module compilation (#71). - Adds a metadata key "Compilation" to
AnalyzeCSharpoutput documents to get the RoslynCompilationfrom the module (#71). - Adds
IConfig.EnsureNonNull()andIConfig.EnsureNonDocument()extensions to simplify config parameter checks. - Refactors many of the configuration methods in
AnalyzeCSharpto take configs instead of atomic values. - Ensures namespace documents from
AnalyzeCSharpcontain the "ContainingAssembly" metadata (#70). - Build script support for non-Windows platforms via a new
build.sh(#65, thanks @khalidabuhakmeh). - Adds a
Config<TValue>.MakeEnumerable()extension to transform a config into an enumerable value. - Adds a common
MultiConfigModuleBaseforMultiConfigModuleandParallelMultiConfigModule. - Adds
CombineConfighelper methods toMultiConfigModuleBaseto help with combining config values during configuration. - Refactors several of the
StartProcessconfiguration methods to take configs.
- Split
DefaultFeatures.CommandsintoDefaultFeatures.BuildCommands,DefaultFeatures.HostingCommands, andDefaultFeatures.CustomCommandsfor finer control. - Renamed
DefaultsToAddtoDefaultFeatures. - Adds a new
ThrowExceptionmodule that can be used to throw exceptions based on a config value. - Renames
BuildCommandtoPipelinesCommand. - Refactors default commands by renaming
buildtopipelinesand accepting pipelines to execute as an argument (moving the root path to an option). - Added
IBootstrapper.AddCommands<TParent>()to add all nested class commands of a parent type. - Added
IBootstrapper.AddPipelines<TParent>()to add all nested class pipelines of a parent type. - Added
Bootstrapper.CreateDefaultWithout()andIBootstrapper.AddDefaultsWithout()to create a default bootstrapper without specific components. - Renamed
IBootstrapper.AddBuildCommand()methods toIBootstrapper.AddPipelineCommand().
- Added
StartProcess.WithArgument()methods to add arguments to the module using a fluent interface. - Added
Config<TValue>.CombineWith()extensions for combining two configs. - Added
Config<TValue>.Transform()extensions for transforming from one value to another. - Made
IExecutionContext(re)implementIMetadatathroughSettings. - Added
ToString()overloads toIFileSystemEntry(can't believe those weren't already there). - Added a
Statiq.Netlifyextension with aDeployNetlifySitemodule. IDocumentnow implementsIContentProviderFactory.- Added some additional
IContentProvideroverloads to theDeployAppServicemodule.
- Updated several low-risk package versions.
- Adds option names to all command option values (#64, thanks @patriksvensson).
- New
servecommand for serving arbitrary folders with a local preview server (#55, #60, thanks @duracellko). - Fix for regression when there are dependencies on pipelines that aren't executing.
- Small -- prefix in console/logs to help indicate when a pipeline phase is finished.
- Set longer timeouts for App Service uploads.
- Added support for uploading a zip file to Azure App Service (useful for artifact-based release processes).
- Fixes a bug in dependency ordering where deployment pipeline output phases were being run too early.
- Added
SetMediaTypemodule to set the media type without changing the content. - Changed the semantics of
IDocument.ContentProviderso that it's never null. - Added
IContentProvider.Lengthto get the content length without needing to get the stream. - Renamed
AddMetadatatoSetMetadatato better match other module naming conventions and to reflect the metadata key being set might already exist. - Renamed
ReplaceContenttoSetContentto better match other module naming conventions. - Removed the pre/post render flag from
ProcessShortcodesand uses a default delimiter of<?# ... ?>(the forthcoming site generator will need to define the alternate delimiter for pre-transform shortcodes directly). - Added overloads of methods that create content providers to set the media type.
- Updated all built-in modules to set the media type whenever appropriate.
- Added
IContentProvider.MediaTypeto surface the media type of content. - Added a
MediaTypesstatic class that contains an exhaustive set of media type (MIME) mappings by file extension. - Added a
DeploySearchIndexmodule that deploys an Azure search index from input document metadata. - Added a
deploycommand that executes deployment pipelines. - Added a new
ExecutionPolicy.Normalpolicy and changedExecutionPolicy.Defaultto specify different behavior depending on if the pipeline is a deployment pipeline.
- The string overload of
SetDestinationnow takes either an extension or a path distinguished by a preceding dot. - Updated Statiq.Razor to 3.0 libraries.
- Updated Statiq.Hosting to 3.0 libraries.
- Fixes
ExecuteIfto work when there are no input documents and the config doesn't require one. - Fixes bug calculating command name for generic command types.
- Refactors
CreateDocumentsand adds additional config-based overloads.
- Changed
IBoostrapper.ConfigureSettings()to use a newIConfigurationSettingsobject that exposes the settings and the underlyingIConfiguration - Renamed the execution-time
IConfigurationSettingstoIReadOnlyConfigurationSettingsand introduced a new mutableIConfigurationSettingsto use in the bootstrapper. - Several bug fixes related to settings and configuration.
- Changed
IBootstrapper.AddSettings()calls to run after other configuration. - Adds a single pattern overload to
ReadFiles. - Some refactoring of the base
Pipelineclass (most importantly to remove theDependenciessetter in favor of adding to the existing hash set). - Adds
IReadOnlyApplicationState.IsCommand()to determine the current command.
- Added extensions for CLI
IConfiguratorto allow more flexible direct configuration (such as command branches). - Removed configuration/settings debug output on startup as it could leak secrets via environment variables or other configuration providers.
- Fix for
GenerateJsonso it executes when no input documents are provided. - Fix for preview command when no output is generated and the output directory does not exist.
- Fix for clearing content with empty string in
ReplaceContent. - Renamed
EngineSettingstoConfigurationSettingsto reflect a broader use than just the engine.
- Added
IBootstrapper.AddDelegateCommand()fluent methods to configure delegate-based commands. - Added
IBootstrapper.AddBuildCommand()fluent methods to configure simple commands that build specified pipelines. - Refactored the base commands to allow consumers to derive from
EngineCommand. - Added a new
IEngineManagerinterface to expose the engine manager to commands that derive fromEngineCommand. - Refactored
IEngine.SettingsandIExecutionContext.Settingsto use aIConfigurationas the backing store and present it as metadata. - Lazily creates type-based pipelines using the DI container so they can have injected services (#59).
- Adds
INamedPipelineto allow pipeline instances to provide names. - Changes
Module.AfterExecution()andModule.AfterExecutionAsync()to pass a newExecutionOutputsclass instead of by ref (which doesn't work with async). - Some tweaks to the
MirrorResourcesretry policy.
- Adds
==overloads toNormalizedPath. - Adds a special
RenderSection()toStatiqRazorPagethat renders default content if the section is not defined. - Renamed
IDocument.GetStream()toIDocument.GetContentStream(). - Renamed
IDocument.GetStringAsync()toIDocument.GetContentStringAsync(). - Renamed
IDocument.GetBytesAsync()toIDocument.GetContentBytesAsync(). - Added
IEngine.SerialExecutionand--serialCLI argument to run pipelines and modules in serial (#58).
- Adds support for deployment pipelines (
IPipeline.Deployment) which run their output phase only after other output phases (#57). - Fixes a bug when specifying a setting on the CLI and the bootstrapper.
- Adds
StartProcess.WithErrorExitCode()to define a custom function for determining if the process existed in error. - Adds new
-d/--defaultsand a flag to the engine to indicate if default pipelines should be run independent of specified pipelines. - Renames
SimpleBuildCommandtoCustomBuildCommandand adds support for the default pipelines flag.
- Adds back a
ExecuteModulesmodule that works like the oldBranchmodule used to by dropping any output documents from the child modules. - Tweaks to the placeholder factory in
CreateTree. - Fix for the JavaScript engine getting reset on execution.
- No longer strips "Pipeline" from the end of pipeline classes for the pipeline name since
nameofis often used to refer to pipelines.
- Adds
StartProcess.KeepContent()to prevent replacing document content with process output. - Adds
StartProcess.OnlyOnce()to only execute the process once. - Renamed
PipelineTriggertoExecutionPolicy. - Adds type-based methods for adding pipelines.
- All
IPipelineimplementations from the entry assembly are added by the bootstrapper by default. - All
ICommandimplementations from the entry assembly are added by the bootstrapper by default. - Adds ability to specify which defaults to add to the bootstrapper.
- Made
EngineManagerpublic so it can be used by custom commands. - Adds a new
SimpleBuildCommandbase command to make creating new pipeline-specific build commands easier. - Adds
AddPipelines()andAddCommands()methods to add pipelines and commands from the entry or a given assembly. - Adds
MultiConfigModule,ParallelMultiConfigModule,SyncMultiConfigModule, andParallelSyncMultiConfigModulebase classes for modules that use multipleConfig<T>values. - Adds
ExecutionPipelinebase pipeline for use when a custom pipeline that runs code for each phase is needed. - Adds new
ZipDirectorymodule. - Renames the
Statiq.AmazonWebServicesextension library toStatiq.Aws. - Adds
Statiq.Azureextension library. - Adds new
DeployAppServicemodule.
- Updated to .NET Core 3.0 final.
- Isolated pipelines can now be dependencies of other pipelines (but output documents still can't be accessed).
- Renames delegate-based
IBootstrapper.AddSettings()overload toIBoostrapper.ConfigureSettings(). - Renames
IBootstrapper.AddServices()toIBoostrapper.ConfigureServices(). - Adds
IBootstrapper.ConfigureEngine(). - Adds a
StartProcessmodule to start a process and create a document from it's output or run it in the background. - The bootstrapper now adds environment variables to the settings by default with ALL_CAPS keys.
- Any setting with an ALL_CAPS key is masked during debug output on startup.
- Ongoing console logging improvements.
- Added trigger conditions to pipelines to include always running or manually running.
- Added a
-p/--pipelineCLI argument to indicate which pipelines to execute.
- New execution summary table logged after execution.
- New console logger with better output.
- More refactoring of base
Modulebefore/after methods.
- Renamed the GitHub project/repo to "Statiq.Framework" to match forthcoming "Statiq.Web" and to distinguish between primary code repos (prefixed by "Statiq.") and themes, etc. Also note the upcoming Statiq app will be known as Statiq Web from now on (as opposed to Statiq Framework).
- The engine now returns a
IPipelineOutputswith the result documents from each pipeline. - Adds global events
BeforeModuleExecutionandAfterModuleExecutionwith ability to override outputs. - Adds a new global event mechanism via
IEventCollection,IReadOnlyEventCollection,IEngine.Events, andIExecutionContext.Events. - Refactored the base module classes to include a before/after execution method, made the execution methods
protected, and renamed the execution methods for clarity. - Added property setters with null checks to
Pipelineso it works better as a base class and you can define the phase modules directly as properties. - Cleaned up
ModuleListmethods to remove overload ambiguity betweenparams IModule[]andIEnumerable<IModule>. - Added an implicit operator from
IModule[]toModuleList. - Raw application arguments as well as application input are now surfaced through a new
IReadOnlyApplicationStateobject in theIExecutionContext, taking the place of theApplicationInputproperty. - Adds a bunch of
Config.FromSettings()methods that get values from aIReadOnlySettings. - "Pipeline" is now trimmed from the end of type names when types are added as a pipeline to a pipeline collection.
- Statiq Framework is comprehensive "reboot" of Wyam.