Page
Library
Module
Module type
Parameter
Class
Class type
Source
profile option, like widgets, and can be limited to specific build profiles.--config option for specifying custom config path without the use of environment variables.--version-number option that prints just the version number (for easy use from scripts).soupault --init how takes --site-dir and --build-dir options into account when generating the config.keep_extensions and default_extension options are now mentioned in configs genrated by soupault --init.[] is false, any non-empty list is true).post-save hook makes it easier to post-process generated page files (e.g., run them through an HTML minifier).Sys.get_program_output(cmd, input_string).Sys.strip_extensions function for removing extensions from file names.save hook code.clean_urls = false, pages now have correct url index fields (with original extension removed) (github#44, report by github/@laumann).index_template, index_item_template, or index_processor.absolute_links widgets without prefix are considered configuration errors.settings.build_dir is no longer allowed (formerly caused soupault to use the current dir as output dir).settings.process_pages_first option allows the user to force processing certain pages before all other.pre-parse, pre-process, post-index, render, and save.index.index_first option allows pages to access their own index entries (at cost of a two-pass workflow with a reduced index-only run done first).sort_by and sort_type) can be specified in every index view independently.action option to control generated HTML insertion.lua_source option.relative_links and absolute_links widgets support almost all imaginable that can contain URLs in attributes.--dump-index-json <file> option allows exporting metadata to JSON without setting index.dump_json in the config.target_file (path to the output file, relative to the current working directory).index_entry (the index entry of the page being processed if index.index_first = true, otherwise it's nil).String.slugify_soft(string) replaces all whitespace with hyphens, but doesn't touch any other characters.String.url_encode(str) and String.url_decode(str) for working with percent-encoded URLs.String.join_url as an alias for String.join_path_unix.HTML.to_string(etree) and HTML.pretty_print(etree) return string representations of element trees, useful for save hooks.HTML.create_document() creates an empty element tree.HTML.clone_document(etree) make a copy of a complete element tree.HTML.append_root(etree, node) adds a node after the last element.HTML.child_count(elem) returns the number of children of an element.HTML.unwrap(elem) yanks the child elements out of a parent and inserts them in its former place.Table.take(table, limit) removes up to limit items from a table and returns them.Table.chunks(table, size) splits a table into chunks of up to size items.Table.has_value(table, value) returns true if value is present in table.Table.apply_to_values(func, table) applies function func to every value in table (a simpler version of Table.apply if you don't care about keys).Table.get_nested(table, {"key", "sub-key", ...}) and Table.get_nested_default(table, {"key", "sub-key", ...}, default) for easily retrieving values from nested tables (handy for getting config options).Table.keys(table) returns a list of all keys in table.Sys.list_dir(path) returns a list of all files in path.Value.repr(value) returns a string representation of a Lua value for debug output (similar to Python's __repr__ in spirit).String.length is now Unicode-aware, the old ASCII-only version is now available as String.length_asciiString.truncate is now Unicode-aware, the old ASCII-only version is now available as String.truncate_asciinumeric index entry sorting method works correctly again.include_subsections option is now available to all widgets and documented (it makes section apply to a dir and all its subdirs).soupault.toml work correctly now (fixed in OTOML 1.0.1).Sys.list_dir correctly handles errors when the argument is not a directory.index.sort_by is not set, entries are now sorted by their url field rather than displayed in arbitrary order.running preprocessor "cmark --unsafe --smart"...).persistent_data variable allows storing data between Lua plugin runs.HTML.matches_selector and HTML.matches_any_of_selectors plugin functions for checking if elements match given selectors.settings.soupault_version option for setting minimum required soupault version.Sys.join_path_unix, Sys.basename_unix, and Sys.dirname_unix plugin functions for safely working with URLs on all OSes.Table.iter_ordered and Table.iter_values_ordered functions for ordered iteration over integer-indexed tables.ignore_heading_selectors in the ToC widget for excluding certain headings from the ToC.NO_COLOR environment variable.TOML.from_string/TOML.from_string_unsafe and YAML.from_string/YAML.from_string_unsafe for TOML and YAML parsing.Soupault now uses OTOML instead of To.ml for TOML parsing and manipulation.
--show-default-config and --show-effective-config options for displayingconfig variable.include_subsections option in index views now works correctly (report by toastal).soupault --init now includes all options, including pretty_print_html, plugin_discovery, and plugin_dirs (report by Crystal-RainSlide).wrap widget.soupault --profile live --profile debug.disabled = true to its config.index.sort_type option for sorting index entries in different ways (can be calendar, numeric, and lexicographic, the default is calendar).index.strict_sort option that makes soupault fail the build if a value can't be parsed.generator_mode = false and keep_doctype = false, and the page lacks an <HTML> element.settings.pretty_print_html option for choosing whether to pretty-print output HTML or not.relative_links and absolute_links.Sys.get_extensions and Sys.has_extension.exec and preprocess_elements can no longer crash soupault on Windows.ignore_extensions option now checks all extensions rather than just the last, i.e., ignore_extensions = ["tar"] will match both file.tar and file.tar.gz now (report by Anton Bachin).settings.debug = true and --debug automatically enable exception traces now.soupault --help (patch by Anton Bachin).keep = true in the title widget allows keeping existing title.index.leaf_file allows marking subdirectories as "hand-made clean URLs".index.force_indexing_path_regex option for treating some index pages as normal pages.widget_config alias for config (since now there’s the global soupault_config, a more specific alias may be a good idea)build_dir and site_dir variables in the plugin environment (PR by Hristos)Table.get_key_default(table, key, default_value)Value module: is_int, is_float, is_string, is_table, is_list (table with all integer keys), is_nil.Sys.mkdir, Sys.get_file_modification_dateinclude_subsection option in the [index] table works correctly now (used to cause a spurious option validation error).HTML.get_heading_level function now works with nodes returned by HTML.select (rather than just values created with HTML.create_element).insert_html widget now supports parse = false, mainly for consistency with include and preprocess_element.String.base64_encode and String.base64_decode.Sys.basename and Sys.dirname.Sys.get_extension (e.g. "hello.jpg" → "jpg").Sys.file_exists.Sys.is_file and Sys.is_dir. Both return nil if it does not exist.Sys.run_program_get_exit_code. Returns the exit code unlike, Sys.run_program. 0 means success.Sys.delete_file and Sys.delete_recursiveprofile option for widgets works as expected again.custom_options config table for storing user/plugin-defined options.soupault_config variable allows plugins to access the global soupault config.JSON.unsafe_from_string() function that returns nil if it cannot parse its input.%).escape filter of the template processor now emits symbolic HTML entities like > now, rather than numeric character codes.Iterating through tables is a real weak point of the 2.5 era Lua implemented by Lua-ML. To make working with tables simpler, I’ve added a high level few helpers functions, including:
Table.iter(func, table)Table.iter_values(func, table)Table.apply(func, table)Table.fold(func, table)Table.fold_values(func, table)soupault --init.32-bit Windows is no longer supported, all future Windows builds will be for 64-bit Windows only.
default_content_action and default_content_selector options for the default template.content_action and content_selector options for custom templates.slug_regex, slug_replacement_string, and slug_force_lowercase.max_heading_link_level level in the ToC widget allows adding heading links to headings too deep for the ToC itself.settings.keep_doctype option allows preserving existing doctype if it's present.--index-only.soupault --version.breadcrumb_template in the breadcrumbs widgets is now a Jingoo template.There is an online config convertor to simplify migration.
The reason for removing the built-in content model was that custom fields introduced in soupault ... were already more flexible than the old-built in fields: they had extract_attribute and default_value options. Old field configuration, however, were limited to just a selector and nothing else, since their syntax wasn't designed to be extensible: index_date_selector, index_author_selector, index_title_selector, and index_excerpt_selector.
That was a design mistake that was impossible to fix without completely changing the syntax. Removing the inflexible built-in fields in the process looked like a logical step.
site_index variable.String.render_template(template_string, env_table) plugin function for Jingoo template rendering.JSON.to_string and JSON.pretty_print functions for JSON output.Sys.get_file_size function.min_headings option in the ToC widget to show a ToC only for pages with enough headings.valid_html option in the ToC widget that makes it output nested lists inside a <li> rather than directly under <ul>/<ol>.HTML.get_headings_tree function for getting page ToC data structure and rendering a custom ToC.String.to_number function for parsing numbers.force option in the title widget forces it to create a <title> element if a page doesn't have it.nil values and return nil in that case.extract_attribute option in custom index fields allows extracting element attributes rather than content.HTML.set_attribute, HTML.is_element.String.join(strings, separator) function.settings.plugin_discovery = true. The default plugin directory is plugins/.HTML.get_tag_name, HTML.select_any_of, HTML.select_all_of.Sys.is_unix. and Sys.is_windows.page_file field in page index entries.--index-only option to only extract site index and exit without generating pages.preprocess_element widget now allows lists of selectors in the selector option.Sys.run_program and Sys.get_program_output.title widget correctly removes all HTML tags from the title string (if there are any) and doesn't add extra whitespace (thanks to Thomas Lethan).profile = "live" will only be processed if you run soupault --profile live.preprocess_element and exec widget can now access the target directory setting via TARGET_DIR environment variable.Plugin.require_version("42.0.0").Sys.random(max)Sys.get_program_output(command)Log.debug(message)HTML.replace_element and HTML.delete_elementString.trim(string) and String.slugify_ascii(string)preprocess_element for piping HTML element content through external programs.Building soupault now requires OCaml 4.08 or later.
<noscript> elements in the page <body> are now handled correctly.strip_tags option.index.extract_after_widgets option.Plugin.exit and Plugin.failRegex.splitHTML.create_text and HTML.strip_tagsSys.read_file, Sys.join_pathpage_url variable available to plugins.section and exclude_section now behave as expected.settings.complete_page_selector option for specifying element whose presence excludes page from templating (by default, <html>).settings.generator_mode = false.SOUPAULT_CONFIG environment variable.delete_element widget for deleting HTML elements from pages.--verbose and --debug options.settings.ignore_file_extensions option for ignoring certain files.soupault --init generates more illustrative and well-commented configs.%PATH% now work as expected, no need to specify an absolute path[preprocessors] section doesn't cause an erroneus "invalid config section" warning anymorelink_id_prepend and back_link_id_append that allow you to create a separate "namespace" for footnote links.option "foo" is not valid for widget "title".invalid option "backlinks", did you mean "back_links"?.adoc) is now in the default page extensions list.Log.info, Log.warning, Log.errorsoupault --init generates correct page_file_extensions option in the default config now.include_html widget.Footnotes now include links back to the original location in the document for easier navigation. It's possible to disable this and make footnote links one way with back_links = false widget option.
[widgets.footnotes]
widget = "footnotes"
# No back links
back_links = false
# ...It's now possible to limit widgets to page file paths matching a Perl-compatible regex.
[widgets.starts-with-foo]
path_regex = "/foo(.*)"
widget = "insert_html"
selector = "body"
html = '<p>This page name starts with foo!</p>'It's now possible to explicitly exclude pages from a widget using these options:
exclude_pageexclude_sectionexclude_path_regexFor example:
[widgets.toc]
# No ToC on any page named "index"
exclude_path_regex = '/index(\.*)'Binaries for macOS are available.
Only files with extensions .htm .html .md .rst are assumed to be pages now, all other files are copied to the build dir unchanged. This is to simplify switching for existing websites that store assets together with pages, and to comply with the principle of least astonishment.
You can change it with page_file_extensions option, for example:
[settings]
page_file_extensions = ["htm", "html", "md", "rst", "txt"]It is now possible to export the global website index to file:
[index]
index = true
dump_json = "path/to/file.json"Example:
[index.custom_fields]
tags = {selector = ".tag", select_all = true}
category = {selector = "#category" }page and section options can now be either single selector or lists. This also applies to the selector option in title and footnotes widgets, with different semantics (select any that exists and select all respectively).
--strict/strict = true) now actually stops on the first error.use_heading_text and use_heading_slug options. Old use_header_* options are kept for compatibility but deprecated.soupault --init are now displayed if neither site dir nor default template exist.The first beta. It's stable enough to build my own website with a pretty interesting config, but may still have rough edges.