Reference configs

angular/angular: 3 sources hide a byte-order mark

In Angular, 3 TypeScript sources start with an invisible UTF-8 byte-order mark before their @license header. tslint's header rule accepts them; alint's file_header rule reads the first bytes as they are.This config was written to test alint; Angular doesn't use alint.

What alint found

.alint.yml
- id: angular-source-license-header
  kind: file_header
  paths:
    include:
      - "packages/*/index.ts"
      - "packages/*/public_api.ts"
      - "packages/*/src/**/*.ts"
    exclude:
      - "packages/*/src/**/*.d.ts"
      - "packages/*/src/**/*.generated.ts"
      - "packages/*/test/**"
  pattern: '(?s)^/\*[*!]\s*\n\s*\*\s*@license\s*\n\s*\*\s*Copyright\s+Google\s+LLC\b'
  level: warning

⚠︎ warning angular-source-license-header

Three files start with a byte-order mark before the header, among them packages/core/src/defer/interfaces.ts.

⚠︎ warning angular-source-license-header

The header of packages/compiler/src/template/pipeline/src/emit.ts starts with an extra blank line.

The config

Angular's 15 framework packages follow one layout that no check in its CI covers: a scoped package.json with the MIT license and the version 0.0.0-PLACEHOLDER, an entry point, an API barrel, a Bazel build file and an API golden. The other two packages under packages/, benchpress and zone.js, are versioned on their own. The config checks that layout one convention at a time, along with the @license header, the tool configs and the husky hooks. tslint, the format check and the API check run from command_idempotent rules.

.alint.yml
- id: angular-package-version-is-placeholder
  # fixed here: benchpress and zone.js keep versions of their own
  kind: for_each_dir
  select: ["packages/*", "!packages/benchpress", "!packages/zone.js"]
  when_iter: 'iter.has_file("package.json")'
  require:
    - kind: json_path_matches
      paths: "{path}/package.json"
      path: "$.version"
      matches: '^0\.0\.0-PLACEHOLDER$'
  level: error

Every framework package's version is 0.0.0-PLACEHOLDER until the release step replaces it. Nine more for_each_dir rules check the rest of the layout, from the scoped name to the API golden; all ten exclude benchpress and zone.js, which are versioned and structured separately.

.alint.yml
- id: angular-no-deep-cross-package-imports
  kind: import_gate
  language: js
  paths:
    include:
      - "packages/*/src/**/*.ts"
    exclude:
      - "packages/*/src/**/*.d.ts"
      - "packages/*/test/**"
      - "packages/**/testing/**"
  forbid: '^@angular/[a-z-]+/.*/(src|private)/'
  level: warning

Source in one package may not reach into another package's src/ or private/ directories. import_gate reads each import statement.

What stays outside alint

What needs the TypeScript syntax tree, Bazel or GitHub stays with Angular's tools:

  • the five custom tslint rules, the circular-import check and the API golden diff, which the config runs from command_idempotent rules, and the symbol extractor;
  • releases and pull-request merges, which change git state or call GitHub;
  • keeping the commit scopes in .ng-dev/commit-message.mjs in step with the package directories. The scopes live in a JavaScript export, which alint can't read;
  • checking that every golden still has a package, which needs a rule kind alint doesn't have.