Skip to content

Commit b2788bf

Browse files
devversionmmalerba
authored andcommitted
build: package docs content into npm package (#14411)
* build: package docs content into npm package * Packages the Bazel generated docs content into the Bazel generated `ng_package` of the `material-examples`. * Package overviews for CDK and Material into the docs content
1 parent b78a750 commit b2788bf

File tree

5 files changed

+196
-3
lines changed

5 files changed

+196
-3
lines changed

src/material-examples/BUILD.bazel

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package(default_visibility=["//visibility:public"])
22

3-
load("//:packages.bzl", "CDK_TARGETS", "MATERIAL_TARGETS", "ROLLUP_GLOBALS")
3+
load("//:packages.bzl", "CDK_TARGETS", "MATERIAL_TARGETS", "ROLLUP_GLOBALS", "MATERIAL_PACKAGES",
4+
"CDK_PACKAGES")
45
load("//tools:defaults.bzl", "ng_module", "ng_package")
56
load("//tools/highlight-files:index.bzl", "highlight_files")
7+
load("//tools/package-docs-content:index.bzl", "package_docs_content")
68

79
ng_module(
810
name = "examples",
@@ -21,17 +23,56 @@ ng_module(
2123
tsconfig = ":tsconfig-build.json",
2224
)
2325

24-
highlight_files(
25-
name = "highlighted-files",
26+
filegroup(
27+
name = "example-source-files",
2628
srcs = glob(["*/*.html", "*/*.css", "*/*.ts"])
2729
)
2830

31+
filegroup(
32+
name = "material-overviews",
33+
srcs = ["//src/lib/%s:overview" % name for name in MATERIAL_PACKAGES]
34+
)
35+
36+
filegroup(
37+
name = "cdk-overviews",
38+
srcs = ["//src/cdk/%s:overview" % name for name in CDK_PACKAGES]
39+
)
40+
41+
highlight_files(
42+
name = "highlighted-source-files",
43+
srcs = [":example-source-files"]
44+
)
45+
46+
package_docs_content(
47+
name = "docs-content",
48+
srcs = {
49+
# We want to package the guides in to the docs content. These will be displayed
50+
# in the documentation.
51+
"//guides": "guides",
52+
53+
# For the live-examples in our docs, we want to package the highlighted files
54+
# into the docs content. These will be used to show the source code for examples.
55+
":highlighted-source-files": "examples-highlighted",
56+
57+
# In order to be able to run examples in StackBlitz, we also want to package the
58+
# plain source files into the docs-content.
59+
":example-source-files": "examples-source",
60+
61+
# Package the overviews for "@angular/material" and "@angular/cdk" into the docs content
62+
":material-overviews": "overviews/material",
63+
":cdk-overviews": "overviews/cdk",
64+
65+
# TODO(devversion): we need to also package the API html files here
66+
}
67+
)
68+
2969
ng_package(
3070
name = "npm_package",
3171
srcs = ["package.json"],
3272
entry_point = "src/material-examples/public_api.js",
3373
globals = ROLLUP_GLOBALS,
3474
deps = [":examples"],
75+
data = [":docs-content"],
3576
# TODO(devversion): re-enable once we have set up the proper compiler for the ng_package
3677
tags = ["manual"],
3778
)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
nodejs_binary(
7+
name = "package-docs-content",
8+
entry_point = "angular_material/tools/package-docs-content/package-docs-content.js",
9+
data = [
10+
"@matdeps//source-map-support",
11+
":sources",
12+
],
13+
)
14+
15+
ts_library(
16+
name = "sources",
17+
srcs = glob(["**/*.ts"]),
18+
deps = ["@matdeps//@types/node"],
19+
tsconfig = ":tsconfig.json",
20+
)

tools/package-docs-content/index.bzl

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"""
2+
Implementation of the "package_docs_content" rule. The implementation runs the
3+
packager executable in order to group all specified files into the given sections.
4+
"""
5+
def _package_docs_content(ctx):
6+
# Directory that will contain all grouped input files. This directory will be created
7+
# relatively to the current target package. (e.g. "bin/src/material-examples/docs-content")
8+
output_dir = ctx.attr.name;
9+
10+
# Arguments that will be passed to the packager executable.
11+
args = ctx.actions.args()
12+
13+
# List of outputs that should be generated by the packager action. Bazel will automatically
14+
# throw an error if any output has not been generated properly.
15+
expected_outputs = [];
16+
17+
# Support passing arguments through a parameter file. This is necessary because on Windows
18+
# there is an argument limit and we need to handle a large amount of input files. Bazel
19+
# switches between parameter file and normal argument passing based on the operating system.
20+
# Read more here: https://docs.bazel.build/versions/master/skylark/lib/Args.html#use_param_file
21+
args.use_param_file(param_file_arg = "--param-file=%s")
22+
23+
# Walk through each defined input target and the associated section and compute the
24+
# output file which will be added to the executable arguments.
25+
for input_target, section_name in ctx.attr.srcs.items():
26+
section_files = input_target.files.to_list()
27+
28+
for input_file in section_files:
29+
# For each input file, we want to create a copy that is stored in the output directory
30+
# within its specified section. e.g. "pkg_bin/docs-content/guides/getting-started.html"
31+
output_file = ctx.actions.declare_file(
32+
"%s/%s/%s" % (output_dir, section_name, input_file.basename))
33+
34+
# Add the output file to the expected outputs so that Bazel throws an error if the file
35+
# hasn't been generated properly.
36+
expected_outputs += [output_file]
37+
38+
# Pass the input file path and the output file path to the packager executable. We need
39+
# to do this for each file because we cannot determine the general path to the output
40+
# directory in a reliable way because Bazel targets cannot just "declare" a directory.
41+
# See: https://docs.bazel.build/versions/master/skylark/lib/actions.html
42+
args.add("%s,%s" % (input_file.path, output_file.path))
43+
44+
# Do nothing if there are no input files. Bazel will throw if we schedule an action
45+
# that returns no outputs.
46+
if not ctx.files.srcs:
47+
return None
48+
49+
# Run the packager executable that groups the specified source files and writes them
50+
# to the given output directory.
51+
ctx.actions.run(
52+
inputs = ctx.files.srcs,
53+
executable = ctx.executable._packager,
54+
outputs = expected_outputs,
55+
arguments = [args],
56+
)
57+
58+
return DefaultInfo(files = depset(expected_outputs))
59+
60+
"""
61+
Rule definition for the "package_docs_content" rule that can accept arbritary source files
62+
that will be grouped into specified sections. This is being used to package the docs
63+
content into a desired folder structure that can be shared with the docs application.
64+
"""
65+
package_docs_content = rule(
66+
implementation = _package_docs_content,
67+
attrs = {
68+
# This defines the sources for the "package_docs_content" rule. Instead of just
69+
# accepting a list of labels, this rule requires the developer to specify a label
70+
# keyed dictionary. This allows developers to specify where specific targets
71+
# should be grouped into. This helpful when publishing the docs content because
72+
# the docs repository does not about the directory structure of the generated files.
73+
"srcs": attr.label_keyed_string_dict(allow_files = True),
74+
75+
# Executable for this rule that is responsible for packaging the specified
76+
# targets into the associated sections.
77+
"_packager": attr.label(
78+
default = Label("//tools/package-docs-content"),
79+
executable = True,
80+
cfg = "host"
81+
)},
82+
)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Script that will be dispatched by the "package_docs_content" rule and is responsible for
3+
* copying input files to a new location. The new location will be computed within the Bazel
4+
* rule implementation so that we don't need to compute the output paths with their sections
5+
* multiple times.
6+
*/
7+
8+
import {readFileSync, writeFileSync} from 'fs';
9+
10+
/**
11+
* Determines the command line arguments for the current Bazel action. Since this action can
12+
* have a large set of input files, Bazel may write the arguments into a parameter file.
13+
* This function is responsible for handling normal argument passing or Bazel parameter files.
14+
* Read more here: https://docs.bazel.build/versions/master/skylark/lib/Args.html#use_param_file
15+
*/
16+
function getBazelActionArguments() {
17+
const args = process.argv.slice(2);
18+
19+
// If Bazel uses a parameter file, we've specified that it passes the file in the following
20+
// format: "arg0 arg1 --param-file={path_to_param_file}"
21+
if (args[0].startsWith('--param-file=')) {
22+
return readFileSync(args[0].split('=')[1], 'utf8').trim().split('\n');
23+
}
24+
25+
return args;
26+
}
27+
28+
if (require.main === module) {
29+
// The script expects the output path as first argument. All remaining arguments will be
30+
// considered as markdown input files that need to be transformed.
31+
getBazelActionArguments().forEach(argument => {
32+
// Each argument that has been passed consists of an input file path and the expected
33+
// output path. e.g. {path_to_input_file},{expected_output_path}
34+
const [inputFilePath, outputPath] = argument.split(',', 2);
35+
36+
writeFileSync(outputPath, readFileSync(inputFilePath, 'utf8'));
37+
});
38+
}
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+
}

0 commit comments

Comments
 (0)