mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
build: highlight example sources files with bazel (#14325)
Part of #13454
This commit is contained in:
committed by
Jeremy Elbourn
parent
6347ace05e
commit
bb19dfc685
@@ -3,6 +3,7 @@ package(default_visibility=["//visibility:public"])
|
||||
load("@angular//:index.bzl", "ng_package")
|
||||
load("//:packages.bzl", "CDK_TARGETS", "MATERIAL_TARGETS", "ROLLUP_GLOBALS")
|
||||
load("//tools:defaults.bzl", "ng_module")
|
||||
load("//tools/highlight-files:index.bzl", "highlight_files")
|
||||
|
||||
ng_module(
|
||||
name = "examples",
|
||||
@@ -21,6 +22,11 @@ ng_module(
|
||||
tsconfig = ":tsconfig-build.json",
|
||||
)
|
||||
|
||||
highlight_files(
|
||||
name = "highlighted-files",
|
||||
srcs = glob(["*/*.html", "*/*.css", "*/*.ts"])
|
||||
)
|
||||
|
||||
ng_package(
|
||||
name = "npm_package",
|
||||
srcs = ["package.json"],
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
|
||||
load("//tools:defaults.bzl", "ts_library")
|
||||
|
||||
nodejs_binary(
|
||||
name = "highlight-files",
|
||||
entry_point = "angular_material/tools/highlight-files/highlight-files.js",
|
||||
data = [
|
||||
"@matdeps//highlight.js",
|
||||
"@matdeps//source-map-support",
|
||||
":sources",
|
||||
],
|
||||
)
|
||||
|
||||
ts_library(
|
||||
name = "sources",
|
||||
srcs = glob(["**/*.ts"]),
|
||||
deps = ["@matdeps//@types/node"],
|
||||
tsconfig = ":tsconfig.json",
|
||||
)
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Script that will be used by the highlight_files Bazel rule in order to highlight
|
||||
* multiple input files using highlight.js. The output will be HTML files.
|
||||
*/
|
||||
|
||||
import {readFileSync, writeFileSync} from 'fs';
|
||||
import {extname, join} from 'path';
|
||||
import {highlightCodeBlock} from './highlight-code-block';
|
||||
|
||||
/**
|
||||
* Determines the command line arguments for the current Bazel action. Since this action can
|
||||
* have a large set of input files, Bazel may write the arguments into a parameter file.
|
||||
* This function is responsible for handling normal argument passing or Bazel parameter files.
|
||||
* Read more here: https://docs.bazel.build/versions/master/skylark/lib/Args.html#use_param_file
|
||||
*/
|
||||
function getBazelActionArguments() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
// If Bazel uses a parameter file, we've specified that it passes the file in the following
|
||||
// format: "arg0 arg1 --param-file={path_to_param_file}"
|
||||
if (args[0].startsWith('--param-file=')) {
|
||||
return readFileSync(args[0].split('=')[1], 'utf8').trim().split('\n');
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
// The script expects the bazel-bin path as first argument. All remaining arguments will be
|
||||
// considered as markdown input files that need to be transformed.
|
||||
const [bazelBinPath, ...inputFiles] = getBazelActionArguments();
|
||||
|
||||
// Walk through each input file and write transformed markdown output to the specified
|
||||
// Bazel bin directory.
|
||||
inputFiles.forEach(inputPath => {
|
||||
const fileExtension = extname(inputPath).substring(1);
|
||||
// Convert "my-component-example.ts" into "my-component-example-ts.html"
|
||||
const baseOutputPath = inputPath.replace(`.${fileExtension}`, `-${fileExtension}.html`);
|
||||
const outputPath = join(bazelBinPath, baseOutputPath);
|
||||
const htmlOutput = highlightCodeBlock(readFileSync(inputPath, 'utf8'), fileExtension);
|
||||
|
||||
writeFileSync(outputPath, htmlOutput);
|
||||
});
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
Gets a path relative to the specified label. This is achieved by just removing the label
|
||||
package path from the specified path. e.g. the path is "guides/test/my-text.md" and the
|
||||
label package is "guides/". The expected path would be "test/my-text.md".
|
||||
"""
|
||||
def _relative_to_label(label, short_path):
|
||||
# TODO(devversion): extract into generic utility under tools/
|
||||
return short_path[len(label.package) + 1:]
|
||||
|
||||
"""
|
||||
Implementation of the "highlight_files" rule. The implementation runs the
|
||||
highlight-files executable in order to highlight the specified source files.
|
||||
"""
|
||||
def _highlight_files(ctx):
|
||||
input_files = ctx.files.srcs;
|
||||
args = ctx.actions.args()
|
||||
expected_outputs = [];
|
||||
|
||||
# Do nothing if there are no input files. Bazel will throw if we schedule an action
|
||||
# that returns no outputs.
|
||||
if not input_files:
|
||||
return None
|
||||
|
||||
# Support passing arguments through a parameter file. This is necessary because on Windows
|
||||
# there is an argument limit and we need to handle a large amount of input files. Bazel
|
||||
# switches between parameter file and normal argument passing based on the operating system.
|
||||
# Read more here: https://docs.bazel.build/versions/master/skylark/lib/Args.html#use_param_file
|
||||
args.use_param_file(param_file_arg = "--param-file=%s")
|
||||
|
||||
# Add the bazel bin directory to the command arguments. The script needs to know about
|
||||
# the output directory because the input files are not in the same location as the bazel
|
||||
# bin directory.
|
||||
args.add(ctx.bin_dir.path)
|
||||
|
||||
for input_file in input_files:
|
||||
# Extension of the input file (e.g. "ts" or "css")
|
||||
file_extension = input_file.extension
|
||||
|
||||
# Determine the input file path relatively to the current package path. This is necessary
|
||||
# because we want to preserve directories for the input files and `declare_file` expects a
|
||||
# path that is relative to the current package. We remove the file extension including the dot
|
||||
# because we will constructo an output file using a different extension.
|
||||
relative_basepath = _relative_to_label(ctx.label, input_file.short_path)[
|
||||
:-len(file_extension) - 1]
|
||||
|
||||
# Construct the output path from the relative basepath and file extension. For example:
|
||||
# "autocomplete.ts" should result in "autocomplete-ts.html".
|
||||
expected_outputs += [
|
||||
ctx.actions.declare_file("%s-%s.html" % (relative_basepath, file_extension)),
|
||||
]
|
||||
|
||||
# Add the path for the input file to the command line arguments, so that the executable
|
||||
# can process it.
|
||||
args.add(input_file.path)
|
||||
|
||||
# Run the highlight-files executable that highlights the specified source files.
|
||||
ctx.actions.run(
|
||||
inputs = input_files,
|
||||
executable = ctx.executable._highlight_files,
|
||||
outputs = expected_outputs,
|
||||
arguments = [args],
|
||||
)
|
||||
|
||||
return DefaultInfo(files = depset(expected_outputs))
|
||||
|
||||
"""
|
||||
Rule definition for the "highlight_files" rule that can accept arbritary source files
|
||||
that will be transformed into HTML files which reflect the highlighted source code of
|
||||
the given files. The outputs can be referenced through the default output provider.
|
||||
"""
|
||||
highlight_files = rule(
|
||||
implementation = _highlight_files,
|
||||
attrs = {
|
||||
"srcs": attr.label_list(allow_files = True),
|
||||
|
||||
# Executable for this rule that is responsible for highlighting the specified
|
||||
# input files.
|
||||
"_highlight_files": attr.label(
|
||||
default = Label("//tools/highlight-files"),
|
||||
executable = True,
|
||||
cfg = "host"
|
||||
)},
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["es2015"],
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"sourceMap": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"bazelOptions": {
|
||||
"suppressTsconfigOverrideWarnings": true
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,8 @@ ts_library(
|
||||
srcs = glob(["**/*.ts"]),
|
||||
deps = [
|
||||
"@matdeps//@types/node",
|
||||
"@matdeps//@types/marked"
|
||||
"@matdeps//@types/marked",
|
||||
"//tools/highlight-files:sources",
|
||||
],
|
||||
tsconfig = ":tsconfig.json",
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {MarkedOptions, Renderer} from 'marked';
|
||||
import {Renderer} from 'marked';
|
||||
import {basename, extname} from 'path';
|
||||
import {highlightCodeBlock} from './highlight-code-block';
|
||||
|
||||
/** Regular expression that matches whitespace. */
|
||||
const whitespaceRegex = /\W+/g;
|
||||
@@ -14,10 +13,6 @@ const exampleCommentRegex = /<!--\W*example\(([^)]+)\)\W*-->/g;
|
||||
*/
|
||||
export class DocsMarkdownRenderer extends Renderer {
|
||||
|
||||
constructor(options?: MarkedOptions) {
|
||||
super({highlight: highlightCodeBlock, baseUrl: 'material.angular.io/', ...options});
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a markdown heading into the corresponding HTML output. In our case, we
|
||||
* want to create a header-link for each H3 and H4 heading. This allows users to jump to
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
*/
|
||||
|
||||
import {readFileSync, writeFileSync} from 'fs';
|
||||
import {join} from 'path';
|
||||
import {DocsMarkdownRenderer} from './docs-marked-renderer';
|
||||
import * as marked from 'marked';
|
||||
import {join} from 'path';
|
||||
import {highlightCodeBlock} from '../highlight-files/highlight-code-block';
|
||||
import {DocsMarkdownRenderer} from './docs-marked-renderer';
|
||||
|
||||
// Regular expression that matches the markdown extension of a given path.
|
||||
const markdownExtension = /.md$/;
|
||||
@@ -15,7 +16,7 @@ const markdownExtension = /.md$/;
|
||||
const markdownRenderer = new DocsMarkdownRenderer();
|
||||
|
||||
// Setup our custom docs renderer by default.
|
||||
marked.setOptions({renderer: markdownRenderer});
|
||||
marked.setOptions({renderer: markdownRenderer, highlight: highlightCodeBlock});
|
||||
|
||||
if (require.main === module) {
|
||||
// The script expects the bazel-bin path as first argument. All remaining arguments will be
|
||||
|
||||
Reference in New Issue
Block a user