18 KiB
Documentation editing guidelines
This page covers guidelines for editing the Handsontable documentation.
Maintenance rules
When adding new documentation files, check the documentation directory structure, and follow the guidelines below.
Filenames
- Use only lower-case characters.
- To separate words, use
-. - Use the
.mdfile extension. The.vueextension is disabled.
Frontmatter
Each Markdown file can start with the following frontmatter tags:
| Tag | Meaning | Default value |
|---|---|---|
id |
The page's unique ID. | Required. Used for redirecting between different versions (e.g., 12.1 to 11.0) of the same documentation page (https://github.com/handsontable/handsontable/pull/10163). Don't change the IDs of existing pages. To add an ID for a new page, generate 8 random alphanumeric characters (https://www.random.org/strings/?num=20&len=8&digits=on&loweralpha=on&unique=on&format=html&rnd=new). |
title |
The page's header. | If not set, gets generated from the page's parent's title. |
permalink |
The page's unique URL. | If not set, gets generated from the Markdown file name. |
canonicalUrl |
A canonical URL of the page's latest version. | None (not required) |
metaTitle |
The page's SEO meta title. | None (not required) |
description |
The page's SEO meta description. | None (not required) |
tags |
Search tags used by the documentation search engine. | None (not required) |
react |
Holds an alternative set of frontmatter tags (applied only to the React version of the page) | None (not required) |
searchCategory |
Search category used by the search engine to categorize the search results. | If not set, the search result will be listed under the default "Guides" section. |
You can set different frontmatter tags for different framework versions of the page. For example, you can set metaTitle to say either JS data grid or React data table, depending on the framework:
```yaml // applies to the JS version of the page metaTitle: JS data grid
// applies to the React version of the page react: metaTitle: React data table ```
You can use the following framework keys:
react
Frontmatter example:
---
id: 1ezrscdc
title: Introduction
metaTitle: Installation - Guide - Handsontable Documentation for Javascript
description: Easily install the data grid using your preferred package manager or import Handsontable assets directly from the CDN.
permalink: /api/
canonicalUrl: /api/
react:
id: xyr8fg2e # The page id should be different for different for other framework variations
metaTitle: Installation - Guide - Handsontable Documentation for React
description: Install the wrapper for React via npm, import stylesheets, and use it to get up and running your application.
customValue: Custom # Custom value that can be used within template and will be available only for React framework
tags:
- api
- api ref
searchCategory: API Reference # The list of categories can be found here ./docs/.vuepress/config.js#L258
---
Sitemap frontmatter
The vuepress-plugin-sitemap lets us use additional tags to customize the documentation site map:
---
sitemap:
exclude: false
changefreq: hourly
---
Editing the documentation
When editing the documentation content, follow the guidelines below.
Editing the next documentation version
Draft files to be included in the documentation's next version are kept in the content directory.
The next version of the documentation is available only locally and on the staging server.
To display the next version in a browser:
- Start a local Handsontable documentation server.
- In your browser, go to http://localhost:8080/docs/.
Editing a published documentation version
To edit an already-published documentation version, go to the prod-docs/<MAJOR.MINOR> branch (e.g. prod-docs/9.0).
To display a published documentation version in a browser:
- Start a local Handsontable documentation server.
- In your browser, go to http://localhost:8080/docs/{MAJOR.MINOR}/.
If you're editing the latest version (a version with the largest <MAJOR.MINOR> number), remember to make the same edits to the next version as well.
Editing the API reference
The next version's API reference is generated automatically from the source code, into the /content/api/ directory.
To edit the next version's API reference:
- Go into the source code and change the required JSDoc comments.
- Generate the
nextversion's API reference output:npm run docs:api
To edit a published version's API reference:
- Go to the required version's API reference output:
/docs/<MAJOR.MINOR>/api(e.g./docs/9.0/api). - Edit the required Markdown files.
Reviewing the documentation
When reviewing someone else's changes, you can see the documentation output in a few different ways:
- Switch to the reviewed branch, pull the latest changes, and start a local documentation server (link redirects won't work, though).
- Deploy the documentation to the staging environment (https://dev.handsontable.com/docs).
- Deploy the documentation locally at a specific commit.
Deploying the documentation locally at a specific commit
To deploy the documentation locally at a [COMMIT_HASH] commit:
- If you don't have Docker Desktop, install it.
- From the
docsdirectory, run the following command:npm run docs:review [COMMIT_HASH] - In your browser, go to: http://localhost:8000/docs/.
Documentation versioning
New documentation is created automatically after the Handsontable is released. The ./scripts/release.mjs
takes care to create a Documentation production branch, generate API content from source code, commit, and deploy the Docs image to the production.
Markdown links
When linking to other documentation pages, avoid using absolute links or relative URLs.
To link to another page in the same documentation version, use the following syntax:
[link_text](@/relative_file_path_from_this_version's_root/file_name.md#some-anchor)
For example, to link to a file called core.md, from anywhere in the same documentation version:
[Core](@/api/core.md#updatesettings)
To link to another page but for other framework (and still for the same documentation version), use the following syntax:
[link_text](@/{FRAMEWORK}/relative_file_path_from_this_version's_root/file_name.md#some-anchor)
For example, to link to a file called ./content/guides/getting-started/react-methods.md that should be accessible only for React framework, use:
[React methods](@/react/guides/getting-started/react-methods/react-methods.md)
When there is no framework defined in the link URL, the generated link will be pointed to the currently viewed framework. For example, link [Core](@/api/core.md) for Javascript will point to /docs/javascript-data-grid/api/core and for chosen React framework to /docs/react-data-grid/api/core.
List of available frameworks: javascript, react.
Follow these rules:
- After the
@character, provide the target's relative file path (from the current version's root directory).
For example:[Clipboard][@/guides/cell-features/clipboard/clipboard.md]. - After the target file's name, add the
.mdextension
For example:[Autofill](@/api/autofill.md). - To link to a specific section, use anchors.
For example:[Core](@/api/core.md#some-anchor).
Also, the following rules apply:
- The target file needs to have the
permalinkfrontmatter tag defined. - If generating a final URL link fails, the initial value gets output as a relative link.
The documentation's link checker catches such failed links.
Checking for broken links
To check for broken links:
- Generate the Handsontable API reference. From the
docsdirectory, run:npm run docs:api - Build the documentation output. From the
docsdirectory, run:npm run docs:build - Check for broken links. From the
docsdirectory, run:npm run docs:check-links - Open the broken links report:
/docs/report-check-links.xlsx.
Markdown variables
It is possible to include metadata from VuePress or frontmatter in the content using the $page object and the following syntax:
Welcome the users of {{ $page.frameworkName }}!
The above code prints the following text in the React variant of the docs:
Welcome the users of React!
The full list of available variables is available at:
- https://vuepress.vuejs.org/guide/frontmatter.html (official)
- https://github.com/handsontable/handsontable/blob/develop/docs/.vuepress/plugins/extend-page-data/index.js#L76-L82 (our modifications)
Markdown containers
To render content in different ways, the documentation uses Markdown containers, for example:
::: example #exampleId .class :preset --html 1 --js 2
// code example
:::
We use the following Markdown containers:
| Container | Usage |
|---|---|
::: tip [title] |
Adds a blue tip note. |
::: warning [title] |
Adds a yellow warning note. |
::: danger [title] |
Adds a red danger note. |
::: details [title] |
Adds an accordion with expandable content. |
::: source-code-link <URL> |
Adds a source code link to the API ref header. |
::: example [options] |
Renders a code example as specified in [options]. |
For more information, see the VuePress documentation.
Adding code examples
Using the example Markdown container, you can add code snippets that show the code's result:
::: example #exampleId .class :react-redux --html 1 --js 2 --css 3 --no-edit --tab preview
```html
<div id="exampleId"></div>
```
```js
// code here
```
```css
/* custom css here */
```
:::
The example Markdown container offers the following options:
| Option | Required | Example | Possible values | Usage |
|---|---|---|---|---|
#exampleId |
No | #example1 |
String | Container's unique ID. |
.class |
No | .new-class |
String | Container's custom class. |
:preset |
No | :hot |
:hot | :hot-lang | :hot-numbro | :react | :react-languages | :react-numbro | :react-redux | :react-advanced | :angular | :angular-languages | :angular-numbro | :vue | :vue-numbro | :vue-languages | :vue-vuex |
Sets code dependencies. |
--js <pos> |
No | --js 1 |
Positive integer (default 1) |
Sets the JS code snippet's position in the markdown container. |
--html <pos> |
No | --html 2 |
Positive integer (default 0) |
Sets the HTML code snippet's position in the markdown container. 0 disables the HTML tab. |
--css <pos> |
No | --css 2 |
Positive integer (default 0) |
Sets the CSS code snippet's position in the markdown container. 0 disables the CSS tab. |
--no-edit |
No | --no-edit |
--no-edit |
Removes the Edit button. |
--tab <tab> |
No | --tab preview |
code | html | css | preview |
Sets a tab as open by default. |
Non-editable examples
You can also embed an example without the tabbed container.
To display just the result of the code you want to present, use the <HandsontablePreview> component. The code wrapped in this component and a markdown code block will be rendered with the context of the current Handsontable version.
<HandsontablePreview>
```js
// enter the Handsontable-related code here.
const containerElement = document.querySelector('#hot');
new Handsontable(containerElement, {});
```
Note: Remember to place all the needed HTML and <style> elements in the markdown file as well.
Finding the broken examples
The example-checker script checks if:
- Every example container's code initializes at least one Handsontable instance.
- The number of Handsontable instances implemented in the example containers corresponds to the number of Handsontable instance DOM containers being rendered on the page.
To use the example-checker script: (all the commands need to be run from the docs directory)
- Build the documentation.
npm run docs:build
- Run the script:
npm run docs:test:example-checker
The script is also automatically executed by the Docs Staging Deployment Github Actions workflow.
React style guide
When you edit React examples and code samples, follow the guidelines below.
For matters not covered here, follow the conventions of https://beta.reactjs.org/learn.
- Don't gather multiple props in a single
settings={}prop. Instead, specify individual props.<HotTable data={data} height="auto" /> - In JSX, use double quotes (
""). If a prop's value is a string, use double quotes without curly braces.licenseKey="00000-00000-00000-00000-00000" - In JS inside of JSX, use single quotes (
''). For example, if a React prop contains a JS object:<HotTable licenseKey="00000-00000-00000-00000-00000" nestedHeaders={[ ['A', { label: 'B', colspan: 8 }, 'C'] ]} /> - Get rid of elements that are not necessary (e.g., a
<Fragment>with a single child). - Use named imports:
import { useRef } from 'react'; useRef(...); - If a constant's value is a reference to the Handsontable component instance, add
Refto that constant's name.const hotRef = useRef(null); const hotTableComponentRef = useRef(null); - In functional React components, use
useRefinstead ofReact.createRef. - For the React Fragments, use the
<>shorthand instead of the explicit syntax (<React.Fragment>).<> <HotTable/> <div className="controls"> // (...) </div> </> - Always define
dataas a const, outside of JSX.const data = [ ['', 'Tesla', 'Volvo', 'Toyota', 'Ford'], ['2019', 10, 11, 12, 13], ['2020', 20, 11, 14, 13], ['2021', 30, 15, 12, 13] ]; return <HotTable data={data} />