This is the multi-page printable view of this section. Click here to print.
Community
- 1: Roadmap
- 2: Developer Guide
- 2.1: Software Stack
- 2.2: Running Stroom in an IDE
- 2.3: Components
- 2.4: Contributing
- 2.5: Release Process
- 2.5.1: Releasing Stroom
- 2.6: Setting up releases to Sonatype & Maven Central
- 3: Developing Content
- 4: Documenting Stroom
- 4.1: Building the Documentation
- 4.2: Managing Stroom Versions
- 4.3: Documentation Style Guide
- 4.3.1: Site Structure
- 4.3.2: Front Matter
- 4.3.3: Markdown Style Conventions
- 4.3.4: Additional Page Elements
- 4.3.5: Images
- 4.3.6: Icon Gallery
1 - Roadmap
v7.0
Reference data storage
Reference data uses a memory-mapped disk-based store rather than direct memory to reduce the memory overhead associated with storing reference data.
Search result storage
Search results are stored on disk rather than in memory during creation to reduce the memory overhead incurred by search.
Modularisation
Separation of Stroom components into discreet modules that have clear APIs and separate persistence where required to reduce coupling.
Modernisation of libraries
Changing Stroom libraries to replace Spring with Guice and Hibernate with JOOQ.
Annotations
Search results in dashboards can be annotated to provide status and notes relating to the result item, e.g. an event. These annotations can later be searched to see which events have annotations associated with them.
v7.1
Elastic search integration
Elastic search can be used for indexing data. Data can be sent to an elastic index via a pipeline element and an elastic index can be queried from a Stroom dashboard.
Interactive Visualisations
Selecting or manipulating parts of visualisations can be used to trigger further queries to zoom in or select specific data etc.
Improved Proxy Aggregation
Proxy aggregation can better match user defined aggregate sizes and forward to multiple destinations.
User Preferences
The UI can be customised to meet the needs of an end user including theme (dark mode), date and time format, font, layout.
v7.2
XSLT 3
Add support for XSLT 3.
Accessibility Improvements
Refactoring some elements of the UI to improve accessibility.
v8+
Authorisation enhancements
The Stroom authorisation system is split out into a separate service and provides integration with external authorisation mechanisms.
Proxy processing
Stroom proxy is capable of pipeline processing in the same way as a full Stroom application. Pipeline configuration content can be pushed to proxies so that they can perform local processing prior to sending data to Stroom.
Multiple input sources
Stroom is capable of processing data from a Kafka topic, HDFS, the local file system, HTTP POST in addition to the included stream store.
Multiple output destinations
Stroom has improved support for writing to various destinations such as Kafka, HDFS, etc. Improvements include compression and meta data wrapping for future import.
Improved field extraction
Enhancements to data splitter and associated UI to make the process of extracting field data from raw content much easier.
Kafka analytics
Stroom exposes the use of Apache Kafka Streams for performing certain complex analytics.
Query fusion
Stroom allows multiple data sources to be queried at the same time and the results of the queries to be fused. This might be for fusing data from multiple search indexes, e.g. events and annotations, or to effectively decorate results with additional data at search time.
Reference data deltas
Reference data is enhanced to cope with changes (additions and removals) of state information rather than always relying on complete snapshots.
2 - Developer Guide
2.1 - Software Stack
Stroom and Stroom Proxy
Stroom and Stroom Proxy live in the same repository, share some common code and are built by the same Gradle build.
Languages and key frameworks
- Java 15 - The language for the core application
- Dropwizard - A RESTful framework incorporating embedded Jetty.
- Junit 5
- SLF4j and Logback
- Mockito
- Jooq - Generates Java code for type safe SQL.
- Apache Lucene - The search library used by Stroom’s indexes and dashboard queries.
- Lightning Memory Mapped Database - Used for memory mapped persistent reference and search data stores.
- React - Some of the new UI screens.
- Typescript
Build and development tools
- Gradle - Building the java application and orcestrating related sub-builds, e.g. npm.
- Github Actions - The CI build and release.
- Bash - Various utility shell scripts.
- Docker - Building the stroom and stroom-proxy docker images.
- Docker Compose -
- Docker containers - Provide consistent build environments for
- Java
- npm
- Plant UML
- npm - For the build of the new React based UI screens.
Services
- Nginx - Used for SSL termination, load balancing and reverse proxying.
- MySQL - Database for persistence in Stroom.
2.2 - Running Stroom in an IDE
We tend to use IntelliJ as our Java IDE of choice. This is a guide for running Stroom in IntelliJ for the purposes of developing/debugging Stroom.
Prerequisites
In order to build/run/debug Stroom you will need the following:
- OpenJDK 15
- Git
- Gradle
- IntelliJ
- Docker CE
- Docker Compose
These instructions assume that all servcies will either run in the IDE or in Docker containers.
We develop on Linux so if you are running on a Mac you may experience issues with some of our shell scripts. For running the various shell scripts in our repositories you are advised to install
- bash 4+
- jq
- GNU grep
- GNU sed
Stroom git repositories
To develop Stroom you will need to clone/fork multiple git repositories. To quickly clone all of the Stroom repositories you can use the helper script described in stroom-resource .
Database setup
Stroom requires a MySQL database to run. You can either point stroom at a local MySQL server or use the MySQL Docker container from stroom-resources.
MySQL in a Docker container
See the section below on stroom-resources.
Host based MySQL server
With an instance of MySQL server 8.0 running on your local machine do the following to create the stroom database:
Then run the following commands in the MySQL shell:
Local configuration file
When running stroom in an IDE you need to have a local configuration file to allow you to change settings locally without affecting the repository.
The local configuration file live in the root of the Stroom repository ./local.yml
.
To create a default version of this file run this script from within the root of the stroom git repository.
This will create ./local.yml
using stroom-app/dev.yml
as a template.
So that you can run a multi-node cluster it will also create ./local2.yml
and ./local3.yml
as well.
These files are not source controlled so you can make any changes you like to them, e.g. setting log levels or altering stroom property property values values.
stroom-resources
As a minimum to develop stroom you will need clones of the stroom
and stroom-resources
git repositories.
stroom-resources
provides the docker-compose configuration for running the many docker containers needed.
Having cloned stroom-resources
navigate to the directory stroom-resources/bin
and run the script
On first run this will create a default version of the git-ignored file stroom-resources/bin/local.env
which is intended for use by developers to configure the docker stacks to run.
This file is used to set a number of environment variables that docker compose will use to configure the various containers.
The key variable in there is SERVICE_LIST
.
This is a bash array that sets the services to run.
By default it is set to run stroom-all-dbs
(MySQL + database init scripts) and nginx
which are sufficient for running Stroom in an IDE.
Verify the Gradle build
Before trying to run Stroom in an IDE it is worth performing a Gradle build to verify the code compiles and all dependencies are present. This command will run all parts of the build except for the tests which can take 20+mins to run. Some parts of the build are run inside docker containers (to remove the need to install additional dependencies) so on first run there will be an overhead of building the docker image layers. These layers will be cached which will speed up future builds.
Local or embedded MySQL
The Junit integration tests that need a database can either be run against the local MySQL (i.e. stroom-all-dbs
) or an embedded MySQL instance.
Configuring the database used can be done with the JVM argument -DuseEmbeddedMySql=false
, which can be set in Run/Debug Configurations => Edit configuration templates… => JUnit => VM options in Intellij.
False will use your local MySQL instance, true with use the embedded one.
The CI build uses the embedded MySQL.
The pros/cons of using the embedded instance are:
- No dependency on stroom-resources to run the full build.
- Requires the MySQL binaries to be downloaded, sometimes multiple times.
- Consumes a lot of disk space if multiple instances are run.
- Harder to debug tests as the database is destroyed at the end of the test.
Clearing down your environment
If you need to work from a clean slate and you are using the container based MySQL you can run the following:
Warning
This script will delete ALL containers running/stopped whether related to Stroom or not. It is essentially a clean slate for your docker environment. If you are running other unrelated containers, don’t run this.
It will also delete all stroom state held on the filesystem, i.e. the stream store and lucene index shards.
Sample Data
When developing Stroom it is helpful to have Stroom run with pre-loaded content and data as by default it will be completely empty.
SetupSampleData.java
is a class that loads pre-defined content and data into the database and file system so that Stroom can begin processing data on boot.
This sample data/content is very useful for manually testing and exercising the application in development.
This class assumes that the database being used for Stroom is completely empty.
To run SetupSampleData use the pre-defined Run Configuration in IntelliJ called SetupSampleData. This will load content (e.g. XSLTs, Pipelines, etc.), create Feeds and load data into the Feeds.
You should now have a database and stream store populated with tables and data, providing you with some predefined feeds, data, translations, pipelines, dashboards, etc.
When Stroom is next started it will begin to process the data using the pre-defined pipelines.
Running Stroom from the IDE
The user interface for Stroom is built using GWT (see GWT Project for more information or GWT specific documentation). As a result Stroom needs to be started up with GWT Super Dev Mode. Super Dev Mode handles the on-the-fly compilation of the Java user interface source into JavaScript and the source map that links client JavaScript back to Java source for client side debugging.
The following steps for running and debugging Stroom in IDEA assume you have a MySQL database running on localhost:3307
, with a database stroom
and user stroomuser
already created.
JAVA_HOME
Ensure environment variable JAVA_HOME
is set and points to a valid JDK 15 directory
Alternatively to simplify the process of installing and managing Java JDKs consider using SDKMan .
Build stroom-app
NOTE: During development, it is helpful to skip running unit and integration tests, to speed up the build process:
Start a single Stroom node
- Select the IDEA run configuration named
Stroom GWT SuperDevMode
- Click
Debug
. Stroom will start, with log output displayed in theRun
pane at the bottom of the window.
This run configuration essentially sets the JVM argument -DgwtSuperDevMode=true
to run the application in Super Dev Mode.
Watch the log output. Once you see a log INFO message containing the text “Started”, you will be able to launch the app in a browser from: https://localhost.
You will see the Stroom blue background, with a username/password prompt. Enter the following default credentials:
- Username:
admin
- Password:
admin
You can now interact with Stroom and set breakpoints in Java code.
Note that setting breakpoints in any of the java code in modules suffixed with -client
(i.e. client side GWT Java code) does not have any effect, as these components are compiled to static JavaScript.
Breakpoints in modules ending -shared
will only have an effect if you are debugging server side code.
Note
Stroom has been written with Google’s Chrome browser in mind so has only been tested on Chrome. Behaviour in other browsers may vary. We would like to improve cross-browser support so please let us know about any browser incompatibilities that you find.Starting the Super Dev Mode Compiler
With the Stroom application running you need to also run a draft GWT compile and run the Super Dev Mode compiler.
On first use it is recomended to run:
This will ensure a clean state of the GWT compiled javascript. It may be necessary to re-run the clean, and draft compile if there have been significant changes to the Java code or if there are problems running Stroom in Super Dev Mode.
Normally however you can just run:
When this gradle task runs it will echo some instructions for how to set up your browser. Once the browser is all set up with the dev mode favorites you can visit Stroom at
- http://localhost:8080 (bypassing Nginx)
- https//localhost (via Nginx)
Running without Nginx is simpler but can hide problems with the Stroom/Nginx configuration/integration.
Authentication
In development you can either run Stroom with authentication on or off. It is a quicker development experience with authentication turned off but this can hide any problems with authentication flow.
To run Stroom with authentication turned off set the following in local.yml
:
stroom:
security:
authentication:
authenticationRequired: false
If you want to run with authentication but don’t want to be prompted to change the password on first boot you can set:
stroom:
security:
identity:
passwordPolicy:
forcePasswordChangeOnFirstLogin: false
Alternatively you can run the IntelliJ Run Configuration Stroom Reset Admin Password, which will reset the password to admin
and prevent further prompts to change it.
Right click behaviour
Stroom overrides the default right click behaviour in the browser with its own context menu.
For UI development it is often required to have access to the browser’s context menu for example to inspect elements.
To enable the browser’s context menu you need to ensure this is property is set to null in dev.yml
:
stroom:
ui:
oncontextmenu: null
To return it to its defualt value, set it to "return false;"
.
Hot loading GWT UI code changes
If you make any changes to the Java code in -client
or -shared
modules then in order for them to be hot loaded into the Javascript code you simply need to refresh the brower.
This will trigger Super Dev Mode to recompile any changed code.
If you have make significant code changes, e.g. moving/renaming classes then GWT can get confused so you may need to run the gwtDraftCompile and/or gwtClean gradle tasks followed by gwtSuperDevMode.
Debugging GWT UI code
To debug the GWT UI code you will need to use Chrome Dev Tools (shift+ctrl+i
).
Setting breakpoints in the UI code in IntelliJ will have no effect.
SuperDevMode creates source maps that link the running javascript back to Java code that you can set break points in.
To find the Java source in Chrome Dev Tools open the Sources tab then in the left hand navigator pane (Page tab) select:
Top => ui => stroom (ui) => 127.0.0.1:9876 => sourcemaps/stroom => stroom
This folder then contains all the stroom java packages.
2.3 - Components
Some examples of components in Stroom include
- stroom-activity - Component for recording a users actions against a current activity
- stroom-dictionary - Component for storing lists of words.
- stroom-statistics - Component for recording statistical data, e.g. amount of data received in X minutes.
In the project structure a component appears as a first level subdirectory of the root project folder. Components have further subdirectories (modules) that make up the various parts of the component, e.g.
stroom
- Root projectstroom-activity
- The componentstroom-activity-api
- API module forstroom-activity
stroom-activity-impl
- Implementation of the API and other module implementation codestroom-activity-impl-db
- Database persistence implementation used by implstroom-activity-impl-db-jooq
- JOOQ generated classes used bystroom-activity-impl-db
stroom-activity-mock
- Mock implementation for thestroom-activity
API
Dependencies between a modules components
The diagram below shows the dependencies between the different modules that make up a component as well as the internal dependencies within the impl
module.
The actual implementations used at runtime are determined by Guice bindings in whichever Guice modules are loaded by the application.
Tests can bind mock implementations of a components API just by using the Guice module within the mock module.
Dependencies between components
Typically a component will need to call out to other components to apply security constraints and to log user activity. These typical relationships are shown in the diagram below.
Component API, e.g. modules ending in -api
API layer
All communication between components in stroom must be made via a component’s API. The API provides the minimum surface area for communication between components and decouples dependencies between components to just the API code. For component testing purposes mock implementations of these APIs can be used to limit testing to just a single component.
Component API and service implementation, e.g. modules ending in -impl
Client interaction - REST services and GWT Action Handlers
The uppermost layer of the server side code services requests from the client. The client may make restful calls as is the case for the new UI or will use Actions that are handles with ActionHandlers as is the case for the legacy GWT UI.
Since this layer deals with all client interaction it should be responsible for creating audit logs for all user activity, e.g. accessing documents, searching etc. No audit logging should need to be performed at a lower level within the application as deeper levels have less knowledge of user intent since they may just be playing a part in the wider request.
The client interaction layer adds no logic and asks the underlying service layer to service the encapsulated request away from the REST endpoint wrapping code or GWT action handler code. This allows multiple types of endpoint to use the same underlying service layer. If a request requires the use of multiple services to form a response, this must be handled within the service layer by the primary service which will be responsible for any such orchestration.
Service layer
The service layer applies permission constraints to any requests being made so that only calls from identified and permitted users are allowed to proceed. The service layer performs all orchestration and business logic, and is responsible for all mutations of objects that will be persisted by the underlying persistence layer such as stamping objects to be updated with the current user and update time.
The service layer provides implementations for any API that the component may have.
The service layer provides the DAO (Data Access Object) API for the persistence layer to implement but maintains no knowledge of underlying persistence implementation, e.g. database queries.
Persistence implementation, e.g. modules ending in -impl-db
Persistence layer - DAOs
The persistence layer is an implementation of one or more DAOs specified in the service layer. The persistence layer provides no logic, it just stores and retrieves objects in a database or other persistence technology. If serialisation/de-serialisation is required in order to persist the object then that should also be performed by this layer so that no code above this layer has to care about this implementation detail.
The persistence layer does not apply security or permissions checking so should not need to reference the security API.
2.4 - Contributing
TODO
- Feature branches
- Branch name
- Change log
- Checkstyle
- PR conventions
- Link to issue
2.5 - Release Process
2.5.1 - Releasing Stroom
Pre-requisites for a release
The follow need to be completed before a release is made.
Logging changes
Stroom and its related repositories all have a CHANGELOG.md
file for recording changes made between releases.
Before making a release you should ensure that all changes have been recorded in the CHANGELOG.
This is not done by directly editing the file but instead using the script ./log_change.sh
.
log_change creates change entry files in the directory ./unreleased_changes/
.
This prevents merge conflicts that would happen with multiple people editing the CHANGELOG file.
The following examples show you how to use the log_change script.
Commit and push all changes
Before releasing all local changes that you want in the release should be committed and pushed.
Commits that you want in a release should be merged down to a release branch, e.g. 7.0
or master
.
Once pushed and merged ensure that the branch passes the
CI build
.
Decide on the next version number
Stroom versioning follows Semantic Versioning .
Given a version number MAJOR.MINOR.PATCH:
- MAJOR is incremented when there are major or breaking changes.
- MINOR is incremented when functionality is added in a backwards compatible manner.
- PATCH is incremented when bugs are fixed.
Based on the changes since the last release establish if it is a major, minor or patch release to determine the next version number.
Performing a named release of Stroom
Once all the above pre-requisites have been met you can trigger the release by running this command:
This script will do the following:
- Adds the content of the unreleased change entry files (created by
log_change.sh
) to the CHANGELOG. - Prompts for (and suggests) the next version based on the previous release.
- Adds a new version heading to CHANGELOG.
- Adds/updates the version compare links in the CHANGELOG.
- Commits and pushes the change log changes.
- Creates an annotated git tag using the release version number and change entries.
The tagged git commit will trigger a CI build that includes additional release elements such as:
- Pushing the built docker images to DockerHub.
- Creating a release for the git tag in GitHub with all the release artefacts.
- Publishing any libraries to Sonatype and Maven Central.
Performing a named release of the docker stacks
Once the Stroom release build has finished and the artefacts are available on GitHub Releases and DockerHub you can create an associated release of the Stroom docker stacks.
In the following examples we will assume that you have just released Stroom v7.0.1
on branch 7.0
, and the previous release was v7.0.0
.
Checkout and pull the corresponding release branch in the stroom-resources repository.
Now edit the file bin/stack/container_versions.env
and edit the following line, setting it to the version of stroom you have just released:
STROOM_TAG="v7.0.0"
STROOM_TAG="v7.0.1"
If any of the other docker image versions need updating then do it at this point.
Now add/commit/push the change. Check the CI build is successful for the new Stroom image.
If the build is green then tag the stacks release as follows:
This script will build all the stack variants locally to ensure they will build successfully, though it does not test them. If the local build is successful it will then create an annotated git tag which will trigger a release CI build. The release CI build will create an archive for each stack variant and add them as a release artefacts.
SNAPSHOT releases
SNAPSHOT releases should not be released to Sonatype or Maven Central.
If a development version of a library needs to be shared between projects then you can either use the Gradle task publishToMavenLocal
to publish a SNAPSHOT
version to your local Maven repository and change your dependency version to SNAPSHOT
, or perform a named release along the lines of vx.y.z-alpha.n
.
Release Versioning conventions
Semantic versioning is used, and this should be adhered to, see SemVer . The following are examples of valid version names
SNAPSHOT
- Used only for local development, never to be published publicly.v3.3.0
- Initial release of v3.3, with an associated3.3
branch.v3.3.1
- A patch release to v3.3 on the3.3
branch.v3.4.0-alpha.1
- An alpha release of v3.4, either onmaster
or a3.4
branchv3.4.0-beta.1
- An beta release of v3.4, either onmaster
or a3.4
branch
To Perform a Local Build
2.6 - Setting up releases to Sonatype & Maven Central
Create a Sonatype account
You need to create an account on Sonatype and you will need to raise a jira ticket on Sonatype’s jira to get approved on the uk.gov.gchq group. This will require an existing user approved for the group to approve you on the ticket.
Setting up a GPG key
You can use the following commands for setting up a GPG2 key for signing.
Setting up the gradle build
The signing and release to Sonatype is done by various gradle plugins.
id "io.github.gradle-nexus.publish-plugin" version "1.0.0"
id "signing"
id "maven-publish"
See the root and event-logging-api gradle build files (in the event-logging repo) for an example of how to set up gradle.
The credentials can be passed to the gradle build using special gradle env vars Project Properties (external). The credentials required are:
ORG_GRADLE_PROJECT_SIGNINGKEY
- The key as produced by thegpg2 --armor
command.ORG_GRADLE_PROJECT_SIGNINGPASSWORD
- The password for the GPG key.ORG_GRADLE_PROJECT_SONATYPEUSERNAME
- The account username on Sonatype.ORG_GRADLE_PROJECT_SONATYPEPASSWORD
- The account password on Sonatype.
Setting up Github Actions
You will need to provide Github with the four secrets listed above by setting them as repository secrets at https://github.com/gchq/ORG_GRADLE_...
bit as the name.
So that the action can create the Github release you will also need to set up an SSH key pair and provide it with the public and private key. To generate the key pair do:
The key pair will be created in ~/.ssh/
.
Create a repo deploy key with the public key, named ‘Actions Deploy Key’ and with write access at https://github.com/
3 - Developing Content
TODO
Add content4 - Documenting Stroom
This site is built using Hugo with the Docsy Hugo theme. The content is pre-dominantly authored in Markdown with some Hugo shortcodes.
Useful external links
- Hugo static site generator.
- Docsy theme for Hugo.
- Commonmark Markdown cheat sheet and tutorial.
4.1 - Building the Documentation
Prerequisites
In order to build and contribute to the documentation you will need the following installed:
- bash
- Docker
- docker-buildx
Note
If you cannot or do not want to install Docker and buildx on your local machine see Developing Stroom-Docs on GitHub Codespaces below.
Docker or Docker Desktop is required as all the build steps are performed in docker containers to ensure a consistent and known build environment. It also ensures that the local build environment matches that used in GitHub actions.
docker-buildx
is a plugin for docker that allows caching of the docker images to speed up the build process.
This may be installed by your package manager when you install docker
or Docker Desktop, or you may need to install it separately.
You can confirm you have buildx
by executing the following command which should give you output similar to this:
It is possible to build the docs without docker but you would need to install all the other dependencies that are provided in the docker images, e.g. java, plantuml, puppeteer, hugo, npm, html2canvas, jspdf, graphviz etc.
It is assumed that you have a reasonable understanding of how to use Git and Github, specifically:
- Github
- Forks
- Pull requests
- Git
- Branching
- Pulling from upstream remotes
Cloning the stroom-docs git repository
The git repository for this site is stroom-docs (external link).
stroom-docs uses the Docsy theme (themes/docsy/
) via a Go module so the theme will be pulled in when Hugo is first run.
Unless you are a committer on the gchq/stroom-docs
repository, you will need to fork this repository into your own Github account.
You can then clone your fork of the repository like so (in this example it is assumed your Github username is jbloggs
):
Configuring the fork
You now need to configure the clone of your fork with details of the gchq/stroom-docs
upstream, which will allow you to pull changes from it.
Checking out the correct branch
There is a version of the documentation for each minor Stroom version (see Stroom Versions.
Before you start editing/viewing the documentation you need to be working from the correct branch of the Git repository.
If for example you are adding some content that is applicable to Stroom v7.0 then you need to checkout branch 7.0
.
Creating a feature branch
If you are making changes to the documentation then the recommended working practice is to always make changes on a feature branch.
A feature branch would typically contain all commits/changes relating to a single feature, e.g. the addition of a new section, or updating the documentation for a specific change in Stroom.
Having only these changes on a branch makes it easy to merge them into the release branch (e.g. 7.0
) or to just delete the branch if they are no longer needed.
A feature branch would typically be merged into the appropriate release branch by creating a pull request in GitHub.
Assuming you have checked out the desired release branch that you would like your changes to ultimately be merged into, do something like the following to create a feature branch (where add-properties-section
is the name of your branch):
This will create the named branch and check it out in one step.
Serving the site on a local server
To view the stroom-docs site in a browser you simply need to run:
This will execute the following steps:
Developing Stroom-Docs on GitHub Codespaces
If you cannot or do not want to install docker and buildx on your local machine but need to work on the documentation then you can do it from within GitHub Codespaces .
Note
Codespaces is a paid feature on GitHub, however it comes with 60hrs of free use per month so if you are only using it for stroom-docs development this should be ample.To develop Stroom-Docs with Codespaces do the following:
- Visit Stroom-Docs’ GitHub site at the desired version branch, e.g.
https://github.com/gchq/stroom-docs/tree/7.2
(or visit
https://github.com/gchq/stroom-docs
and switch branch using the branch/tag drop-down button).
Note
If you are developing on a fork then replacegchq
in the URL with your github username. - Click on the green Code drop-down button.
- On the Codespaces tab click on Create Codespace on
On first use of the Codespace it will take some time to do the initial setup of the development container. Subsequent uses of the Codespace will load more quickly. - It will open Visual Studio Code in the browser with a terminal pane at the bottom.
- In the terminal pane enter:
./serve_site.sh
This will run the Hugo development server and Codespaces should detect the open port. You should see something like: - Click Open in Browser and it will open a URL unique to your Codespace in the browser displaying the stroom-docs site. If this doesn’t appear then open the PORTS tab in VSCode and click the Open in Browser icon in the Forwarded Addresses column to open the served site in the browser.
Within the Codespace you can use all the git commands to pull/push/commit changes.
To stop the code space hit ctrl+shift+p
, enter stop
and then select Codespaces: Stop current Codespace.
Warning
When editing the documentation using Codespaces you need to manually refresh the browser tab with the served site. It does not auto-refresh like it does when running./serve-site.sh
on your local machine.
Additional commands
Converting the PlantUML files to SVG
stroom-docs makes used of
PlantUML
for a lot of its diagrams.
These are stored in the repository as .puml
text files.
In order that they can be rendered in the site they need to be converted into SVGs first.
Note
Docsy has the capability to render PlantUML content in fenced code blocks on the fly. This capability makes use of internet based servers to do the conversion therefore it is not suitable for this site as this site needs to available for deployment in environments with no internet access. All PlantUML content should authored in.puml
files and converted at build time.
To convert all .puml
files into sibling .puml.svg
files, run this from the repository root:
This command will find all .puml
files (in content/
and assets/
) and convert each one to SVG.
It only needs to be run on first clone of the repo or when .puml
files are added/changed.
The generated .puml.svg
files are ignored by git.
This command will be run as part of the GitHub Actions automated build.
Warning
If runInPumlDocker.sh SVG
is not run having added links to PlantUML images in the documentation, then when you build or serve the site you will see errors like this:
Error: Error building site: "/builder/shared/content/en/docs/user-guide/concepts/streams.md:57:1":
failed to render shortcode "image":
failed to process shortcode: "/builder/shared/layouts/shortcodes/image.html:54:21":
execute of template failed: template: shortcodes/image.html:54:21:
executing "shortcodes/image.html" at <$image.Name>: nil pointer evaluating resource.Resource.Name
Note
In the build docker containers your local stroom-docs repository is mounted into the container as/builder/shared/
, so if you see this path mentioned in the logs this is referring to your local repository.
Running a local Hugo server
The documentation can be built and served locally while developing it. To build and serve the site, run this from the repository root.
This uses Hugo to build the site in memory and then serve it from a local web server. When any source files are changed or added Hugo will detect this and rebuild the site as required, including automatically refreshing the browser page to update the rendered view.
Once the server is running the site is available at localhost:1313.
Warning
Sometimes changes made to the site source will not be re-loaded correctly so it may be necessary to stop and re-start the server.Building the site locally
To perform a full build of the static site, run this from the repository root:
This will generate all the static content and place it in public/
.
Generating the PDF
Every page has a Print entire section link that will display a printable view of that section and its children.
In addition to this the GitHub Actions we generate a PDF of the docs
section and all its children, i.e. all of the documentation (but not News/Releases or Community) in one PDF.
This makes the documentation available for offline use.
To test the PDF generation, run this from the repository root:
Updating the Docsy theme
The Docsy theme is a dependency of this Hugo site. See Update the Hugo Docsy Module for details on how to update the version of the Docsy theme.
In those instructions when it says to run a hugo
command you need to do it from within the hugo docker container.
This will give you a bash prompt inside the container that has the hugo
binary available.
The container has access to your local stroom-docs repository (from where you ran runInHugoDocker.sh
) and the initial directory is the root of the repository.
Inside the container the root of the repository is mounted as /builder/shared
.
To leave the container’s shell type exit
.
Alternatively you can run a single command directly, e.g. to update Docsy to 0.6.0
do:
4.2 - Managing Stroom Versions
The Docsy theme supports site versioning so that multiple versions of the site/documentation can exist and link between each other.
For this documentation site, each version of the site is tied to a minor release of Stroom, e.g. 7.0
, 7.1
, 7.2
, 8.0
etc.
Each Stroom version is represented by a git branch with the same name.
There is an additional git branch legacy
that is for all Stroom versions prior to 7.0
and will be removed once the versions prior to 7.0
are no longer supported.
Documentation changes for an as yet unreleased Stroom version would be performed on the master
branch which does not get published.
When it is ready for publishing then create a version branch from master
.
When the combined site is built, each version will exist within a directory as siblings of each other, i.e.
/ # Latest version content lives here (i.e. copy of v8.0)
/7.0/
/7.1/
/7.2/
/8.0/ # Latest version is also published here but only used by CI build.
/legacy/
The master
branch is NOT published to GitHub Pages or included in the release artefacts.
Versioned Site Configuration
To configure each version of the site so that it knows what version it is and what the other versions are you need to edit config.toml
.
This needs to be done on each branch in a way that is appropriate to each branch.
If a change needs to be applied to all branches then it is best to make it in the oldest branch for which the documentation is published, and then merge the changes the changes up the chain, e.g. legacy => 7.0 => 7.1 => 7.2 => 8.0 => master.
The following config properties needed to be amended on each branch. This example is from the 7.1 branch and is based on there being versions legacy, 7.0 and 7.1, with 7.1 being the latest.
[params]
# Menu title if your navbar has a versions selector
# to access old versions of your site.
version_menu = "Stroom Version (7.0)"
# If true, displays a banner on each page warning that
# it is an old version. Set this to true on each git branch
# of stroom-docs that is not the latest release branch
archived_version = true
# Used in the banner on each archived page.
# Must match the value in brackets in "version_menu" above
version = "7.0"
# A link to latest version of the docs. Used in the
# "version-banner" partial to point people to the main
# doc site. Ignored for the latest version
# Should be the same on all version branches.
url_latest_version = "/../"
# The version number of the latest version. Used in the
# "version-banner" partial to tell people what the latest
# version is. Ignored for the latest version
latest_version = "7.1"
# The name of the github branch that this version of the
# documentation lives on. Used for the github links in the
# top of the right hand sidebar. Should match the last part
# of url_latest_version.
github_branch = "7.0"
# A set of all the versions that are available.
[[params.versions]]
version = "7.1 (Latest)"
url = "/"
[[params.versions]]
version = "7.0"
url = "/../7.0"
[[params.versions]]
version = "Legacy"
url = "/../legacy"
[params]
# Menu title if your navbar has a versions selector
# to access old versions of your site.
version_menu = "Stroom Version (7.1)"
# If true, displays a banner on each page warning that
# it is an old version. Set this to true on each git branch
# of stroom-docs that is not the latest release branch
archived_version = false
# Used in the banner on each archived page.
# Must match the value in brackets in "version_menu" above
version = "7.1"
# A link to latest version of the docs. Used in the
# "version-banner" partial to point people to the main
# doc site. Ignored for the latest version
url_latest_version = "/../"
# The version number of the latest version. Used in the
# "version-banner" partial to tell people what the latest
# version is. Ignored for the latest version
latest_version = "7.1"
# The name of the github branch that this version of the
# documentation lives on. Used for the github links in the
# top of the right hand sidebar. Should match the last part
# of url_latest_version.
github_branch = "7.1"
# A set of all the versions that are available.
[[params.versions]]
version = "7.1 (Latest)"
url = "/"
[[params.versions]]
version = "7.0"
url = "/../7.0"
[[params.versions]]
version = "Legacy"
url = "/../legacy"
params.versions
Setting the params.versions
values is somewhat confusing.
The url
property will result in a relative href
in the built site that is relative to the site root for that version.
The following is the built HTML for v7.1 which is the latest.
<a class="dropdown-item" href="./">7.1 (Latest)</a> <!-- 7.1 is located at the site root -->
<a class="dropdown-item" href="./7.0">7.0</a> <!-- 7.0 is located in the 7.0 sub-directory of the site root -->
<a class="dropdown-item" href="./legacy">Legacy</a>
The following shows how params.versions
are set in each version branch, assuming that 7.1 is the latest version.
# Versioned root is /legacy
# Latest is parent
# Other versions are siblings
[[params.versions]]
version = "7.1 (Latest)"
url = "/../"
[[params.versions]]
version = "7.0"
url = "/../7.0"
[[params.versions]]
version = "Legacy"
url = "/"
# Versioned root is /7.0
# Latest is parent
# Other versions are siblings
[[params.versions]]
version = "7.1 (Latest)"
url = "/../"
[[params.versions]]
version = "7.0"
url = "/"
[[params.versions]]
version = "Legacy"
url = "/../legacy"
# Versioned root is /
# Latest is site root
# Other versions are children
[[params.versions]]
version = "7.1 (Latest)"
url = "/"
[[params.versions]]
version = "7.0"
url = "/7.0"
[[params.versions]]
version = "Legacy"
url = "/legacy"
Automated build process
On every commit Github Actions will build the version of the site that the commit is on to ensure that Hugo can convert the content into a static site.
It will also build all the other versioned branches to check that they work.
On a nightly basis, Github Actions will also run a scheduled build on the HEAD commit of the master
branch.
In addition to building each version of the site, it will establish if the combined site needs to be published.
It will determine this by comparing the commit hashes of each version branch with the contents of a commit.sha1
file that is published in each of the version directories on https://gchq.github.io/stroom-docs.
If any one of the hashes is different then the combined site will be assembled and published.
This automated build will look for any branches matching the pattern (legacy|[0-9]+\.[0-9]+)
and for each one will do the following:
- Checkout that branch
- Build the site for that version using Hugo
- Add the site files to a combined site
- Generate the documenation PDF
- Build the site with no other versions configured
- Create a zip of the single version site
Once each site has been processed it will:
- Copy the latest version of the site to the root of the combined site
- Create a single zip file containing the combined site
- Tag the release with a version number
- Add the following release artefacts:
- Single version site zips
- Combined site zip
- Single version PDFs
- Publish the combined site to GitHub Pages https://gchq.github.io/stroom-docs .
Although the build is run on the master
branch it will use the HEAD
commit of each of the release branches to build the site(s).
The build and release can be forced by adding the text [publish]
to the commit message on master
.
This is useful in testing, or if updated documentation is needed for any reason.
For example you can run this on the master
branch to for:
Merging changes
When you make changes to one of the version branches (7.0
, 7.1
, etc.), either directly or with a pull request from a feature branch, you will need to merge the changes up through each of the versions until they reach master
.
Merging up through multiple branches is tedious when done manually so you can use the merge_up.sh
script in the root of this repo.
You can either run it without any arguments to merge from legacy
all the way up to master
with all branches in between.
Alternatively you can supply the name of the branch to start from, e.g. ./merge_up.sh 7.0
, which will save it doing a pointless merge up from older branches that have not changed.
When you run it, it will tell you the merge path and get you to confirm.
If there are no merge conflicts then it will perform all the merges and return you to your current branch.
If there are conflicts at any stage then it will stop at that point.
You will then need to fix the conflicts and commit the merge.
You can then run merge_up.sh
again to do the rest of the merges.
Where to make changes
The nature of a change to the site/documentation will determine which git branch the change is made on.
Changes specific to a Stroom version
Any changes that are specific to a Stroom version, e.g. documenting a new feature in that version should be made on the oldest branch that contains that feature.
If the change relates to an as yet unreleased version of Stroom then make the change on master
.
Changes to the News/Releases
Adding news items or release notes for new versions should be done on the latest release branch. The News/Releases section is not included in old versions when released.
Changing the site look
Ideally changes to the look of the site, e.g. upgrading the Docsy theme sub-module to a new commit, adding shortcodes or tweaking the CSS should be done on all branches so when switching between branches the look doesn’t change.
This means this sort of change should be done on the oldest published version branch and then merged up the chain to the others, e.g. legacy
=> 7.0
=> 7.1
=> master
.
In some cases a change to the look may require significant refactoring of the content, e.g. changes to a shortcode. In the event of this it may be necessary to only make the change on the latest release branch and for different versions to have a slightly different look. The decision on how best to tackle these situations will have to be on a case by case basis.
Changing the GitHub Actions build process
If the change impacts the building of a single version then it needs to be done on the oldest version and merge up.
If the change only impacts the preparation of release artefacts then it can be performed on the master
branch.
Adding a new version branch
The change to config.toml
needs to be done on all version branches.
Unfortunately you cannot just add the new [[params.versions]]
block into legacy
and merge up as each version branch will need editing so the url
values are applicable to version branch being edited, see above.
Building a mock multi-version site
To make it easier to test how the combined site will look with multiple versions the following script can be run to mock up a multi-version site. It does the following:
- Copies the content of the local repository.
- Amends the config file to set appropriate versions.
- Builds the site for that version.
- Copies the built site into a sub-directory matching the version in
/tmp/stroom-docs_mock_combined_site/
.
To run this script do:
create_mock_combined_site.sh
The combined site can be served using something like the Python simple HTTP server, e.g.
cd /tmp/stroom-docs_mock_combined_site
python -m SimpleHTTPServer 8888
Then open a browser at localhost:8888.
As each version of the site is a copy of the same thing the content will be all the same but it allows you to test the version drop down and archived banner.
4.3 - Documentation Style Guide
Overview
Stroom’s documentation is created using the static site generator Hugo . This converts markdown content into a rich HTML site. The markdown content in stroom-docs is not intended to be read as-is in GitHub, it needs to be rendered first.
The full documentation for Hugo can be found here . The site also uses the Docsy theme for Hugo. The documentation for Docsy can be found here . The Docsy theme provides a lot of the styling but also adds other features and shortcodes. You should consult the Docsy documentation in the first instance.
To maintain a degree of consistency in the documentation you should use this section as a reference for how to layout your content.
Shortcodes
The documentation makes heavy use of Hugo shortcodes for adding page elements such as links, icons, images, etc. Shortcodes are a compact way of inserting reusable content into a page and make it easy to change how a page element is styled by just changing the shortcode in one place.
There are numerous shortcodes available to use:
- Hugo built in shortcodes
- Docsy theme shortcodes
- Bespoke stroom-docs shortcodes.
These can be found in
layouts/shortcodes/
.
An example of using a short code in your markdown is:
Click the {{< stroom-icon "save.svg" "Save Document" >}} icon.
This calls the shortcode stroom-icon with the positional arguments save.svg
and Save Document
.
Shortcodes can either use positional arguments or named arguments depending on how they have been written.
This is an example of calling a shortcode with named arguments:
Click the {{< stroom-icon name="settings.svg" colour="red" >}} icon.
Check the documentation for specific shortcode to see how to call it.
Editor snippets and shortcodes
To make your life much easier when editing the documentation it is highly recommended to use a text editor that supports text snippets. Snippets make it very quick to add shortcodes into the documentation.
For example the following UltiSnips (for Vim) and VS Code snippets adds a skeleton front matter to a page.
snippet hfront "Hugo markdown metadata front matter" b
---
title: "${1:Title}"
linkTitle: "$1"
#weight:
date: `date "+%Y-%m-%d"`
tags: $2
description: >
$3
---
$0
endsnippet
{
"hugo-front-matter": {
"prefix": "hfront",
"body": [
"---",
"title: \"${1:Title}\"",
"linkTitle: \"$1\"",
"#weight:",
"date: `date \"+%Y-%m-%d\"`",
"tags: $2",
"description: >",
" $3",
"---",
"",
"$0"
],
"description": "Hugo markdown metadata front matter"
}
}
TODO
Add section on naming, i.e. what names we use for things, e.g. data/meta/stream, config/properties, job/task, etc.4.3.1 - Site Structure
File names
Ideally files and directories should be named using lower-kebab-case, e.g. site-structure.md
.
Directory structure
All page content, i.e. markdown, is located underneath content/en
.
This directory has one sub-directory for each of the top nav bar items.
Stroom-Docs top level sections
Each of the following sections can have a different styling that is appropriate to its content, e.g. documentation vs blog.
Landing Page
The landing page is located at content/en/_index.html
.
This is the page that users will initially see, unless visiting via a direct link.
About (about
)
A single page describing what stroom is.
Documentation (docs
)
This is where all the documentation for installing, administering and using stroom is located.
News/Releases (news
)
This is a blog
type section that contains a page for each new Stroom release and a set of blog posts for Stroom news items.
The pages in the two sub-sections (news
and releases
) are displayed in chronalogical order based on the date
key in the page’s front matter.
News (news/news
)
This sub section has a flat structure with one .md
file per news item.
Each file should be named in the form YYYYMMDD-<name>.md
.
The date
key should be set in the front matter to match the date of the file.
Hugo will use this date
key to order the files in the menu.
The date should be set in ISO 8601 date format, i.e.
date: 2021-07-09
Releases (news/releases
)
Each new minor version release of Stroom should have a file in this directory.
They should be named in the form vXX.YY.md
where XX
is the zero padded major version and YY
is the zero padded minor version, e.g. v07.01
.
The zero padding is to ensure correct ordering by default withouth having to resort to using weight
in the front matter.
The front matter should be set along these lines:
---
title: "Version 7.0"
linkTitle: "7.0"
date: 2021-07-07
description: >
Key new features and changes present in v7.0 of Stroom and Stroom-Proxy.
---
Community (community
)
This section provides information for people wanting to contribute to the development of Stroom and its peripheral repositories.
This can include developer documentation for building and developing Stroom.
This has the same structure as docs
.
Documentation content
The docs
and community
top level sections have a tree structure for their content.
Each of these directories will contain three different types of entities:
- Section directories
- Section index files (
_index.md
) - Pages (e.g.
building.md
)
The following is an example of part of the structure of the community
section.
├── documentation/ Documentation section directory
│ ├── building.md Page
│ ├── _index.md Documentation section index page
│ ├── style-guide/ Style guide section directory
│ │ ├── basic-elements.md Page
│ │ ├── icon-gallery.md Page
│ │ ├── _index.md Style guide section index page
│ │ ├── site-structure.md Page
│ │ └── using-images.md Page
│ └── versions.md Page
└── roadmap.md Page
A section can essentially contain branches (sections) and leaves (pages).
A branch (i.e. a section) is defined by a directory that contains an _index.md
file.
The front matter in this index file defines the meta data for that section, e.g. the title, date, tags, description, etc.
A leaf (i.e. a page with no children) is just a markdown file with front matter.
The front matter for branches and leaves works in the same way.
How do I…?
Add a child page
If you already have a section that you want to add a new child page to then you will already have a structure like this:
└── my-section/
├── _index.md
├── a-page.md
└── another-page.md
To add a new page simple create a .md
file for the new page in the section directory, e.g.
└── my-section/
├── _index.md
├── a-page.md
├── another-page.md
└── new-page.md
Add the front matter to the top of the new page file. e.g.
---
title: "My Long Wordy Title"
linkTitle: "My Short Title"
weight: 20
date: 2022-01-27
tags:
description: >
A new page describing stuff.
---
The new page should now appear in the list of child pages on the section page and in the left hand navigation pane.
If you want to control the position of the new page relative to its siblings then adjust the weight of this page and that of its siblings to get the order that you want.
Add a new section
If you want to add a sub-section to an existin section then you will already have a structure like this:
└── my-section/
├── _index.md
├── a-page.md
└── another-page.md
To add a new sub-section create a sub-directory within the existing directory (with a name that roughly matches the section name) and create an _index.md
file within it, e.g.
└── my-section/
├── my-new-sub-section/
│ └── _index.md
├── _index.md
├── a-page.md
└── another-page.md
In the _index.md
file add front matter to the top, e.g.
---
title: "My Long Wordy Section Title"
linkTitle: "My Short Section Title"
weight: 20
date: 2022-01-27
tags:
description: >
A new section for stuff.
---
As with pages, adjust the weight of the section and its siblings to get the order you require.
To add pages to this new section see Add a new child page above.
If you are not sure if you need to add a whole new sub-section or just a child page you can just add a new sub-section and add content to the _index.md
file as if it were a simple page.
If you later realise that you need child pages then move the content out into a child page and create other sibling pages to it.
4.3.2 - Front Matter
Note
See Hugo Front Matter for the full list of metadata keys that can be set.Front matter in Hugo is a set of meta data at the top of each page that controls which menus include the page as well as providing information about the page, e.g.
---
title: "Site Structure"
linkTitle: "Site Structure"
weight: 10
date: 2021-07-20
tags:
- style
- TODO
description: >
Describes the file and directory structure for the site.
---
Hugo supports front matter in YAML, JSON and TOML, however for consistency all front matter in stroom-docs should be in YAML format.
Title and link title
This is the section/page title and will become the h1
heading (in HTML/Markdown terms) on the section/page.
The linkTitle
is the text that is displayed in the left hand navigation sidebar.
It should be the same as title
unless the title is quite long, in which case a shorter version should be used so it fits in the sidebar.
Weight
The weight controls the position of the page/section within the other pages/sections of its parent.
i.e. it controls the order of the pages/sections in the left hand navigation bar and the list of child items on a section index.
If no weight is provided then Hugo will use date
, then linkTitle
, then the file path.
To assist with re-ordering pages you can use the script change_weights.sh
in the root of the repo.
E.g. to change the order of the child items of the user-guide section do the following:
./change_weight.sh content/en/docs/user-guide
Date
The date should be set/updated to the current date when a page/section is created or modified. This data is show at the bottom of the page and tells the reader when the page was last updated.
Tags
In the front matter, tags
is a list of tags that are applicable to the document and allow documents to be searched for by tag.
Tag names should conform to the following conventions:
- Lower kebab case, i.e.
reference-data
, even for abbreviations. - The only exception to the case rule is
TODO
, which is always upper case. - Singular, i.e.
pipeline
rather thanpipelines
.
Avoid using too many unique tag names as it will make the list of tags in the sidebar to large to be useful. When setting a tag on a document consult the list of existing tags to ensure consistency and to see if a more applicable tag already exists.
Add the TODO
tag to a page when the page is incomplete.
This makes it easy to find areas of the documentation that are in need of attention.
Cascading tags
If you want to apply a tag to all descendant pages of a section you can add this to the front matter of the section:
cascade:
tags:
- install
This will then apply all of tags added to tags
to each descendant page.
Description
A short description of what the page/section covers. This will be shown on the index page of its parent.
4.3.3 - Markdown Style Conventions
Line breaks
Sentence per line
Each sentence must start on a new line, even in numbered/bulleted lists. This makes it easier to move sentences around or to remove them and limits the scope of changes when it comes to git diffs and merges. When the markdown is rendered into HTML/PDF, the sentences will be joined into a single paragraph.
See this site for more of the reasons behind sentence per line. Though this link relates to Asciidoc, the same logic applies to markdown.
For example:
This is the first sentence of the paragraph.
This is the second.
This it the third and final one.
This is the start of a new paragraph.
Which renders as:
This is the first sentence of the paragraph. This is the second. This it the third and final one.
This is the start of a new paragraph.
This is the first sentence of the paragraph. This is the second. This it the third and final one.
This is the start of a new paragraph.
Which renders as:
This is the first sentence of the paragraph. This is the second. This it the third and final one.
This is the start of a new paragraph.
No hard line breaks.
Long lines should not be hard wrapped by adding line breaks. You should instead rely on your editor to soft wrap long lines that cannot fit on the visible screen area. The process of hard wrapping long lines will vary from editor to editor and not all editors support re-wrapping lines after the content has changed. It also relies on each person’s editor being configured to the same wrap column. Adding hard wraps also means a slight change at the start of a paragraph will potentially cause all subsequent lines to be re-wrapped and thus appear as a substantial difference in the commit.
## Don't do this
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.
## Do this instead
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Forced line breaks
In some circumstances, e.g. a list of items that is not bulleted, you may want to prevent the joining of adjacent lines when rendered.
You can force a line break by adding two spaces ␣␣
at the end of a line.
Paragraph 1.
One␣␣
Two␣␣
Three
Paragraph 2.
Which renders as:
Paragraph 1.
One
Two
Three
Paragraph 2.
Paragraph 1.
One
Two
Three
Paragraph 2.
Which renders as:
Paragraph 1.
One Two Three
Paragraph 2.
Blank lines and spacing
- A heading line should be preceded by two blank lines and followed by one blank line. This makes the headings clearer in the markdown source. The only exception to this is when one heading come immediately after its parent heading with no text in between.
- A fenced code block should be surrounded by one blank line.
- Paragraphs should be separated by one blank line.
- Bulleted and numbered lists should be surrounded by one blank line.
- Additional sentences in bulleted/numbered lists should be indented for clarity in the raw markdown.
e.g:
The text belonging to the previous heading.
## A Heading
## A sub heading
The text of this heading.
A second sentence in this paragraph.
A new paragraph.
A second sentence in this paragraph.
Here are some bullets:
* Bullet Z.
* Bullet A.
This is an additional sentence for this bullet point.
And so is this.
* Sub-bullet AX.
This is an additional sentence for this bullet point.
And so is this.
* Bullet F.
Here are some numbered steps:
1. Step 1.
1. Step 2.
1. Step 3.
Another random line.
## Another Heading
Headings
The page title uses heading level one (#
in markdown) so all markdown headings should be >= 2 (##
, ###
, ####
, etc.).
Headings should have two blank lines above them for clarity in the raw markdown.
The #
characters should always be followed by one space character
The following is an example of the heading levels.
# Heading level 1
DON'T use this level in your documents.
Level one headings will be generated from the `title` in the document's front matter.
## Heading level 2
This heading level is effectively level 1 on the page and right hand pane, e.g. `1`.
### Heading level 3
This heading level is effectively level 2 on the page and right hand pane, e.g. `1.1`.
#### Heading level 4
This heading level is effectively level 3 on the page and right hand pane, e.g. `1.1.1`.
##### Heading level 5
This heading level is effectively level 4 on the page but not shown on the right hand pane.
###### Heading level 6
This heading level is effectively level 5 on the page but not shown on the right hand pane.
Markdown supports an alternate style for headings, as shown below. Don’t use this style as it is not clear from the symbols what the heading level is.
Heading level 1
===============
Don't use this style.
Heading level 2
---------------
Don't use this style.
Table of contents
The page table of contents (right hand pane) is controlled by this in config.toml
.
[markup]
[markup.tableOfContents]
endLevel = 4
ordered = false
startLevel = 2
The maximum depth of the table of contents can be controlled with endLevel
.
Heading example (level 2)
This is an example of a level 2 heading.
Heading example (level 3)
This is an example of a level 3 heading.
Heading example (level 4)
This is an example of a level 4 heading.
Heading example (level 5)
This is an example of a level 5 heading.
Heading example (level 6)
This is an example of a level 6 heading.
Block quotes
Single line
A simple paragraph block quote.
> This is a simple block quote.
> This is the second sentence on the same line.
This is a simple block quote. This is the second sentence on the same line.
Multi line
A pair of spaces at the end of a line can be used to force line breaks, e.g.:
> This is a multi line block quote.␣␣
> This is the second line.␣␣
> This is the third line.
This is a multi line block quote.
This is the second line.
This is the third line.
Lists
Bulleted list
- Fruit. Make sure you get your five-a-day.
- Meat
- Beef
- Chicken
- Vegetables.
* Fruit.
Make sure you get your five-a-day.
* Meat
* Beef
* Chicken
* Vegetables.
Numbered List
Numbered list items should all be numbered with number 1
so that the markdown render handles the consecutive numbering.
This makes the file easier to edit and means the addition of one item in the middle does not cause a change to all the lines after it, e.g:
- Item one. This is some extra content for step 1.
- Item two.
- Sub-item A.
- Sub-item B.
- Item three.
1. Item one.
This is some extra content for step 1.
1. Item two.
1. Sub-item A.
1. Sub-item B.
1. Item three.
Check List
- Item 1. This is some extra content for item 1.
- Item 2.
- Item 2a.
- Item 2b.
- Item 3.
* [ ] Item 1.
This is some extra content for item 1.
* [ ] Item 2.
* [x] Item 2a.
* [ ] Item 2b.
* [x] Item 3.
Definition list
- Name
- Godzilla
- Birthplace
- Japan
- Color
- Green
Name
: Godzilla
Birthplace
: Japan
Color
: Green
Tables
Tables should ideally have its columns aligned in the markdown for clarity in the raw markdown.
## Ideally do this
| Artist | Album | Year |
|-----------------|----------------|------|
| Michael Jackson | Thriller | 1982 |
| Prince | Purple Rain | 1984 |
| Beastie Boys | License to Ill | 1986 |
## Or this
Artist | Album | Year
----------------|----------------|-----
Michael Jackson | Thriller | 1982
Prince | Purple Rain | 1984
Beastie Boys | License to Ill | 1986
## But this is acceptable
| Artist | Album | Year |
|-|-|-|
| Michael Jackson | Thriller | 1982 |
| Prince | Purple Rain | 1984 |
| Beastie Boys | License to Ill | 1986 |
All will produce the same result, however, the latter can be harder to read in markdown form. The first two are harder to create and update in markdown form.
Artist | Album | Year |
---|---|---|
Michael Jackson | Thriller | 1982 |
Prince | Purple Rain | 1984 |
Beastie Boys | License to Ill | 1986 |
If you are editing the documentation with Vim then the plugin
tabular
is very useful for auto aligning markdown tables.
Simply position the cursor somewhere in the table and do :Tabularize\|
to tabularize on the |
character.
Line breaks in cells
If you need a line break in a table cell then use <br>
.
Comments
As the Markdown content is processed by Hugo and is not intended to be read in its raw Markdown form it means it is possible to include comments in the content. This can be useful when you want to leave development comments in the content that are not for display in the rendered site. Comments are done with the HTML comment syntax, i.e.
<!-- This is a comment -->
<!--
This is a
mult-line comment
-->
4.3.4 - Additional Page Elements
Links
While links can be added using standard markdown link syntax you should use Hugo shortcodes to add them. The advantage of the shortcode is that Hugo will check for broken links when building the site.
External links
As this site is deployed to environments with no internet connect and is also released in PDF form it is important that any links to locations outside of the this site (i.e. on the internet) are clearly marked. To include an external link do the following:
-
This is a link to Stroom on Github with a title.
This is a link to {{< external-link "Stroom on Github" "https://github.com/gchq/stroom" >}} with a title.
-
This is the same link with no title, https://github.com/gchq/stroom .
This is the same link with no title, {{< external-link "https://github.com/gchq/stroom" >}}.
Versioned URLs
Some external links are to other Stroom URLs are versioned.
If you need to link to a site external to this one that has the Stroom version in the URL then you can use the tag @@VERSION@@
in the URL.
This will be translated into the Stroom version of this site, as seen in the Stroom Version (…) drop down at the top of the page.
This saves you from having to update the URL on each release of Stroom.
-
This is a versioned URL https://gchq.github.io/stroom/v7.4
This is a versioned URL {{< external-link "https://gchq.github.io/stroom/v@@VERSION@@" >}}
Warning
This will not work for versionlegacy
as that is not an actual Stroom version.
Anchors
You can link to headings on a page using its anchor. The anchor for a heading is the heading text with:
- All non-alphanumeric characters removed
- Spaces replaced with a
-
- All characters made lower case
- Multiple consecutive
-
characters, e.g.---
are replaced with a single-
For example the heading Mr O'Neil's 1st Event (something)
becomes as an anchor #mr-oneils-1st-event-something
.
See The link examples below that use anchors.
Duplicate anchors
If you have two headings on the same page then Hugo will suffix the anchors with a sequential number to ensure uniqueness of the anchor. For example, with the following markdown:
## Apples
### Example
## Oranges
### Example
Hugo will create the following anchors:
apples
example
oranges
example-1
If you want to avoid confusion and removed the risk of anchors breaking if new headings are added in the middle, then you can explicitly name anchors:
## Apples
### Example {#apples-example}
## Oranges
### Example {#oranges-example}
This is only worth doing if you want to link to these heading.
Shortcode internal page link examples
Shortcode links are slightly more verbose to type but are preferable to markdown style links as the link target will be checked at site build time so you know all the links are correct.
Hugo has ref
and relref
link shortcodes.
Use only relref
as this will be translated into a relative path when the site it built ensuring that the site can be run from any base path.
The following are some example of different links to internal content.
Heading anchor
-
A link to a heading anchor on this page.
[link]({{< relref "#alerts" >}})
Absolute path
-
A link to a heading anchor on another page, using an absolute path.
[link]({{< relref "community/documentation/style-guide/using-images#captions" >}})
Relative path
-
A link to a heading anchor on page above this one, using a relative path.
[link]({{< relref "../versions" >}})
Unique page name
-
A link to a heading anchor on another page, using only the unique page name. This is quicker to type and won’t break if pages are moved but will not work if the page name is not unique.
[link]({{< relref "running#basic-configuration" >}})
Section link
-
A link to a branch/section in the document tree, i.e. to the
\_index.md
.[link]({{< relref "docs/HOWTOs" >}})
Next page in section link
-
A link to the next page in the current section. If the current page is the last page in the section then no link will be displayed. What the next page is is defined by the page weights or the default ordering of pages in the section.
This is useful when you have a set of pages in a section that have a natural flow, e.g. where the pages in a section are the sequential steps in an installation guide.
The link looks like this(with the page title in the link text and the hover tip showing both the page title and the description):
Next page - Images{{< next-page >}}
Previous page in section link
-
A link to the previous page in the current section. If the current page is the last page in the section then no link will be displayed. What the previous page is is defined by the page weights or the default ordering of pages in the section.
This is useful when you have a set of pages in a section that have a natural flow, e.g. where the pages in a section are the sequential steps in an installation guide.
The link looks like this(with the page title in the link text and the hover tip showing both the page title and the description):
Previous page - Markdown Style Conventions{{< prev-page >}}
Markdown page link examples
Warning
Don’t use markdown style links for internal page links as they can’t be verified at site build time like the short code links can.Markdown style links should not contain the .md
extension as this will be stripped when the site is generated, e.g. for the following content:
/content
/en
/docs
/section-x
/sub-section-a
_index.md
page1.md
page2.md
/sub-section-b
_index.md
page1.md
page2.md
This will become:
/docs
/section-x
/sub-section-a
/page1
/page2
/sub-section-b
/page1
/page2
in the rendered site.
-
A link to a heading anchor on this page.
[link](#alerts)
-
A link to a heading anchor on another page, using a relative link.
[link](../using-images#captions)
-
A link to a heading anchor on another page, using an absolute link.
[link](/docs/style-guide/using-images#captions)
Download file links
You can create a link to download a file, like these:
-
Download a file .
-
Download mock_stroom_data.csv
{{< file-link "quick-start-guide/mock_stroom_data.csv" >}}Link Title{{< /file-link >}}
{{< file-link "quick-start-guide/mock_stroom_data.csv" />}}
All paths are relative to /assets/files/
.
Glossary links
If you need to create a link to an item in the Glossary you can use the glossary
shortcode.
E.g.
-
A feed is something you should know about, and so are streams .
A {{< glossary "feed" >}} is something you should know about, and so are {{< glossary "stream" "streams" >}}.
The argument to the shortcode is the glossary term. This should match the heading text on the Glossary page exactly, ignoring case. It will be converted to an HTML anchor so that you can link directly to the heading for the term in question.
Code
Inline code
Inline code looks like this
.
Inline code `looks like this`.
Code blocks (simple)
Code blocks should be surrounded with fences ```language-type
and ```
with the language type always specified to ensure correct syntax highlighting.
If the language type is not supplied then styling will be different to fenced blocks with a language.
This is a markdown example of a fenced code block containing XML content.
<root>
<child attr="xxx">some val</child>
</root>
```xml
<root>
<child attr="xxx">some val</child>
</root>
```
Note
The fenced code block MUST have a language specified. This ensures the correct default styling is used and makes it explicitly clear to anyone editing the markdown what the content of the block is. If the content of the fenced block has no supported language or is just plain text then use languagetext
.
The following are some example of rendered code blocks:
id,date,time
1,6/2/2018,10:18
2,12/6/2017,5:58
3,6/7/2018,11:58
---
root:
someKey: "value"
<root>
<child attr="xxx">
some val
</child>
</root>
echo "${VAR}"
code blocks (advanced)
If you need to show line numbers or to highlight sections of a code block then you can use the code-block
shortcode.
This shortcode takes the following named arguments:
- language - The language for syntax highlighting.
Defaults to
text
. - lines - Whether to display line numbers or not (
true
|false
). Defaults totrue
. - highlight - A comma separate list of lines to highlight.
Ranges of line numbers can be specified, e.g.
2-8,13,25-30
. Defaults to no line highlighting. - start - The line number to start at. Defaults to 1.
The following is an example of how to use the shortcode.
{{< code-block language="xml" highlight="2-5,8" >}}
<root>
<child attr="xxx">
some val
</child>
<child attr="xxx">
some val
</child>
<child attr="xxx">
some val
</child>
</root>
{{< /code-block >}}
Default behaviour
{{< code-block >}}
...
{{< /code-block >}}
With line numbers, a language and a starting line number
{{< code-block language="xml" start="5" >}}
...
{{< /code-block >}}
With line numbers, a language and highlighted lines
{{< code-block language="xml" highlight="2-5,8" >}}
...
{{< /code-block >}}
With a language and highlighted lines, but without line numbers
{{< code-block language="xml" lines="false" highlight="2-5,8" >}}
...
{{< /code-block >}}
Command line blocks
To demonstrate commands being run on the command line you can use the command-line
shortcode.
This results in a code block with the shell prompt displayed on the left of each line.
It also means the prompt part is not selectable when the user selects the text for copy/pasting.
The shortcode takes the following positional arguments:
- username - The username to appear in the prompt, defaults to
user
. - hostname - The hostname to appear in the prompt, defaults to
localhost
. - language - The language of the content (a valid and installed prism language name language name), defaults to
bash
.
If you want to display shell output then prefix each output line with (out)
.
It will then be displayed without a prompt.
To display a blank line with no prompt then have a line with just (out)
in it.
If your shell command is very long then you can split it into multiple lines using the shell line continuation character \
which must be the last character on the line.
If this character is present then it will be rendered with a different prompt to indicate it is a continuation.
Readers can then copy/past the muli-line command into a shell and run it.
{{< command-line "david" "wopr" >}}
echo hello \
world
(out)hello world
id
(out)uid=1000(david) gid=1000(david)
{{</ command-line >}}
MySQL shell blocks
To demonstrate commands being run in a MySQL shell you can use the sql-shell
shortcode.
This works in a similar way to the command-line
shortcode but has a different prompt and no shortcode arguments.
If you want to display shell output then prefix each output line with (out)
.
It will then be displayed without a prompt.
If your sql statement is multi-line, prefix all lines except the first with (con)
(for continuation).
Continuation lines will be rendered with a continuation prompt (->
).
To display a blank line with no prompt then have a line with just (out)
in it.
{{< sql-shell >}}
select *
(con)from token_type
(con)limit 2;
(con)+----+------+
(con)| id | type |
(con)+----+------+
(con)| 1 | user |
(con)| 2 | api |
(con)+----+------+
(out)2 rows in set (0.00 sec)
(out)
select database();
(out)+------------+
(out)| database() |
(out)+------------+
(out)| stroom |
(out)+------------+
(out)1 row in set (0.00 sec)
{{</ sql-shell >}}
Inline files
Some code or text examples may be too large for a fenced block so you can put the content in a separate file and include it in-line like so.
<?xml version="1.1" encoding="UTF-8"?>
<dataSplitter
xmlns="data-splitter:3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="data-splitter:3 file://data-splitter-v3.0.1.xsd"
version="3.0">
<!--
GEOHOST REFERENCE FEED:
CHANGE HISTORY
v1.0.0 - 2020-02-09 John Doe
This is a reference feed for device Logical and Geographic data.
The feed provides for each device
* the device FQDN
* the device IP Address
* the device Country location (using ISO 3166-1 alpha-3 codes)
* the device Site location
* the device Building location
* the device Room location
*the device TimeZone location (both standard then daylight timezone offsets from UTC)
The data is a TAB delimited file with the first line providing headings.
Example data:
FQDN IPAddress Country Site Building Room TimeZones
stroomnode00.strmdev00.org 192.168.2.245 GBR Bristol-S00 GZero R00 +00:00/+01:00
stroomnode01.strmdev01.org 192.168.3.117 AUS Sydney-S04 R6 5-134 +10:00/+11:00
host01.company4.org 192.168.4.220 USA LosAngeles-S19 ILM C5-54-2 -08:00/-07:00
-->
<!-- Match the heading line - split on newline and match a maximum of one line -->
<split delimiter="\n" maxMatch="1">
<!-- Store each heading and note we split fields on the TAB (	) character -->
<group>
<split delimiter="	">
<var id="heading"/>
</split>
</group>
</split>
!-- Match all other data lines - splitting on newline -->
<split delimiter="\n">
<group>
<!-- Store each field using the column heading number for each column ($heading$1) and note we split fields on the TAB (	) character -->
<split delimiter="	">
<data name="$heading$1" value="$1"/>
</split>
</group>
</split>
</dataSplitter>
The card has a maximum height and will show scrollbars as required.
Examples of how to use in-line files are:
{{< textfile "style-guide/in_line_file_example.xml" "xml" >}}My caption{{< /textfile >}}
{{< textfile "style-guide/in_line_file_example.xml" >}}My caption{{< /textfile >}}
{{< textfile "style-guide/in_line_file_example.xml" />}}
Supported languages
This site uses
Prismjs
for syntax highlighing code blocks.
PrismJs supports a large number of different languages however only certain languages have been included with this site.
The language specified in the markdown code fence or in the command-line
shortcode must be in the list of included languages.
The list of included language names are:
sh
bash
css
csv
groovy
http
java
javascript
jq
json
python
regex
scss
sql
text
toml
xml
yaml
To include extra languages in this site you need to build a new version of the prism.js
and prism.css
files.
This can be done
here
.
When creating new versions of these file you must include the languages and plugins already included else you may break this site.
The generated files are then copied over the top of /static/css/prism.css
and /static/js/prism.js
.
Both files include a comment at the top with the link to the PrismJs download page with the currently included items selected.
Use this link then add any additional items, bearing in mind the size of the download and its impact on page load times.
An example of the download link is https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+csv+groovy+java+jq+json+markdown+python+regex+scss+sql+toml+yaml&plugins=line-highlight+line-numbers+command-line+toolbar+copy-to-clipboard+treeview */
Warning
The css/js downloaded from the Prism site is taken from the head of their master branch so even though the css/js mention a Prism version number this may be the same for downloads done at different times.Alerts
Various page/block level quotes for drawing attention to things.
Warning
Using shortcodes, e.g.{{< pipe-elm "SplitFilter" >}}
inside an of these alerts is currently not fully supported so may not work.
Warning block Quote
Warning
This is a warning that can contain markdown.The markdown for this is:
{{% warning %}}
This is a warning that can contain _markdown_.
{{% /warning %}}
Page level warning
Warning
This is a warning that can contain markdown.
The markdown for this is:
{{% page-warning %}}
This is a warning that can contain _markdown_.
{{% /page-warning %}}
Note block Quote
Note
This is a note that can contain markdown.The markdown for this is:
{{% note %}}
This is a note that can contain **markdown**.
{{% /note %}}
See also block Quote
Useful for linking to other areas of the documentation or to external sites.
See Also
The markdown for this is:
{{% see-also %}}
[Note block quote]({{< relref "#note-block-quote" >}})
[Warning block quote]({{< relref "#warning-block-quote" >}})
{{% /see-also %}}
Page level info
This is some info that can contain markdown.
The markdown for this is:
{{% pageinfo %}}
This is some info that can contain **markdown**.
{{% /pageinfo %}}
TODO block Quote
Used to indicate areas of the documentation that are unfinished or incorrect.
TODO
This is a TODO that can containmarkdown
.
The markdown for this is:
{{% todo %}}
This is a TODO that can contain `markdown`.
{{% /todo %}}
Cards
Cards can be used to display related content side by side. Each card can contain markdown and/or Hugo short codes. The cards will be displayed horizontally to fill the width of the page.
---
root:
someKey: "value"
<root>
<child attr="xxx">some val</child>
</root>
The markdown for this is:
{{< cardpane >}}
{{< card header="YAML" >}}
```yaml
---
root:
someKey: "value"
```
{{< /card >}}
{{< card header="XML" >}}
```xml
<root>
<child attr="xxx">some val</child>
</root>
```
{{< /card >}}
{{< /cardpane >}}
Tabbed panes
Hugo/Docsy have shortcodes for tabbed panes however these mean only one tab will be printed or visible in the generated PDF so their use should be avoided.
4.3.5 - Images
Image assets
All Images should be placed in /assets/images/
or within a descendent directory of it.
Images should be added to the markdown using the image
shortcode.
This ensures a consistent look for all images and allows control of the size of the image.
The short code can be added in the following ways.
Markdown:
{{< image "style-guide/stroom-oo.svg" "200x" >}}
{{< image "style-guide/stroom-oo.png" >}}
{{< image "style-guide/stroom-oo.svg" "200x" >}}Image caption{{< /image >}}
All paths used in the image
shortcode are relative to /assets/images
.
The following shows an example of the directory structure.
/assets
/images
/section-x
/sub-section-y
/page1
/image.svg
/content
/en
/docs
/section-x
/sub-section-y
page1.md - #image shortcode used in here
Where images are only used by one page then the directory structure in /assets
ought to mirror that of the page the images are used in, as shown above.
If images are used by multiple pages then some other sensible organisation of the images should be used, e.g. /assets/images/section-x
if they are limited to pages in one section, or /aaets/images/common
if they are used in multiple sections.
Captions
The image can be displayed with a caption:
Example:
Markdown:
{{< image "style-guide/svg-logo.svg" "200x" >}}
By W3C SVG Logo, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=105996438
{{< /image >}}
Size
The image can be defined with a maximum width (e.g. "300x"
) or a maximum height ("x200"
).
Example:
Markdown:
{{< image "style-guide/svg-logo.svg" "120x" />}}
.png files
.png
files can be rendered in their original size by omitting the size argument.
Examples:
Or they can be rendered with a set size.
Markdown:
The markdown for the examples above is:
{{< image "style-guide/stroom-amber.png" />}}
Or they can be rendered with a set size.
{{< image "style-guide/stroom-amber.png" "50x"/>}}
Using global /assets/
resources
For images that are shared by multiple page bundles, e.g. stroom icons, place them in /assets/images/
.
The image path is relative to /assets/images/
, e.g. file /assets/images/style-guide/svg-example.svg
becomes style-guide/svg-example.svg
.
Example:
Markdown:
{{< image "style-guide/svg-example.svg" "200x" >}}
This is some optional caption text for the image.
And this is another line.
{{< /image >}}
PlantUML
PlantUML is the favoured tool for producing diagrams such as UML diagrams, entity relationship diagrams and other more general architecture diagrams. The diagrams are written in plain text which makes them easy to version control. The plantUML syntax can then be converted into image files, e.g. .svg files.
A plantUML diagram looks like this in plain text form:
@startuml
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response
Alice -> Bob: Another authentication Request
Alice <-- Bob: Another authentication Response
@enduml
PlantUML diagrams should be saved in a dedicated .puml
file in the same folder as the page that will display it.
If it is needed by multiple pages then it should be saved in /assets/images/
.
The build process will convert all .puml
files to a corresponding .puml.svg
file.
These generated .puml.svg
files are ignored by git so need to be regenerated at build time or when you change a .puml
file.
The images can be generated by doing:
./container_build/runInPumlDocker.sh SVG
You should embed a PlantUML image like this, using the .puml.svg
file (that may not yet exist, but will have to exist before the site is built):
Example:
Markdown:
{{< image "style-guide/puml-example.puml.svg" "300x" />}}
Using page resources
Images can be located in a
page bundle
.
This is where the page is defined as a named directory (rather than a .md
file) with an associated index.md
file for the markdown contnet.
All other items in the directory are page resources that can be used by the page, i.e. image files.
Warning
Whilst you can structure your site using page resources the preffered approach for stroom-docs is to use the common assets directory. This keeps all the images in one place and means pages can have a named markdown file rather than all being calledindex.md
.
Use the image
short code to display an image file that is located in the same directory as the page.
For the short code to work the page must be a leaf bundle (index.md
) or a branch bundle (_index.md
), i.e:
/docs
/MyPage
index.md - #image shortcode used in here
example.svg
or
/docs
/MySection
/Page1
index.md
/Page2
index.md
_index.md - #image shortcode used in here
example.svg
In the above example, the shortcode would look like:
{{< image "example.svg" "200x" >}}
Stroom user interface Components
Sometimes it is useful to display an image of certain user interface elements to explain something. Rather than use screenshots which are very difficult to keep up to date, you can instead use some simple shortcodes to display some UI elements, e.g. buttons, pipeline elements, etc. By using shortcodes, any change to the look of the Stroom UI means only the shortcode content and their styling need to change, without having to recreate tens or hundreds of screenshots.
Stroom icons
Stroom UI icons such as stroom-icon
.
Arguments:
name
- The filename (and relative path) of the icon file. The path is relative to/assets/images/stroom-ui/
, e.g.documents/Feed.svg
.title
(optional) - The hover tip title that will be given to the icon. If not supplied, the filename (minus extension) will be converted to sentence case and used as the title.enabled
(optional) [enabled
|disabled
] - Whether the button is enabled or disabled. Defaults toenabled
.colour
(optional) - The colour variant to use for the icon. Not all icons support colour variants. If not supplied, and where the icon supports colour variants, then the default colour is blue. See below for the list of colour variants.
The full list of available icons can be found in the Icon Gallery.
Warning
The icon filenames and paths are case sensitive so ensure you have the correct case, e.g. mostdocument
icons are in upper sentence case.
Examples:
Simple use:
Custom hover tip name:
A document icon:
A pipeline icon:
Enabled
vs disabledAn icon in its different colour states:
- Default (no colour specified)
blue
brey
green
red
Markdown:
The markdown for the examples above is:
Simple use: {{< stroom-icon "save.svg" >}}
Custom hover tip name: {{< stroom-icon "key.svg" "Not a key" >}}
A document icon: {{< stroom-icon "document/Feed.svg" >}}
A pipeline icon: {{< stroom-icon "pipeline/text.svg" >}}
Enabled {{< stroom-icon "delete.svg" >}} vs disabled {{< stroom-icon "delete.svg" "Delete" "disabled" >}}
An icon in its different colour states:
* Default (no colour specified) {{< stroom-icon name="settings.svg" >}}
* `blue` {{< stroom-icon name="settings.svg" colour="blue" >}}
* `brey` {{< stroom-icon name="settings.svg" colour="grey" >}}
* `green` {{< stroom-icon name="settings.svg" colour="green" >}}
* `red` {{< stroom-icon name="settings.svg" colour="red" >}}
Buttons
To display a user interface button you can use the shortcode stroom-btn
with the button title as its only argument.
Arguments:
title
- The text to display on the button.type
- Optional. (primary
|secondary
).primary
results in a blue button.secondary
results in a red button.- Not Set results in a standard grey button.
filename
- Optional. Filename of an icon to use next to the text, e.g.undo.svg
.
Note
If the title isOK
, Close
or Cancel
then the type and filename do not need to be set as they will be set automatically.
Examples:
, , and
And not in line
Markdown:
The markdown for the examples above is:
{{< stroom-btn "Ok" >}}, {{< stroom-btn "Close" >}}, {{< stroom-btn "Cancel" >}} and {{< stroom-btn title="Undo" filename="undo.svg" >}}
And not in line
{{< stroom-btn "Save" >}}<br/>
Pipeline elements
To display a pipeline element (as seen on the Structure sub-tab on the Pipeline screen), like
SplitFilter
, you can use the shortcode pipe-elm
.
Arguments:
element_name
- The name of the pipeline element (case sensitive), e.g.XSLTFilter
.display_name
(optional) - The display name for the pipeline element. If a display name is not provided then the element name will be used as the display name.
The list of available pipeline elements can be found in this gallery.
An invalid element_name
will result in an error when building the site.
The icon will be selected to match the element name provided. The element is a clickable link to the appropriate reference page for that element.
Examples:
This is an xsltFilter with its default name:
This is a splitFilter with a custom name:
This is an IndexingFilter in line.
Markdown:
The markdown for the examples above is:
This is an xsltFilter with its default name:
{{< pipe-elm "XSLTFilter" >}}<br/>
This is a splitFilter with a custom name:
{{< pipe-elm "SplitFilter" "My Split Filter" >}}<br/>
This is an {{< pipe-elm "IndexingFilter" >}} in line.
Pipelines
To display a pipeline consisting of multiple pipeline elements (as seen on the Structure sub-tab on the Pipeline screen) you can use the short code pipe
.
This shortcode takes no arguments.
Instead, the inner content of the shortcode is populated with multiple pipe-elm
shortcodes to describe each of the elements in the pipeline.
This shortcode does not support any branching/forking in the pipeline.
Example:
Markdown:
The markdown for the two examples above is:
{{< pipe >}}
{{< pipe-elm "Source" >}}
{{< pipe-elm "XMLParser" >}}
{{< pipe-elm "RecordCountFilter" "recordCount (read)" >}}
{{< pipe-elm "SplitFilter" >}}
{{< pipe-elm "IdEnrichmentFilter" >}}
{{< pipe-elm "XSLTFilter" >}}
{{< pipe-elm "SchemaFilter" >}}
{{< pipe-elm "ElasticIndexingFilter" >}}
{{< pipe-elm "RecordCountFilter" "recordCount (written)" >}}
{{< /pipe >}}
Each element is a clickable link to the appropriate reference page for that element. Pipelines cannot be used in-line in text.
For details on how to use pipe-elm
see pipeline elements above.
The list of available pipeline elements can be found in this gallery.
Stroom document tabs
To display a top level Stroom document tab, like
Big Index
, you can use the shortcode
stroom-tab
.
Arguments:
icon_filename
- The filename of the icon to use (relative toassets/images/stroom-ui/document/
) (case sensitive), e.g.Pipeline.svg
.title
- The text to display in the tab, e.g.Indexing Pipeline
.state
(optional) - Whether the tab is active or not (active
orinactive
). Defaults toinactive
.
For a full list of all available icons see the Icon Gallery
Examples:
Simple: MY_FEED
Custom name: My Translation
Active/Inactive: My Translation My Translation
Unsaved: * My Translation
Markdown:
The markdown for these examples is:
Simple: {{< stroom-tab "Feed.svg" "MY_FEED" >}}
Custom name: {{< stroom-tab "XSLT.svg" "My Translation" >}}
Active/Inactive: {{< stroom-tab "XSLT.svg" "My Translation" "active" >}} {{< stroom-tab "XSLT.svg" "My Translation" >}}
Unsaved: {{< stroom-tab "XSLT.svg" "My Translation" "active" "unsaved" >}}
Stroom selected menu items
To display the selection of a menu item you can use the stroom-menu
shortcode.
Arguments:
menu_item_names...
- One argument per menu item name in the order root to leaf.
Examples:
For example to demonstrate creating a folder using the context menu:
The shortcode takes one argument per menu item so you can have multiple levels of menu.
Markdown:
The markdown for these examples is:
For example to demonstrate creating a folder using the context menu:
{{< stroom-menu "New" "Folder" >}}
The shortcode takes one argument per menu item so you can have multiple levels of menu.
{{< stroom-menu "Add" "Folder" "Feed" >}}
It cannot be used in-line in text, it needs to be on its own line.
The list of available menu items with an icon can be found in this gallery. Menu item names are case-sensitive.
If the menu item name is not an exact match to one in the gallery then it will be displayed without an icon, e.g.:
Keyboard Shortcuts
To display a keyboard shortcut (AKA key binding) you can use the key-bind
shortcode.
Arguments:
key_bind...
- One or more key bindings, whit keys in the key binding delimited by,
,-
or+
. The name and case of non-alphabet keys will be normalised, e.g.del
=>Delete
. The modifier keysctrl
,shift
,alt
,meta
will be placed first and displayed in a consistent order.
Each argument is one of more keys that are pressed at the same time, e.g. "ctrl,c"
for
Ctrl ^
+
c
.
Chord key bindings where multiple key binds are pressed and released in sequence have one argument for each step in the chord, e.g. pressing g
then p
has arguments "g"
and "p"
, producing
g
,
p
.
Examples:
This is a key binding with modifiers Ctrl ^ + Shift ⇧ + f and this is chord type key binding g , p .
If the key is a ,
then use +
or -
as the delimiter, e.g.
Ctrl ^
+
Alt
+
,
,
Ctrl ^
+
+
or
Alt
+
-
.
Markdown:
The markdown for these examples is:
This is a key binding with modifiers {{< key-bind "ctrl,shift,f" >}} and this is chord type key binding {{< key-bind "g" "p" >}}.
If the key is a `,` then use `+` or `-` as the delimiter, e.g. {{< key-bind "ctrl+alt+," >}}, {{< key-bind "ctrl,+" >}} or {{< key-bind "alt+-" >}}.
4.3.6 - Icon Gallery
This page can be used as a reference for finding icons and their filenames to use them in the documentation.
See here for how to add icons to pages.
General icons
General icons used in Stroom.
Example: {{< stroom-icon "edit.svg" >}}
Pipeline element icons
Icons used for the different pipeline elements.
Base path: pipeline
Example: {{< stroom-icon "pipeline/stream.svg" >}}
Document type icons
Icons used for the different document entity types, i.e. those seen in the explorer tree.
Base path: document
Example: {{< stroom-icon "document/Index.svg" >}}
Table column icons
Icons used on the Dashboard and Query table columns.
Base path: fields
.
Menu items
Menu items with icons that are available for use with the stroom-menu
shortcode.
Pipeline elements
Pipeline elements that are available for use with the pipe-elm
and pipe
shortcodes.
Updating this gallery
Icons
This gallery of icons can be updated by running the following script which will copy all the icons from the stroom repository. You should ensure your local stroom repository is up to date and on the correct branch before running this.
e.g.
Menu Items
To update the available menu items edit the shortcode file layouts/shortcodes/stroom-menu.html
and modify the icon_map
variable.
Pipeline elements
To update the available pipeline elements edit the shortcode file layouts/shortcodes/pipe-elm.html
and modify the element_map
variable.