From 64db486edcc371cb699985fa5f252f8da81505ee Mon Sep 17 00:00:00 2001 From: Jeremy Elbourn Date: Tue, 31 Oct 2023 18:02:22 -0700 Subject: [PATCH] build: add rules for generating block/element API data (#52480) Adds build rules for "artificially" generating `DocEntry` collections for block and element APIs. The two rules are very similar, but _just_ different enough that it's worth having two separate implementations. PR Close #52480 --- .pullapprove.yml | 3 +- tools/manual_api_docs/BUILD.bazel | 37 ++++++ tools/manual_api_docs/blocks/BUILD.bazel | 6 + tools/manual_api_docs/blocks/defer.md | 63 ++++++++++ tools/manual_api_docs/blocks/for.md | 54 ++++++++ tools/manual_api_docs/blocks/if.md | 27 ++++ tools/manual_api_docs/blocks/switch.md | 29 +++++ tools/manual_api_docs/elements/BUILD.bazel | 6 + .../manual_api_docs/elements/ng-container.md | 119 ++++++++++++++++++ tools/manual_api_docs/elements/ng-content.md | 12 ++ tools/manual_api_docs/elements/ng-template.md | 66 ++++++++++ .../generate_block_api_json.bzl | 54 ++++++++ .../generate_block_api_json.ts | 33 +++++ .../generate_element_api_json.bzl | 54 ++++++++ .../generate_element_api_json.ts | 33 +++++ tools/manual_api_docs/test/BUILD.bazel | 12 ++ tools/manual_api_docs/test/dummy.md | 1 + tools/tsconfig.json | 7 +- 18 files changed, 613 insertions(+), 3 deletions(-) create mode 100644 tools/manual_api_docs/BUILD.bazel create mode 100644 tools/manual_api_docs/blocks/BUILD.bazel create mode 100644 tools/manual_api_docs/blocks/defer.md create mode 100644 tools/manual_api_docs/blocks/for.md create mode 100644 tools/manual_api_docs/blocks/if.md create mode 100644 tools/manual_api_docs/blocks/switch.md create mode 100644 tools/manual_api_docs/elements/BUILD.bazel create mode 100644 tools/manual_api_docs/elements/ng-container.md create mode 100644 tools/manual_api_docs/elements/ng-content.md create mode 100644 tools/manual_api_docs/elements/ng-template.md create mode 100644 tools/manual_api_docs/generate_block_api_json.bzl create mode 100644 tools/manual_api_docs/generate_block_api_json.ts create mode 100644 tools/manual_api_docs/generate_element_api_json.bzl create mode 100644 tools/manual_api_docs/generate_element_api_json.ts create mode 100644 tools/manual_api_docs/test/BUILD.bazel create mode 100644 tools/manual_api_docs/test/dummy.md diff --git a/.pullapprove.yml b/.pullapprove.yml index 530e0de5ecf..21f2fd7e9e9 100644 --- a/.pullapprove.yml +++ b/.pullapprove.yml @@ -1168,10 +1168,11 @@ groups: 'tools/esm-interop/**/{*,.*}', 'tools/gulp-tasks/**/{*,.*}', 'tools/legacy-saucelabs/**/{*,.*}', + 'tools/manual_api_docs/**/{*,.*}', 'tools/npm-patches/**/{*,.*}', 'tools/rxjs/**/{*,.*}', - 'tools/saucelabs/**/{*,.*}', 'tools/saucelabs-daemon/**/{*,.*}', + 'tools/saucelabs/**/{*,.*}', 'tools/symbol-extractor/**/{*,.*}', 'tools/testing/**/{*,.*}', 'tools/tslint/**/{*,.*}', diff --git a/tools/manual_api_docs/BUILD.bazel b/tools/manual_api_docs/BUILD.bazel new file mode 100644 index 00000000000..c7ed56acea3 --- /dev/null +++ b/tools/manual_api_docs/BUILD.bazel @@ -0,0 +1,37 @@ +load("//tools:defaults.bzl", "nodejs_binary", "ts_library") + +package(default_visibility = ["//visibility:public"]) + +ts_library( + name = "generate_element_api_json_lib", + srcs = ["generate_element_api_json.ts"], + deps = [ + "//packages/compiler-cli", + "@npm//@types/node", + ], +) + +nodejs_binary( + name = "generate_element_api_json", + data = [ + ":generate_element_api_json_lib", + ], + entry_point = ":generate_element_api_json.ts", +) + +ts_library( + name = "generate_block_api_json_lib", + srcs = ["generate_block_api_json.ts"], + deps = [ + "//packages/compiler-cli", + "@npm//@types/node", + ], +) + +nodejs_binary( + name = "generate_block_api_json", + data = [ + ":generate_block_api_json_lib", + ], + entry_point = ":generate_block_api_json.ts", +) diff --git a/tools/manual_api_docs/blocks/BUILD.bazel b/tools/manual_api_docs/blocks/BUILD.bazel new file mode 100644 index 00000000000..c90da190f2a --- /dev/null +++ b/tools/manual_api_docs/blocks/BUILD.bazel @@ -0,0 +1,6 @@ +load("//tools/manual_api_docs:generate_block_api_json.bzl", "generate_block_api_json") + +generate_block_api_json( + name = "blocks", + srcs = glob(["*.md"]), +) diff --git a/tools/manual_api_docs/blocks/defer.md b/tools/manual_api_docs/blocks/defer.md new file mode 100644 index 00000000000..70b7908c26a --- /dev/null +++ b/tools/manual_api_docs/blocks/defer.md @@ -0,0 +1,63 @@ +A type of [block](api/core/defer) that can be used to defer load the JavaScript for components, +directives and pipes used inside a component template. + +## Syntax + +```html +@defer ( on ; when ; prefetch on ; prefetch when ) { + + +} @placeholder ( minimum? ) { + +

Placeholder

+} @loading ( minimum? ; after? ) { + + loading image +} @error { + +

An loading error occured

+} +``` + +## Description + +### Blocks + +Supported sections of a defer block. Note: only the @defer block template fragment is deferred +loaded. The remaining optional blocks are eagerly loaded. + +| block | Description | +|----------------|----------------------------------------------------------| +| `@defer` | The defer loaded block of content | +| `@placeholder` | Content shown prior to defer loading (Optional) | +| `@loading` | Content shown during defer loading (Optional) | +| `@error` | Content shown when defer loading errors occur (Optional) | + +

Triggers

+ +Triggers provide conditions for when defer loading occurs. Some allow a template reference variable +as an optional parameter. Separate multiple triggers with a semicolon. + +| trigger | Triggers... | +|---------------------------------|-----------------------------------------------| +| `on idle` | when the browser reports idle state (default) | +| `on viewport(?)` | when the element enters the viewport | +| `on interaction(?)` | when clicked, touched, or focused | +| `on hover(?)` | when element has been hovered | +| `on immediate` | when the page finishes rendering | +| `on timer()` | after a specific timeout | +| `when ` | on a custom condition | + +

Prefetch

+ +Configures prefetching of the defer block used in the `@defer` parameters, but does not affect +rendering. Rendering is handled by the standard `on` and `when` conditions. Separate multiple +prefetch configurations with a semicolon. + +```html +@defer (prefetch on ; prefetch when ) { + +} +``` + +Learn more in the [defer loading guide](guide/defer). diff --git a/tools/manual_api_docs/blocks/for.md b/tools/manual_api_docs/blocks/for.md new file mode 100644 index 00000000000..e36458db8c9 --- /dev/null +++ b/tools/manual_api_docs/blocks/for.md @@ -0,0 +1,54 @@ +The `@for` block repeatedly renders content of a block for each item in a collection. + +## Syntax + +```html +@for (item of items; track item.name) { +
  • {{ item.name }}
  • +} @empty { +
  • There are no items.
  • +} +``` + +## Description + +The `@for` block renders its content in response to changes in a collection. Collections can be any +JavaScript [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols), +but there are performance advantages of using a regular `Array`. + +You can optionally include an `@empty` section immediately after the `@for` block content. The +content of the `@empty` block displays when there are no items. + +

    track and objects identity

    + +The value of the `track` expression determines a key used to associate array items with the views in +the DOM. Having clear indication of the item identity allows Angular to execute a minimal set of DOM +operations as items are added, removed or moved in a collection. + +Loops over immutable data without `trackBy` as one of the most common causes for performance issues +across Angular applications. Because of the potential for poor performance, the `track` expression +is required for the `@for` loops. When in doubt, using `track $index` is a good default. + +

    `$index` and other contextual variables

    + +Inside `@for` contents, several implicit variables are always available: + +| Variable | Meaning | +| -------- | ------- | +| `$count` | Number of items in a collection iterated over | +| `$index` | Index of the current row | +| `$first` | Whether the current row is the first row | +| `$last` | Whether the current row is the last row | +| `$even` | Whether the current row index is even | +| `$odd` | Whether the current row index is odd | + +These variables are always available with these names, but can be aliased via a `let` segment: + +```html +@for (item of items; track item.id; let idx = $index, e = $even) { + Item #{{ idx }}: {{ item.name }} +} +``` + +The aliasing is especially useful in case of using nested `@for` blocks where contextual variable +names could collide. diff --git a/tools/manual_api_docs/blocks/if.md b/tools/manual_api_docs/blocks/if.md new file mode 100644 index 00000000000..f3a49a82e65 --- /dev/null +++ b/tools/manual_api_docs/blocks/if.md @@ -0,0 +1,27 @@ +The `@if` block conditionally displays its content when its condition expression is truthy. + +## Syntax + +```html +@if (a > b) { + {{a}} is greater than {{b}} +} @else if (b > a) { + {{a}} is less than {{b}} +} @else { + {{a}} is equal to {{b}} +} +``` + +## Description + +Content is added and removed from the DOM based on the evaluation of conditional expressions in +the `@if` and `@else` blocks. + +The built-in `@if` supports referencing of expression results to keep a solution for common coding +patterns: + +```html +@if (users$ | async; as users) { + {{ users.length }} +} +``` diff --git a/tools/manual_api_docs/blocks/switch.md b/tools/manual_api_docs/blocks/switch.md new file mode 100644 index 00000000000..b36f3870234 --- /dev/null +++ b/tools/manual_api_docs/blocks/switch.md @@ -0,0 +1,29 @@ +The `@switch` block is inspired by the JavaScript `switch` statement: + +## Syntax + +```html +@switch (condition) { + @case (caseA) { + Case A. + } + @case (caseB) { + Case B. + } + @default { + Default case. + } +} +``` + +## Description + +The `@switch` blocks displays content selected by one of the cases matching against the conditional +expression. The value of the conditional expression is compared to the case expression using +the `===` operator. + +The `@default` block is optional and can be omitted. If no `@case` matches the expression and there +is no `@default` block, nothing is shown. + +**`@switch` does not have fallthrough**, so you do not need an equivalent to a `break` or `return` +statement. diff --git a/tools/manual_api_docs/elements/BUILD.bazel b/tools/manual_api_docs/elements/BUILD.bazel new file mode 100644 index 00000000000..75a0a2587cc --- /dev/null +++ b/tools/manual_api_docs/elements/BUILD.bazel @@ -0,0 +1,6 @@ +load("//tools/manual_api_docs:generate_element_api_json.bzl", "generate_element_api_json") + +generate_element_api_json( + name = "elements", + srcs = glob(["*.md"]), +) diff --git a/tools/manual_api_docs/elements/ng-container.md b/tools/manual_api_docs/elements/ng-container.md new file mode 100644 index 00000000000..6cf6beaaae6 --- /dev/null +++ b/tools/manual_api_docs/elements/ng-container.md @@ -0,0 +1,119 @@ +A special element that can hold structural directives without adding new elements to the DOM. + +The `` allows us to use structural directives without any extra element, making sure +that the only DOM changes being applied are those dictated by the directives themselves. + +This not only increases performance \(even so slightly\) since the browser ends up rendering less +elements but can also be a valuable asset in having cleaner DOMs and styles alike. + +It can for example enable us to use structural directives without breaking styling dependent on a +precise DOM structure \(as for example the ones we get when using flex containers, margins, the +child combinator selector, etc.\). + +## Usage notes + +### With `*NgIf`s + +One common use case of `` is alongside the `*ngIf` structural directive. By using the +special element we can produce very clean templates easy to understand and work with. + +For example, we may want to have a number of elements shown conditionally but they do not need to be +all under the same root element. That can be easily done by wrapping them in such a block: + + + +<ng-container *ngIf="condition"> + … +</ng-container> + + + +This can also be augmented with an `else` statement alongside an `` as: + + + +<ng-container *ngIf="condition; else templateA"> + … +</ng-container> +<ng-template #templateA> + … +</ng-template> + + + +### Combination of multiple structural directives + +Multiple structural directives cannot be used on the same element; if you need to take advantage of +more than one structural directive, it is advised to use an `` per structural +directive. + +The most common scenario is with `*ngIf` and `*ngFor`. For example, let's imagine that we have a +list of items but each item needs to be displayed only if a certain condition is true. We could be +tempted to try something like: + + + +<ul> + <li *ngFor="let item of items" *ngIf="item.isValid"> + {{ item.name }} + </li> +</ul> + + + +As we said that would not work, what we can do is to simply move one of the structural directives to +an `` element, which would then wrap the other one, like so: + + + +<ul> + <ng-container *ngFor="let item of items"> + <li *ngIf="item.isValid"> + {{ item.name }} + </li> + </ng-container> +</ul> + + + +This would work as intended without introducing any new unnecessary elements in the DOM. + +For more information see [one structural directive per element](guide/structural-directives#one-per-element). + +### Use alongside ngTemplateOutlet + +The `NgTemplateOutlet` directive can be applied to any element but most of the time it's applied +to `` ones. By combining the two, we get a very clear and easy to follow HTML and DOM +structure in which no extra elements are necessary and template views are instantiated where +requested. + +For example, imagine a situation in which we have a large HTML, in which a small portion needs to be +repeated in different places. A simple solution is to define an `` containing our +repeating HTML and render that where necessary by using `` alongside +an `NgTemplateOutlet`. + +Like so: + + + +<!-- … --> + +<ng-container *ngTemplateOutlet="tmpl; context: {$implicit: 'Hello'}"> +</ng-container> + +<!-- … --> + +<ng-container *ngTemplateOutlet="tmpl; context: {$implicit: 'World'}"> +</ng-container> + +<!-- … --> + +<ng-template #tmpl let-text> + <h1>{{ text }}</h1> +</ng-template> + + + +For more information regarding `NgTemplateOutlet`, see +the [`NgTemplateOutlet`s api documentation page](api/common/NgTemplateOutlet). + diff --git a/tools/manual_api_docs/elements/ng-content.md b/tools/manual_api_docs/elements/ng-content.md new file mode 100644 index 00000000000..817c2a114d4 --- /dev/null +++ b/tools/manual_api_docs/elements/ng-content.md @@ -0,0 +1,12 @@ +The `` element specifies where to project content inside a component template. + +## Attributes + +| Attribute | Description | +|---------------|-------------------------------------------------------------------------| +| `select` | CSS selector. Matching elements are projected into this ``. | + +Only select elements from the projected content that match the given CSS `selector`. + +Angular supports [selectors](https://developer.mozilla.org/docs/Web/CSS/CSS_Selectors) for any +combination of tag name, attribute, CSS class, and the `:not` pseudo-class. diff --git a/tools/manual_api_docs/elements/ng-template.md b/tools/manual_api_docs/elements/ng-template.md new file mode 100644 index 00000000000..b29a0e3a1ff --- /dev/null +++ b/tools/manual_api_docs/elements/ng-template.md @@ -0,0 +1,66 @@ +Angular's `` element defines a template that is not rendered by default. + +With ``, you can define template content that is only being rendered by Angular when +you, whether directly or indirectly, specifically instruct it to do so, allowing you to have full +control over how and when the content is displayed. + +
    + + Note that if you wrap content inside an `` without instructing Angular to render it, + such content will not appear on a page. For example, see the following HTML code, when handling it + Angular won't render the middle "Hip!" in the phrase "Hip! Hip! Hooray!" because of the + surrounding ``. + + ```html +

    Hip!

    + +

    Hip!

    +
    +

    Hooray!

    + ``` + +
    + + +## Usage notes + +### Structural Directives + +One of the main uses for `` is to hold template content that will be used +by [Structural directives](guide/structural-directives). Those directives can add and remove copies +of the template content based on their own logic. + +When using +the [structural directive shorthand](guide/structural-directives#structural-directive-shorthand), +Angular creates an `` element behind the scenes. + +### TemplateRef + +`` elements are represented as instances of the `TemplateRef` class. + +To add copies of the template to the DOM, pass this object to the `ViewContainerRef` +method `createEmbeddedView()`. + +### Template Variables + +`` elements can be referenced in templates +using [standard template variables](guide/template-reference-variables#how-angular-assigns-values-to-template-variables). + +*This is how `` elements are used as `ngIf` else clauses.* + +Such template variables can be used in conjunction with `ngTemplateOutlet` directives to render the +content defined inside `` tags. + +### Querying + +A [Query](api/core/Query) \(such as `ViewChild`\) can find the `TemplateRef` associated to +an `` element so that it can be used programmatically; for instance, to pass it to +the `ViewContainerRef` method `createEmbeddedView()`. + +### Context + +Inside the `` tags you can reference variables present in the surrounding outer +template. +Additionally, a context object can be associated with `` elements. +Such an object contains variables that can be accessed from within the template contents via +template \(`let` and `as`\) declarations. diff --git a/tools/manual_api_docs/generate_block_api_json.bzl b/tools/manual_api_docs/generate_block_api_json.bzl new file mode 100644 index 00000000000..668a9124b39 --- /dev/null +++ b/tools/manual_api_docs/generate_block_api_json.bzl @@ -0,0 +1,54 @@ +load("@build_bazel_rules_nodejs//:providers.bzl", "run_node") + +def _generate_block_api_json(ctx): + """Implementation of the generate_block_api_json rule""" + + # Define arguments that will be passed to the underlying nodejs program. + args = ctx.actions.args() + + # Use a param file for consistency with other doc generation rules. + args.set_param_file_format("multiline") + args.use_param_file("%s", use_always = True) + + # Pass the set of source files from which the API data will be generated. + args.add_joined(ctx.files.srcs, join_with = ",") + + # Pass the name of the output JSON file. + manifest = ctx.actions.declare_file("blocks.json") + args.add(manifest.path) + + # Define an action that runs the nodejs_binary executable. This is + # the main thing that this rule does. + run_node( + ctx = ctx, + inputs = depset(ctx.files.srcs), + executable = "_generate_block_api_json", + outputs = [manifest], + arguments = [args], + ) + + # The return value describes what the rule is producing. In this case we need to specify + # the "DefaultInfo" with the output JSON manifest. + return [DefaultInfo(files = depset([manifest]))] + +generate_block_api_json = rule( + # Point to the starlark function that will execute for this rule. + implementation = _generate_block_api_json, + doc = """Rule that generates an Angular API doc collection for hand-written block APIs""", + + # The attributes that can be set to this rule. + attrs = { + "srcs": attr.label_list( + doc = """The source files for this rule, must include one or more markdown files.""", + allow_empty = False, + allow_files = True, + ), + + # The executable for this rule (private). + "_generate_block_api_json": attr.label( + default = Label("//tools/manual_api_docs:generate_block_api_json"), + executable = True, + cfg = "exec", + ), + }, +) diff --git a/tools/manual_api_docs/generate_block_api_json.ts b/tools/manual_api_docs/generate_block_api_json.ts new file mode 100644 index 00000000000..d405817cbbd --- /dev/null +++ b/tools/manual_api_docs/generate_block_api_json.ts @@ -0,0 +1,33 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {DocEntry, EntryType} from '@angular/compiler-cli'; +import {readFileSync, writeFileSync} from 'fs'; +import {basename} from 'path'; + +function main() { + const [paramFilePath] = process.argv.slice(2); + const rawParamLines = readFileSync(paramFilePath, {encoding: 'utf8'}).split('\n'); + const [srcs, outputFileExecRootRelativePath] = rawParamLines; + + const entries: DocEntry[] = srcs.split(',').map(sourceFilePath => { + const fileContent = readFileSync(sourceFilePath, {encoding: 'utf8'}); + + return { + name: `@${basename(sourceFilePath, '.md')}`, + entryType: EntryType.Block, + description: fileContent, + rawComment: fileContent, + jsdocTags: [], + }; + }); + + writeFileSync(outputFileExecRootRelativePath, JSON.stringify(entries), {encoding: 'utf8'}); +} + +main(); diff --git a/tools/manual_api_docs/generate_element_api_json.bzl b/tools/manual_api_docs/generate_element_api_json.bzl new file mode 100644 index 00000000000..0bae6e1fd50 --- /dev/null +++ b/tools/manual_api_docs/generate_element_api_json.bzl @@ -0,0 +1,54 @@ +load("@build_bazel_rules_nodejs//:providers.bzl", "run_node") + +def _generate_element_api_json(ctx): + """Implementation of the generate_element_api_json rule""" + + # Define arguments that will be passed to the underlying nodejs program. + args = ctx.actions.args() + + # Use a param file for consistency with other doc generation rules. + args.set_param_file_format("multiline") + args.use_param_file("%s", use_always = True) + + # Pass the set of source files from which the API data will be generated. + args.add_joined(ctx.files.srcs, join_with = ",") + + # Pass the name of the output JSON file. + manifest = ctx.actions.declare_file("elements.json") + args.add(manifest.path) + + # Define an action that runs the nodejs_binary executable. This is + # the main thing that this rule does. + run_node( + ctx = ctx, + inputs = depset(ctx.files.srcs), + executable = "_generate_element_api_json", + outputs = [manifest], + arguments = [args], + ) + + # The return value describes what the rule is producing. In this case we need to specify + # the "DefaultInfo" with the output JSON manifest. + return [DefaultInfo(files = depset([manifest]))] + +generate_element_api_json = rule( + # Point to the starlark function that will execute for this rule. + implementation = _generate_element_api_json, + doc = """Rule that generates an Angular API doc collection for hand-written element APIs""", + + # The attributes that can be set to this rule. + attrs = { + "srcs": attr.label_list( + doc = """The source files for this rule, must include one or more markdown files.""", + allow_empty = False, + allow_files = True, + ), + + # The executable for this rule (private). + "_generate_element_api_json": attr.label( + default = Label("//tools/manual_api_docs:generate_element_api_json"), + executable = True, + cfg = "exec", + ), + }, +) diff --git a/tools/manual_api_docs/generate_element_api_json.ts b/tools/manual_api_docs/generate_element_api_json.ts new file mode 100644 index 00000000000..c1fce94b871 --- /dev/null +++ b/tools/manual_api_docs/generate_element_api_json.ts @@ -0,0 +1,33 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {DocEntry, EntryType} from '@angular/compiler-cli'; +import {readFileSync, writeFileSync} from 'fs'; +import {basename} from 'path'; + +function main() { + const [paramFilePath] = process.argv.slice(2); + const rawParamLines = readFileSync(paramFilePath, {encoding: 'utf8'}).split('\n'); + const [srcs, outputFileExecRootRelativePath] = rawParamLines; + + const entries: DocEntry[] = srcs.split(',').map(sourceFilePath => { + const fileContent = readFileSync(sourceFilePath, {encoding: 'utf8'}); + + return { + name: basename(sourceFilePath, '.md'), + entryType: EntryType.Element, + description: fileContent, + rawComment: fileContent, + jsdocTags: [], + }; + }); + + writeFileSync(outputFileExecRootRelativePath, JSON.stringify(entries), {encoding: 'utf8'}); +} + +main(); diff --git a/tools/manual_api_docs/test/BUILD.bazel b/tools/manual_api_docs/test/BUILD.bazel new file mode 100644 index 00000000000..861fe4097e3 --- /dev/null +++ b/tools/manual_api_docs/test/BUILD.bazel @@ -0,0 +1,12 @@ +load("//tools/manual_api_docs:generate_element_api_json.bzl", "generate_element_api_json") +load("//tools/manual_api_docs:generate_block_api_json.bzl", "generate_block_api_json") + +generate_element_api_json( + name = "element_test", + srcs = ["dummy.md"], +) + +generate_block_api_json( + name = "block_test", + srcs = ["dummy.md"], +) diff --git a/tools/manual_api_docs/test/dummy.md b/tools/manual_api_docs/test/dummy.md new file mode 100644 index 00000000000..10197901c26 --- /dev/null +++ b/tools/manual_api_docs/test/dummy.md @@ -0,0 +1 @@ +## This is the content of the file diff --git a/tools/tsconfig.json b/tools/tsconfig.json index 4da6132edaf..b234e0e3f4a 100644 --- a/tools/tsconfig.json +++ b/tools/tsconfig.json @@ -1,4 +1,5 @@ { + // This tsconfig is only used by IDEs, no actual builds. "compilerOptions": { "baseUrl": ".", "declaration": true, @@ -10,8 +11,10 @@ "outDir": "../dist/tools/", "noImplicitAny": true, "noFallthroughCasesInSwitch": true, - "paths": {}, - "rootDir": ".", + "paths": { + "@angular/*": ["../packages/*"] + }, + "rootDirs": [".", ".."], "sourceMap": true, "inlineSources": true, "lib": [