Skip to content

Commit

Permalink
Move to esbuild and update npm packages (#1605)
Browse files Browse the repository at this point in the history
The assets build script instead precompiles the Handlebars templates.
https://handlebarsjs.com/installation/precompilation.html

The HTML formatter's digest function has been updated to produce 8-
character uppercase hashes in order to match those generated by esbuild.

The ESLint config was re-initiated and now uses its default parser
(Espree), so Babel is no longer required.

For the Elixir-based tests to result in up-to-date build dist contents I
found I had to empty the _build directory.
  • Loading branch information
DavidOliver authored Sep 15, 2022
1 parent eb463ec commit 7d400e5
Show file tree
Hide file tree
Showing 61 changed files with 5,717 additions and 23,058 deletions.
13 changes: 5 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
otp: 24
lint: lint
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

- uses: erlef/setup-beam@v1
with:
Expand Down Expand Up @@ -59,17 +59,14 @@ jobs:
name: Check JS
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
- name: Set up Node.js 10.x
uses: actions/[email protected]
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 10.10.0
node-version: 16
- run: npm install --prefix assets
- run: npm run --prefix assets lint

- run: sudo apt-get install xvfb
- name: npm install, build, and test
run: |
- run: |
xvfb-run --auto-servernum npm run --prefix assets test
env:
CI: true
44 changes: 2 additions & 42 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -16,45 +16,5 @@ https://github.com/elixir-lang/ex_doc/

==========================================================================

normalize.css
Copyright (c) Nicolas Gallagher and Jonathan Neal
https://necolas.github.io/normalize.css/

Released under the MIT License.
https://github.com/necolas/normalize.css/blob/master/LICENSE.md

==========================================================================

webpack
Copyright (c) 2012, Tobias Koppers
https://github.com/webpack/webpack

Released under the MIT License.
http://www.opensource.org/licenses/mit-license.php

==========================================================================

lodash
https://lodash.com/
Copyright 2012, The Dojo Foundation
http://dojofoundation.org/

Available under MIT license
https://github.com/lodash/lodash/blob/master/LICENSE

Based on Underscore.js
Copyright 2009, Jeremy Ashkenas, DocumentCloud and
Investigative Reporters & Editors

http://underscorejs.org/LICENSE

==========================================================================

IcoMoon
https://icomoon.io/

Released under the GPL version 3 and the Creative Commons Attribution 4.0 licenses.
https://www.gnu.org/licenses/gpl.html
https://creativecommons.org/licenses/by/4.0/

==========================================================================
Dependencies are externally maintained and have their own licenses; we
recommend you read them as their terms may differ from the terms above.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,13 @@ The easiest way to test changes to ExDoc is to locally rebuild the app and its o

1. Run `mix setup` to install all dependencies
2. Run `mix build` to generate docs. This is a custom alias that will build assets, recompile ExDoc, and output fresh docs into the `doc/` directory
3. If you want to contribute a pull request, please do not add to your commits the files generated in the `assets/` and `formatters/` folders
3. If you want to contribute a pull request, please do not add to your commits the files generated in the `formatters/` directory
4. Run `mix lint` to check if the Elixir and JavaScript files are properly formatted.
You can run `mix fix` to let the JavaScript linter and Elixir formatter fix the code automatically before submitting your pull request

Note that Node 17 or later is not supported due to [API breaking changes with Webpack](https://github.com/webpack/webpack/issues/14532).
If working on the assets, please see the README in the `assets/` directory.

The build process is currently tested in Node 16 LTS.

## License

Expand Down
17 changes: 0 additions & 17 deletions assets/.eslintrc

This file was deleted.

22 changes: 22 additions & 0 deletions assets/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module.exports = {
env: {
browser: true,
es2021: true
},
extends: 'standard',
overrides: [
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
rules: {
'no-path-concat': 0,
'no-throw-literal': 0,
'no-useless-escape': 0,
'object-curly-spacing': 0
},
globals: {
'Handlebars': 'readonly'
}
}
23 changes: 14 additions & 9 deletions assets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@
In this directory live all assets for `ExDoc`. The built, ready-to-use
versions are found in `formatters/{html,epub}/dist`.

To work on these assets you need to install [Node.js] (version 10) and
[NPM] (version 5.6) first (maybe as superuser or administrator).
To work on these assets you first need to install [Node.js] and [npm]. (npm
is usually installed along with Node.js.) The build process is currently tested
in Node 16 LTS.

Assets are built with [esbuild], which, along with the JavaScript linter and
test-runner, is set as a dependency in the assets `package.json` and installed
via [npm]:

```bash
$ npm install --prefix assets
```

## `npm run` scripts

Expand Down Expand Up @@ -32,7 +41,7 @@ Lint all JavaScript files using [ESLint].
### `lint:fix`

```bash
$ npm run --prefix lint:fix
$ npm run --prefix assets lint:fix
```

Lint and automatically fix all JavaScript files using [ESLint].
Expand All @@ -45,12 +54,8 @@ $ npm run --prefix assets test

Run all the available JavaScript tests using [Karma].

## Webpack

Internally we use [Webpack].

[esbuild]: https://esbuild.github.io
[Node.js]: https://nodejs.org/
[NPM]: https://www.npmjs.com/
[npm]: https://www.npmjs.com/
[ESLint]: https://eslint.org/
[Karma]: https://karma-runner.github.io/
[Webpack]: https://webpack.js.org/
7 changes: 0 additions & 7 deletions assets/babel.config.js

This file was deleted.

105 changes: 105 additions & 0 deletions assets/build/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
const path = require('node:path')
const esbuild = require('esbuild')
const util = require('./utilities')


/**
* Configuration variables
*/

// Build options
const commonOptions = {
entryNames: '[name]-[hash]',
bundle: true,
minify: true,
logLevel: 'info',
}
const epubOptions = {
outdir: path.resolve('../formatters/epub/dist'),
}
const htmlOptions = {
outdir: path.resolve('../formatters/html/dist'),
}

// Handlebars template paths
const templates = {
sourceDir: path.resolve('js/handlebars/templates'),
compiledDir: path.resolve('../tmp/handlebars'),
filename: 'handlebars.templates.js',
}
templates.compiledPath = path.join(templates.compiledDir, templates.filename)

// Directories to create/clean
const cleanDirs = {
pre: [
epubOptions.outdir,
htmlOptions.outdir,
templates.compiledDir,
],
postHtml: [
templates.compiledDir,
],
}


/**
* Clean: pre-build
*/

util.ensureEmptyDirsExistSync(cleanDirs.pre)


/**
* Build: ePub
*/

const epubBuild = esbuild.build({
...commonOptions,
...epubOptions,
entryPoints: [
'js/entry/epub.js',
'css/entry/epub-elixir.css',
'css/entry/epub-erlang.css',
],
}).catch(() => process.exit(1))


/**
* Build: HTML
*/

// Precompile Handlebars templates
util.runShellCmdSync(`npx handlebars ${templates.sourceDir} --output ${templates.compiledPath}`)

// esbuild
const htmlBuild = esbuild.build({
...commonOptions,
...htmlOptions,
entryPoints: [
templates.compiledPath,
'js/entry/html.js',
'css/entry/html-elixir.css',
'css/entry/html-erlang.css',
],
loader: {
'.woff2': 'file',
},
}).catch(() => process.exit(1))

// The Handlebars runtime from the local module dist directory is used to ensure
// the version matches that which was used to compile the templates.
// 'bundle' must be false in order for 'Handlebar' to be available at runtime.
esbuild.build({
...commonOptions,
...htmlOptions,
entryPoints: ['node_modules/handlebars/dist/handlebars.runtime.js'],
bundle: false,
}).catch(() => process.exit(1))


/**
* Clean: post-build
*/
Promise.all([epubBuild, htmlBuild]).then(() => {
util.ensureEmptyDirsExistSync(cleanDirs.postHtml)
})
21 changes: 21 additions & 0 deletions assets/build/utilities.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const child_process = require('node:child_process')
const fs = require('fs-extra')

module.exports.runShellCmdSync = (command) => {
child_process.execSync(command, (err, stdout, stderr) => {
if (err) {
console.error(err)
process.exit(1)
} else {
if (stdout) { console.log('\n' + stdout) }
if (stderr) { console.log('\n' + stderr) }
return
}
})
}

module.exports.ensureEmptyDirsExistSync = (dirs) => {
dirs.forEach(dir => {
fs.emptyDirSync(dir)
})
}
3 changes: 1 addition & 2 deletions assets/css/_html.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
@import 'custom-props/theme-light.css';
@import 'custom-props/theme-dark.css';

/* To build with esbuild, remove '~' */
@import '~normalize.css/normalize.css';
@import 'normalize.css/normalize.css';

@import 'icons.css';
@import 'layout.css';
Expand Down
2 changes: 1 addition & 1 deletion assets/css/icons.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@font-face {
font-family: 'remixicon';
src: url('../fonts/remixicon.woff2?t=1590207869815') format('woff2');
src: url('../fonts/remixicon.woff2') format('woff2');
font-display: swap;
}

Expand Down
1 change: 0 additions & 1 deletion assets/fonts/remixicon.symbol.svg

This file was deleted.

3 changes: 1 addition & 2 deletions assets/js/autocomplete/autocomplete-list.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import autocompleteSuggestionsTemplate from '../handlebars/templates/autocomplete-suggestions.handlebars'
import { getSuggestions } from './suggestions'
import { isBlank, qs } from '../helpers'

Expand Down Expand Up @@ -54,7 +53,7 @@ export function updateAutocompleteList (searchTerm) {

// Updates list of suggestions inside the autocomplete.
function renderSuggestions ({ term, suggestions }) {
const autocompleteContainerHtml = autocompleteSuggestionsTemplate({ suggestions, term })
const autocompleteContainerHtml = Handlebars.templates['autocomplete-suggestions']({ suggestions, term })

const autocompleteContainer = qs(AUTOCOMPLETE_CONTAINER_SELECTOR)
autocompleteContainer.innerHTML = autocompleteContainerHtml
Expand Down
10 changes: 5 additions & 5 deletions assets/js/autocomplete/suggestions.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function nodeSuggestion (node, query, category) {
label: null,
description: null,
matchQuality: matchQuality(node.title, query),
category: category
category
}
}

Expand All @@ -98,10 +98,10 @@ function childNodeSuggestion (childNode, parentId, query, category, label) {
return {
link: `${parentId}.html#${childNode.anchor}`,
title: highlightMatches(childNode.id, query),
label: label,
label,
description: parentId,
matchQuality: matchQuality(childNode.id, query),
category: category
category
}
}

Expand All @@ -124,10 +124,10 @@ function moduleChildNodeSuggestion (childNode, parentId, query, category, label)
return {
link: `${parentId}.html#${childNode.anchor}`,
title: highlightMatches(childNode.id, tokenizedQuery),
label: label,
label,
description: parentId,
matchQuality: matchQuality(modFun, query),
category: category
category
}
}

Expand Down
Loading

0 comments on commit 7d400e5

Please sign in to comment.