369 lines
18 KiB
Markdown
369 lines
18 KiB
Markdown
# Documentation editing guidelines
|
|
|
|
This page covers guidelines for editing the [Handsontable documentation](https://handsontable.com/docs).
|
|
|
|
## Maintenance rules
|
|
|
|
When adding new documentation files, check the documentation [directory structure](./README.md#handsontable-documentation-directory-structure), and follow the guidelines below.
|
|
|
|
### Filenames
|
|
|
|
* Use only lower-case characters.
|
|
* To separate words, use `-`.
|
|
* Use the `.md` file extension. The `.vue` extension 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:
|
|
|
|
```yaml
|
|
---
|
|
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`](https://www.npmjs.com/package/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:
|
|
1. Start a [local Handsontable documentation server](./README.md#getting-started-with-handsontable-documentation).
|
|
2. 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](./README.md#handsontable-docs-branches-structure) (e.g. `prod-docs/9.0`).
|
|
|
|
To display a published documentation version in a browser:
|
|
1. Start a [local Handsontable documentation server](./README.md#getting-started-with-handsontable-documentation).
|
|
2. 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:
|
|
1. Go into the source code and change the required JSDoc comments.
|
|
2. Generate the `next` version's API reference output:
|
|
```bash
|
|
npm run docs:api
|
|
```
|
|
|
|
To edit a published version's API reference:
|
|
1. Go to the required version's API reference output: `/docs/<MAJOR.MINOR>/api` (e.g. `/docs/9.0/api`).
|
|
2. 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](./README.md#getting-started-with-handsontable-documentation) ([link redirects](./docker/redirects.conf) won't work, though).
|
|
- [Deploy the documentation to the staging environment](./README-DEPLOYMENT.md#manually-deploying-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).
|
|
|
|
### Deploying the documentation locally at a specific commit
|
|
|
|
To deploy the documentation locally at a `[COMMIT_HASH]` commit:
|
|
1. If you don't have [Docker Desktop](https://www.docker.com/products/docker-desktop), install it.
|
|
2. From the `docs` directory, run the following command:
|
|
```bash
|
|
npm run docs:review [COMMIT_HASH]
|
|
```
|
|
3. 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:
|
|
|
|
```markdown
|
|
[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:
|
|
|
|
```markdown
|
|
[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:
|
|
|
|
```markdown
|
|
[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:
|
|
|
|
```markdown
|
|
[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).<br>
|
|
For example: `[Clipboard][@/guides/cell-features/clipboard/clipboard.md]`.
|
|
* After the target file's name, add the `.md` [extension](#filenames)<br>
|
|
For example: `[Autofill](@/api/autofill.md)`.
|
|
* To link to a specific section, use anchors.<br>
|
|
For example: `[Core](@/api/core.md#some-anchor)`.
|
|
|
|
Also, the following rules apply:
|
|
* The target file needs to have the `permalink` [frontmatter](#frontmatter) tag defined.
|
|
* If generating a final URL link fails, the initial value gets output as a relative link.<br>
|
|
The documentation's [link checker](./README.md#documentation-npm-scripts) catches such failed links.
|
|
|
|
### Checking for broken links
|
|
|
|
To check for broken links:
|
|
|
|
1. Generate the Handsontable API reference. From the `docs` directory, run:
|
|
```bash
|
|
npm run docs:api
|
|
```
|
|
2. Build the documentation output. From the `docs` directory, run:
|
|
```bash
|
|
npm run docs:build
|
|
```
|
|
3. Check for broken links. From the `docs` directory, run:
|
|
```bash
|
|
npm run docs:check-links
|
|
```
|
|
4. 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:
|
|
|
|
```markdown
|
|
::: 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](https://v1.vuepress.vuejs.org/guide/markdown.html#custom-containers).
|
|
|
|
### Adding code examples
|
|
|
|
Using the `example` Markdown container, you can add code snippets that show the code's result:
|
|
|
|
```md
|
|
::: 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<br>(default `1`) | Sets the JS code snippet's position<br>in the markdown container. |
|
|
| `--html <pos>` | No | `--html 2` | Positive integer<br>(default `0`) | Sets the HTML code snippet's position<br>in the markdown container.<br><br>`0` disables the HTML tab. |
|
|
| `--css <pos>` | No | `--css 2` | Positive integer<br>(default `0`) | Sets the CSS code snippet's position<br>in the markdown container.<br><br>`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.
|
|
```js
|
|
<HandsontablePreview>
|
|
```js
|
|
// enter the Handsontable-related code here.
|
|
const containerElement = document.querySelector('#hot');
|
|
|
|
new Handsontable(containerElement, {});
|
|
```
|
|
</HandsontablePreview>
|
|
```
|
|
|
|
**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)
|
|
1. Build the documentation.
|
|
```bash
|
|
npm run docs:build
|
|
```
|
|
2. Run the script:
|
|
```bash
|
|
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.
|
|
```jsx
|
|
<HotTable
|
|
data={data}
|
|
height="auto"
|
|
/>
|
|
```
|
|
- In JSX, use double quotes (`""`). If a prop's value is a string, use double quotes without curly braces.
|
|
```jsx
|
|
licenseKey="00000-00000-00000-00000-00000"
|
|
```
|
|
- In JS inside of JSX, use single quotes (`''`). For example, if a React prop contains a JS object:
|
|
```jsx
|
|
<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:
|
|
```js
|
|
import { useRef } from 'react';
|
|
useRef(...);
|
|
```
|
|
- If a constant's value is a reference to the Handsontable component instance, add `Ref` to that constant's name.
|
|
```js
|
|
const hotRef = useRef(null);
|
|
const hotTableComponentRef = useRef(null);
|
|
```
|
|
- In functional React components, use `useRef` instead of `React.createRef`.
|
|
- For the React Fragments, use the `<>` shorthand instead of the explicit syntax (`<React.Fragment>`).
|
|
```jsx
|
|
<>
|
|
<HotTable/>
|
|
<div className="controls">
|
|
// (...)
|
|
</div>
|
|
</>
|
|
```
|
|
- Always define `data` as a const, outside of JSX.
|
|
```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} />
|
|
```
|