This software aims to provide a simple but powerful templating mechanism.
The original idea was to create a simple static site generator, which is not as overloaded with "unnecessary functionality" as f.e. hugo. The result, though, should not specifically be bound to website contents, as it can be used for any textfile-templating. -> At least when #9 is resolved.
Temingo supports
- normal-type templates (== single-file-output templates) that will render to exactly one output file,
- partial-type templates (== partial templates) that can be included in other templates, also in other partials,
- meta-type templates (== multi-file-output templates) that can be used to render multiple output files,
- static files that will be copied to the output directory as is - respecting their location in the input directory filetree (except for
meta.yaml
files which are used for meta-type templates), - an ignore file (
.temingoignore
) that works similar to.gitignore
, but for the templating process. - a watch mechanism to trigger a rebuild of the output directory if necessary, which continously checks if there are filechanges in the input directory or the
.temingoignore
/
If you're feeling fancy:
curl -s https://raw.githubusercontent.com/thetillhoff/temingo/main/install.sh | sh
or manually from https://github.com/thetillhoff/temingo/releases/latest.
Temingo by default:
- takes all
*.template*
files from the source folder./src
. - writes the rendered files into the destination folder
./output
.
Temingo by default considers the ignored paths as described in ./.temingoignore
which has a similar syntax as a .gitignore
.
Temingo by default takes all other files (static) and copies them into the output folder as-is. Except meta.yaml
s.
Temingo by default takes all *.partial*
files as intermediate templates / snippets
- the defined intermediate template names must be globally unique so they can be imported properly later. Temingo verifies the uniqueness.
- partials are added automatically with path,
partial/page.partial.html
is the automatic default name for that partial. - it's not needed to add the
{{define ...}} ... {{ end }}
part to partials, it's added automatically. - allow globs for including templates, for example
{{ template "*.partial.css" . }}
, also for subfolders
Temingo by default passes the following metadata to the rendering:
- pass global variables like datetime (globally equal renderTime only)
-
.meta.path
contains the rendered template path -
.meta.breadcrumbs
contains a slice of the folder hierarchy for each template
Temingo by default aggregates the metadata that is passed to the rendering as follows;
- Iterate through folders from inputDir
./src
down to the folder containing the template file - On that way, always merge the lowerlevel
meta.yaml
(if it exists) into the parent one (overwrite if necessary) - Pass the final object to the respective template rendering process
For each *.template*
file, temingo by default searches for all ./*/meta.yaml
s (in all folders that are one level further down from the template file) and adds them as .childMeta.<foldername>.<content-object>
pair to the template.
This means you can iterate over them and for example generate links for them.
Temingo by default takes all *.metatemplate*
files and uses them as template in all of the sibling subfolders that contain a meta.yaml
file. The object in those files are passed for each rendering.
Temingo by default processes markdown files as follows:
- If a template path (either as sibling or as child for the metatemplates) contains a
content.md
it is converted to html and made available as.content
during the templating process.
- add --watch / -w flag for watching for file changes in the source folder
- partial/conditional rerender for only the changed files -> also only those changes will be printed in the logs fileWatcher/Render should check if the renderedTemplate is actually different from the existing file (in output/) -> hash if the files exist, check rendered stuff only writeFile when an actual change occured -> take double care of files that are created newly / deleted
- don't delete & copy when a static file hasn't changed. Maintain the necessary hashtable/s for static files in memory.
- if output folder isn't empty, generate hashlist during first build
- don't delete & recreate rendered files when its contents haven't changed
- add --serve / -s flag for running a simple integrated webserver directly on the output folder.
-
file extension autodiscover
- add table in readme on which extensions are covered
- minimum are html, css and js. nice would be are svg and somehow image integration in webpages (webp conversion, auto replace in all src)
temingo can do (this should probably be put into a dedicated application ("website optimizer"?) which could also include submodules like minifyCss, minifyHtml, minifyJs, prettifyCss, prettityHtml, prettifyJs):
- content validation, for example check if the result is valid html according to the last file extension of the file. Supported extensions:
.html
.css
.js
- content minification, for example for html files. Supported extensions:
.html
.css
.js
- optimized media embedding, for example for images. Supported media:
- images
- svg (pregenerate different colors?)
-
SHA256, SHA384, and SHA512 generation for files, for example
*.js
files, so they can be added to your csp config file, and nonces are supported.
TBD
- is it good to do this there? Wouldn't it be better to use something else instead? Linux approach, do one thing, but do it good.
This is currently enabled by default.
- add flag / setting
- beautify html
- beautify css
- beautify js
TBD
-
is it good to do this here? Wouldn't it be better to use something else instead? Linux approach, do one thing, but do it good.
-
add flag / setting
-
minify html, warn user if there are undefined css classes used
-
minify css, warn user if there are unused css classes
-
minify js
TBD
-
is it good to do this here? Wouldn't it be better to use something else instead? Linux approach, do one thing, but do it good.
-
add flag / setting
-
file extension autodiscover (html files only, which image format is used, depending on setting media format can be transformed as well)
-
optimize media embedding automatically, but warn the user
temingo
temingo init // Generates a sample project in the current folder. Only starts writing files if the input directory doesn't exist yet. Supports all flags except `--watch`.
--inputDir, -i, default "./src": Sets the path to the template-file-directory.
--outputDir, -o, default "./output": Sets the destination-path for the compiled templates.
--templateExtension, -t, default ".template": Sets the extension of the template files.
--metaTemplateExtension, -m, default ".metatemplate": Sets the extension of the metatemplate files. Automatically excluded from normally loaded templates.
--partialExtension, -c, default ".partial": Sets the extension of the partial files.
--metaFilename, default "meta.yaml": Sets the filename of the meta files.
--temingoignore, default ".temingoignore": Sets the path to the ignore file.
--watch, -w, default false: Watches the inputDir and the temingoignore.
--dry-run, default false: If enabled, will not touch the outputDir.
--verbose, -v, default false: Enables the debug mode which prints more logs.
Here's a list of variables that are passed to each template rendering process:
["path"] = string -> path to template (within `./src/`)
["breadcrumbs"] = []string -> path to location of template, split by '/'
["meta"] = map[string]object -> aggregated metadata for current folder
["childMeta"] = map[string]object -> metadata of subfolders, key is the folder name containing the respective metadata
-
Test the rendering via golang tests, not manually.
-
go through comments in README and todos in code
-
move funcmap add to template engine into extra function, so it happens always exactly the same for the temporaryTemplateEngine and the templateEngine
-
automatically check all "internal" links of website for validity aka file exists
-
automatically check all links that have a protocol specified to use https and warn in case of http
-
add setting to enable/disable auto-intendation of multiline partials with same whitespace as reference. Default is enabled.
cobra-cli add <command>
go test ./...
- Don't have global variables in a package -> they would be obstructed for the consumer and are not threadsafe
- Don't use functional options -> they require a lot of code / maintenance. Also, having functions to set a context object every time a function is called is tedious
- Use Context (called engine in this project). Not necessarily the go-context package, but implement "instance of package" as context and use that.
- For packages that have "global" variables / arguments, use Context (called "engine" in this project) as well.