Skip to content

Commit f31e9be

Browse files
devversionandrewseguin
authored andcommitted
build: transform guide markdown files with bazel (#14103)
* build: transform guide markdown files with bazel * Initial implementation of a rule that can transform markdown files to the equivalent HTML output. This is the foundation for packaging the guides into the `//src/material-examples` package (see: #13454) * Address feedback
1 parent 60ad70e commit f31e9be

File tree

8 files changed

+146
-1
lines changed

8 files changed

+146
-1
lines changed

.circleci/config.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ jobs:
8888
- *restore_cache
8989
- *copy_bazel_config
9090

91-
# TODO(jelbourn): Update this command to run all tests if the Bazel issues have been fixed.
9291
- run: bazel build src/...
9392
- run: bazel test src/... tools/public_api_guard/...
9493

guides/BUILD.bazel

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package(default_visibility=["//visibility:public"])
2+
3+
load("//tools/markdown-to-html:index.bzl", "markdown_to_html")
4+
5+
markdown_to_html(
6+
name = "guides",
7+
srcs = glob(["**/*.md"]),
8+
)

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
"karma-sauce-launcher": "^1.2.0",
116116
"karma-sourcemap-loader": "^0.3.7",
117117
"magic-string": "^0.22.4",
118+
"marked": "^0.5.1",
118119
"minimatch": "^3.0.4",
119120
"minimist": "^1.2.0",
120121
"mock-fs": "^4.7.0",

tools/markdown-to-html/BUILD.bazel

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
4+
load("//tools:defaults.bzl", "ts_library")
5+
6+
ts_library(
7+
name = "transform-markdown",
8+
srcs = [":transform-markdown.ts"],
9+
deps = ["@matdeps//@types/node"],
10+
tsconfig = ":tsconfig.json",
11+
)
12+
13+
nodejs_binary(
14+
name = "markdown-to-html",
15+
entry_point = "angular_material/tools/markdown-to-html/transform-markdown.js",
16+
data = [
17+
"@matdeps//highlight.js",
18+
"@matdeps//marked",
19+
"@matdeps//source-map-support",
20+
":transform-markdown",
21+
],
22+
)
23+
24+

tools/markdown-to-html/index.bzl

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""
2+
Implementation of the "markdown_to_html" rule. The implementation runs the transform
3+
executable in order to create the outputs for the specified source files.
4+
"""
5+
def _markdown_to_html(ctx):
6+
input_files = ctx.files.srcs;
7+
args = ctx.actions.args()
8+
expected_outputs = [];
9+
10+
# Add the bazel bin directory to the command arguments. The script needs to know about
11+
# the output directory because the input files are not in the same location as the bazel
12+
# bin directory.
13+
args.add(ctx.bin_dir.path)
14+
15+
for input_file in input_files:
16+
# Remove the extension from the input file path. Note that we should not use `.replace`
17+
# here because the extension can be also in upper case.
18+
basename = input_file.basename[:-len(".md")]
19+
20+
# For each input file "xxx.md", we want to write an output file "xxx.html"
21+
expected_outputs += [ctx.actions.declare_file("%s.html" % basename)]
22+
23+
# Add the input file to the command line arguments that will be passed to the
24+
# transform-markdown executable.
25+
args.add(input_file.path)
26+
27+
# Run the transform markdown executable that transforms the specified source files.
28+
# Note that we should specify the outputs here because Bazel can then throw an error
29+
# if the script didn't generate the required outputs.
30+
ctx.actions.run(
31+
inputs = input_files,
32+
executable = ctx.executable._transform_markdown,
33+
outputs = expected_outputs,
34+
arguments = [args],
35+
)
36+
37+
return DefaultInfo(files = depset(expected_outputs))
38+
39+
"""
40+
Rule definition for the "markdown_to_html" rule that can accept arbritary source files
41+
that will be transformed into HTML files. The outputs can be referenced through the
42+
default output provider.
43+
"""
44+
markdown_to_html = rule(
45+
implementation = _markdown_to_html,
46+
attrs = {
47+
"srcs": attr.label_list(allow_files = [".md"]),
48+
49+
# Executable for this rule that is responsible for converting the specified
50+
# markdown files into HTML files.
51+
"_transform_markdown": attr.label(
52+
default = Label("//tools/markdown-to-html"),
53+
executable = True,
54+
cfg = "host"
55+
)},
56+
)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* Script that will be used by the markdown_to_html Bazel rule in order to transform
3+
* multiple markdown files into the equivalent HTML output.
4+
*/
5+
6+
import {readFileSync, writeFileSync} from 'fs';
7+
import {join} from 'path';
8+
9+
// These types lack type definitions.
10+
const marked = require('marked');
11+
const highlightJs = require('highlight.js');
12+
13+
// Regular expression that matches the markdown extension of a given path.
14+
const markdownExtension = /.md$/;
15+
16+
// Setup the default options for converting markdown to HTML.
17+
marked.setOptions({
18+
// Implement a highlight function that converts the code block into a highlighted
19+
// HTML snippet that uses HighlightJS.
20+
highlight: (code: string, language: string): string => {
21+
if (language) {
22+
return highlightJs.highlight(
23+
language.toLowerCase() === 'ts' ? 'typescript' : language, code).value;
24+
}
25+
return code;
26+
}
27+
});
28+
29+
if (require.main === module) {
30+
// The script expects the bazel-bin path as first argument. All remaining arguments will be
31+
// considered as markdown input files that need to be transformed.
32+
const [bazelBinPath, ...inputFiles] = process.argv.slice(2);
33+
34+
// Walk through each input file and write transformed markdown output to the specified
35+
// Bazel bin directory.
36+
inputFiles.forEach(inputPath => {
37+
const outputPath = join(bazelBinPath, inputPath.replace(markdownExtension, '.html'));
38+
writeFileSync(outputPath, marked(readFileSync(inputPath, 'utf8')));
39+
});
40+
}

tools/markdown-to-html/tsconfig.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"compilerOptions": {
3+
"lib": ["es2015"],
4+
"module": "commonjs",
5+
"target": "es5",
6+
"sourceMap": true,
7+
"types": ["node"]
8+
},
9+
"bazelOptions": {
10+
"suppressTsconfigOverrideWarnings": true
11+
}
12+
}

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7469,6 +7469,11 @@ marked@^0.3.2:
74697469
resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.19.tgz#5d47f709c4c9fc3c216b6d46127280f40b39d790"
74707470
integrity sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==
74717471

7472+
marked@^0.5.1:
7473+
version "0.5.1"
7474+
resolved "https://registry.yarnpkg.com/marked/-/marked-0.5.1.tgz#062f43b88b02ee80901e8e8d8e6a620ddb3aa752"
7475+
integrity sha512-iUkBZegCZou4AdwbKTwSW/lNDcz5OuRSl3qdcl31Ia0B2QPG0Jn+tKblh/9/eP9/6+4h27vpoh8wel/vQOV0vw==
7476+
74727477
matchdep@^2.0.0:
74737478
version "2.0.0"
74747479
resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e"

0 commit comments

Comments
 (0)