Initial commit: notification-elements-demo app

Interactive Angular 19 demo for @sda/notification-elements-ui with
6 sections: Bell & Feed, Notification Center, Inbox, Comments &
Threads, Mention Input, and Full-Featured layout. Includes mock
data, dark mode toggle, and real-time event log.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Giuliano Silvestro
2026-02-13 21:49:19 +10:00
commit 5d0c9ec7eb
36473 changed files with 3778146 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
{
"schematics": {
"use-application-builder": {
"version": "19.0.0",
"factory": "./use-application-builder/migration",
"description": "Migrate application projects to the new build system. Application projects that are using the '@angular-devkit/build-angular' package's 'browser' and/or 'browser-esbuild' builders will be migrated to use the new 'application' builder. You can read more about this, including known issues and limitations, here: https://angular.dev/tools/cli/build-system-migration",
"optional": true,
"recommended": true,
"documentation": "tools/cli/build-system-migration"
},
"update-workspace-config": {
"version": "19.0.0",
"factory": "./update-workspace-config/migration",
"description": "Update the workspace configuration by replacing deprecated options in 'angular.json' for compatibility with the latest Angular CLI changes."
},
"update-ssr-imports": {
"version": "19.0.0",
"factory": "./update-ssr-imports/migration",
"description": "Update '@angular/ssr' import paths to use the new '/node' entry point when 'CommonEngine' is detected."
}
}
}

View File

@@ -0,0 +1,15 @@
/**
* @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.dev/license
*/
import { Rule } from '@angular-devkit/schematics';
/**
* Schematics rule that identifies and updates import declarations in TypeScript files.
* Specifically, it modifies imports of '@angular/ssr' by appending '/node' if the
* `CommonEngine` is used from the old entry point.
*
*/
export default function (): Rule;

View File

@@ -0,0 +1,107 @@
"use strict";
/**
* @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.dev/license
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = default_1;
const ts = __importStar(require("../../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
const dependencies_1 = require("../../utility/dependencies");
function* visit(directory) {
for (const path of directory.subfiles) {
if (path.endsWith('.ts') && !path.endsWith('.d.ts')) {
const entry = directory.file(path);
if (entry) {
const content = entry.content;
if (content.includes('CommonEngine') && !content.includes('@angular/ssr/node')) {
const source = ts.createSourceFile(entry.path, content.toString().replace(/^\uFEFF/, ''), ts.ScriptTarget.Latest, true);
yield source;
}
}
}
}
for (const path of directory.subdirs) {
if (path === 'node_modules' || path.startsWith('.')) {
continue;
}
yield* visit(directory.dir(path));
}
}
/**
* Schematics rule that identifies and updates import declarations in TypeScript files.
* Specifically, it modifies imports of '@angular/ssr' by appending '/node' if the
* `CommonEngine` is used from the old entry point.
*
*/
function default_1() {
return (tree) => {
if (!(0, dependencies_1.getPackageJsonDependency)(tree, '@angular/ssr')) {
return;
}
for (const sourceFile of visit(tree.root)) {
let recorder;
const allImportDeclarations = sourceFile.statements.filter((n) => ts.isImportDeclaration(n));
if (allImportDeclarations.length === 0) {
continue;
}
const ssrImports = allImportDeclarations.filter((n) => ts.isStringLiteral(n.moduleSpecifier) && n.moduleSpecifier.text === '@angular/ssr');
for (const ssrImport of ssrImports) {
const ssrNamedBinding = getNamedImports(ssrImport);
if (ssrNamedBinding) {
const isUsingOldEntryPoint = ssrNamedBinding.elements.some((e) => e.name.text.startsWith('CommonEngine'));
if (!isUsingOldEntryPoint) {
continue;
}
recorder ??= tree.beginUpdate(sourceFile.fileName);
recorder.insertRight(ssrImport.moduleSpecifier.getEnd() - 1, '/node');
}
}
if (recorder) {
tree.commitUpdate(recorder);
}
}
};
}
function getNamedImports(importDeclaration) {
const namedBindings = importDeclaration?.importClause?.namedBindings;
if (namedBindings && ts.isNamedImports(namedBindings)) {
return namedBindings;
}
return undefined;
}

View File

@@ -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.dev/license
*/
import { Rule } from '@angular-devkit/schematics';
/**
* Main entry point for the migration rule.
*
* This schematic migration performs updates to the Angular workspace configuration
* to ensure that application projects are properly configured with polyfills
* required for internationalization (`localize`).
*
* It specifically targets application projects that use either the `application`
* or `browser-esbuild` builders.
*
* The migration process involves:
*
* 1. Iterating over all projects in the workspace.
* 2. Checking each project to determine if it is an application-type project.
* 3. For each application project, examining the associated build targets.
* 4. If a build target's `localize` option is enabled but the polyfill
* `@angular/localize/init` is missing from the `polyfills` array, the polyfill
* is automatically added to ensure proper internationalization support.
*
* Additionally, this migration updates projects that use the `dev-server` or `extract-i18n`
* builders to ensure that deprecated `browserTarget` options are migrated to the
* newer `buildTarget` field.
*
*/
export default function (): Rule;

View File

@@ -0,0 +1,77 @@
"use strict";
/**
* @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.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = default_1;
const workspace_1 = require("../../utility/workspace");
const workspace_models_1 = require("../../utility/workspace-models");
/**
* Main entry point for the migration rule.
*
* This schematic migration performs updates to the Angular workspace configuration
* to ensure that application projects are properly configured with polyfills
* required for internationalization (`localize`).
*
* It specifically targets application projects that use either the `application`
* or `browser-esbuild` builders.
*
* The migration process involves:
*
* 1. Iterating over all projects in the workspace.
* 2. Checking each project to determine if it is an application-type project.
* 3. For each application project, examining the associated build targets.
* 4. If a build target's `localize` option is enabled but the polyfill
* `@angular/localize/init` is missing from the `polyfills` array, the polyfill
* is automatically added to ensure proper internationalization support.
*
* Additionally, this migration updates projects that use the `dev-server` or `extract-i18n`
* builders to ensure that deprecated `browserTarget` options are migrated to the
* newer `buildTarget` field.
*
*/
function default_1() {
return (0, workspace_1.updateWorkspace)((workspace) => {
for (const project of workspace.projects.values()) {
if (project.extensions.projectType !== workspace_models_1.ProjectType.Application) {
continue;
}
for (const target of project.targets.values()) {
if (target.builder === workspace_models_1.Builders.DevServer || target.builder === workspace_models_1.Builders.ExtractI18n) {
// Migrate `browserTarget` to `buildTarget`
for (const [, options] of (0, workspace_1.allTargetOptions)(target, false)) {
if (options['browserTarget'] && !options['buildTarget']) {
options['buildTarget'] = options['browserTarget'];
}
delete options['browserTarget'];
}
}
// Check if the target uses application-related builders
if (target.builder !== workspace_models_1.Builders.BuildApplication &&
target.builder !== workspace_models_1.Builders.Application &&
target.builder !== workspace_models_1.Builders.BrowserEsbuild) {
continue;
}
// Check if polyfills include '@angular/localize/init'
const polyfills = target.options?.['polyfills'];
if (Array.isArray(polyfills) &&
polyfills.some((polyfill) => typeof polyfill === 'string' && polyfill.startsWith('@angular/localize'))) {
// Skip if the polyfill is already present
continue;
}
// Add '@angular/localize/init' polyfill if localize option is enabled
for (const [, options] of (0, workspace_1.allTargetOptions)(target, false)) {
if (options['localize']) {
target.options ??= {};
(target.options['polyfills'] ??= []).push('@angular/localize/init');
break;
}
}
}
}
});
}

View File

@@ -0,0 +1,19 @@
/**
* @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.dev/license
*/
/**
* Scans a CSS or Sass file and locates all valid import/use directive values as defined by the
* syntax specification.
* @param contents A string containing a CSS or Sass file to scan.
* @returns An iterable that yields each CSS directive value found.
*/
export declare function findImports(contents: string, sass: boolean): Iterable<{
start: number;
end: number;
specifier: string;
fromUse?: boolean;
}>;

View File

@@ -0,0 +1,117 @@
"use strict";
/**
* @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.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.findImports = findImports;
/**
* Determines if a unicode code point is a CSS whitespace character.
* @param code The unicode code point to test.
* @returns true, if the code point is CSS whitespace; false, otherwise.
*/
function isWhitespace(code) {
// Based on https://www.w3.org/TR/css-syntax-3/#whitespace
switch (code) {
case 0x0009: // tab
case 0x0020: // space
case 0x000a: // line feed
case 0x000c: // form feed
case 0x000d: // carriage return
return true;
default:
return false;
}
}
/**
* Scans a CSS or Sass file and locates all valid import/use directive values as defined by the
* syntax specification.
* @param contents A string containing a CSS or Sass file to scan.
* @returns An iterable that yields each CSS directive value found.
*/
function* findImports(contents, sass) {
yield* find(contents, '@import ');
if (sass) {
for (const result of find(contents, '@use ')) {
yield { ...result, fromUse: true };
}
}
}
/**
* Scans a CSS or Sass file and locates all valid function/directive values as defined by the
* syntax specification.
* @param contents A string containing a CSS or Sass file to scan.
* @param prefix The prefix to start a valid segment.
* @returns An iterable that yields each CSS url function value found.
*/
function* find(contents, prefix) {
let pos = 0;
let width = 1;
let current = -1;
const next = () => {
pos += width;
current = contents.codePointAt(pos) ?? -1;
width = current > 0xffff ? 2 : 1;
return current;
};
// Based on https://www.w3.org/TR/css-syntax-3/#consume-ident-like-token
while ((pos = contents.indexOf(prefix, pos)) !== -1) {
// Set to position of the last character in prefix
pos += prefix.length - 1;
width = 1;
// Consume all leading whitespace
while (isWhitespace(next())) {
/* empty */
}
// Initialize URL state
const url = { start: pos, end: -1, specifier: '' };
let complete = false;
// If " or ', then consume the value as a string
if (current === 0x0022 || current === 0x0027) {
const ending = current;
// Based on https://www.w3.org/TR/css-syntax-3/#consume-string-token
while (!complete) {
switch (next()) {
case -1: // EOF
return;
case 0x000a: // line feed
case 0x000c: // form feed
case 0x000d: // carriage return
// Invalid
complete = true;
break;
case 0x005c: // \ -- character escape
// If not EOF or newline, add the character after the escape
switch (next()) {
case -1:
return;
case 0x000a: // line feed
case 0x000c: // form feed
case 0x000d: // carriage return
// Skip when inside a string
break;
default:
// TODO: Handle hex escape codes
url.specifier += String.fromCodePoint(current);
break;
}
break;
case ending:
// Full string position should include the quotes for replacement
url.end = pos + 1;
complete = true;
yield url;
break;
default:
url.specifier += String.fromCodePoint(current);
break;
}
}
next();
continue;
}
}
}

View File

@@ -0,0 +1,12 @@
/**
* @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.dev/license
*/
import { Rule } from '@angular-devkit/schematics';
/**
* Migration main entrypoint
*/
export default function (): Rule;

View File

@@ -0,0 +1,376 @@
"use strict";
/**
* @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.dev/license
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = default_1;
const schematics_1 = require("@angular-devkit/schematics");
const posix_1 = require("node:path/posix");
const dependencies_1 = require("../../utility/dependencies");
const dependency_1 = require("../../utility/dependency");
const json_file_1 = require("../../utility/json-file");
const latest_versions_1 = require("../../utility/latest-versions");
const workspace_1 = require("../../utility/workspace");
const workspace_models_1 = require("../../utility/workspace-models");
const css_import_lexer_1 = require("./css-import-lexer");
function* updateBuildTarget(projectName, buildTarget, serverTarget, tree, context) {
// Update builder target and options
buildTarget.builder = workspace_models_1.Builders.Application;
for (const [, options] of (0, workspace_1.allTargetOptions)(buildTarget, false)) {
if (options['index'] === '') {
options['index'] = false;
}
// Rename and transform options
options['browser'] = options['main'];
if (serverTarget && typeof options['browser'] === 'string') {
options['server'] = (0, posix_1.dirname)(options['browser']) + '/main.server.ts';
}
options['serviceWorker'] = options['ngswConfigPath'] ?? options['serviceWorker'];
if (typeof options['polyfills'] === 'string') {
options['polyfills'] = [options['polyfills']];
}
let outputPath = options['outputPath'];
if (typeof outputPath === 'string') {
if (!/\/browser\/?$/.test(outputPath)) {
// TODO: add prompt.
context.logger.warn(`The output location of the browser build has been updated from "${outputPath}" to ` +
`"${(0, posix_1.join)(outputPath, 'browser')}". ` +
'You might need to adjust your deployment pipeline or, as an alternative, ' +
'set outputPath.browser to "" in order to maintain the previous functionality.');
}
else {
outputPath = outputPath.replace(/\/browser\/?$/, '');
}
options['outputPath'] = {
base: outputPath,
};
if (typeof options['resourcesOutputPath'] === 'string') {
const media = options['resourcesOutputPath'].replaceAll('/', '');
if (media && media !== 'media') {
options['outputPath'] = {
base: outputPath,
media,
};
}
}
}
// Delete removed options
delete options['vendorChunk'];
delete options['commonChunk'];
delete options['resourcesOutputPath'];
delete options['buildOptimizer'];
delete options['main'];
delete options['ngswConfigPath'];
}
// Merge browser and server tsconfig
if (serverTarget) {
const browserTsConfig = buildTarget.options?.tsConfig;
const serverTsConfig = serverTarget.options?.tsConfig;
if (typeof browserTsConfig !== 'string') {
throw new schematics_1.SchematicsException(`Cannot update project "${projectName}" to use the application builder` +
` as the browser tsconfig cannot be located.`);
}
if (typeof serverTsConfig !== 'string') {
throw new schematics_1.SchematicsException(`Cannot update project "${projectName}" to use the application builder` +
` as the server tsconfig cannot be located.`);
}
const browserJson = new json_file_1.JSONFile(tree, browserTsConfig);
const serverJson = new json_file_1.JSONFile(tree, serverTsConfig);
const filesPath = ['files'];
const files = new Set([
...(browserJson.get(filesPath) ?? []),
...(serverJson.get(filesPath) ?? []),
]);
// Server file will be added later by the means of the ssr schematic.
files.delete('server.ts');
browserJson.modify(filesPath, Array.from(files));
const typesPath = ['compilerOptions', 'types'];
browserJson.modify(typesPath, Array.from(new Set([
...(browserJson.get(typesPath) ?? []),
...(serverJson.get(typesPath) ?? []),
])));
// Delete server tsconfig
yield deleteFile(serverTsConfig);
}
// Update server file
const ssrMainFile = serverTarget?.options?.['main'];
if (typeof ssrMainFile === 'string') {
// Do not delete the server main file if it's the same as the browser file.
if (buildTarget.options?.browser !== ssrMainFile) {
yield deleteFile(ssrMainFile);
}
yield (0, schematics_1.externalSchematic)('@schematics/angular', 'ssr', {
project: projectName,
skipInstall: true,
});
}
}
function updateProjects(tree, context) {
return (0, workspace_1.updateWorkspace)((workspace) => {
const rules = [];
for (const [name, project] of workspace.projects) {
if (project.extensions.projectType !== workspace_models_1.ProjectType.Application) {
// Only interested in application projects since these changes only effects application builders
continue;
}
const buildTarget = project.targets.get('build');
if (!buildTarget || buildTarget.builder === workspace_models_1.Builders.Application) {
continue;
}
if (buildTarget.builder !== workspace_models_1.Builders.BrowserEsbuild &&
buildTarget.builder !== workspace_models_1.Builders.Browser) {
context.logger.error(`Cannot update project "${name}" to use the application builder.` +
` Only "${workspace_models_1.Builders.BrowserEsbuild}" and "${workspace_models_1.Builders.Browser}" can be automatically migrated.`);
continue;
}
const serverTarget = project.targets.get('server');
rules.push(...updateBuildTarget(name, buildTarget, serverTarget, tree, context));
// Delete all redundant targets
for (const [key, target] of project.targets) {
switch (target.builder) {
case workspace_models_1.Builders.Server:
case workspace_models_1.Builders.Prerender:
case workspace_models_1.Builders.AppShell:
case workspace_models_1.Builders.SsrDevServer:
project.targets.delete(key);
break;
}
}
// Update CSS/Sass import specifiers
const projectSourceRoot = (0, posix_1.join)(project.root, project.sourceRoot ?? 'src');
updateStyleImports(tree, projectSourceRoot, buildTarget);
}
// Check for @angular-devkit/build-angular Webpack usage
let hasAngularDevkitUsage = false;
for (const [, target] of (0, workspace_1.allWorkspaceTargets)(workspace)) {
switch (target.builder) {
case workspace_models_1.Builders.Application:
case workspace_models_1.Builders.DevServer:
case workspace_models_1.Builders.ExtractI18n:
case workspace_models_1.Builders.NgPackagr:
// Ignore application, dev server, and i18n extraction for devkit usage check.
// Both will be replaced if no other usage is found.
continue;
}
if (target.builder.startsWith('@angular-devkit/build-angular:')) {
hasAngularDevkitUsage = true;
break;
}
}
// Use @angular/build directly if there is no devkit package usage
if (!hasAngularDevkitUsage) {
for (const [, target] of (0, workspace_1.allWorkspaceTargets)(workspace)) {
switch (target.builder) {
case workspace_models_1.Builders.Application:
target.builder = '@angular/build:application';
break;
case workspace_models_1.Builders.DevServer:
target.builder = '@angular/build:dev-server';
break;
case workspace_models_1.Builders.ExtractI18n:
target.builder = '@angular/build:extract-i18n';
break;
case workspace_models_1.Builders.NgPackagr:
target.builder = '@angular/build:ng-packagr';
break;
}
}
// Add direct @angular/build dependencies and remove @angular-devkit/build-angular
rules.push((0, dependency_1.addDependency)('@angular/build', latest_versions_1.latestVersions.DevkitBuildAngular, {
type: dependency_1.DependencyType.Dev,
// Always is set here since removePackageJsonDependency below does not automatically
// trigger the package manager execution.
install: dependency_1.InstallBehavior.Always,
existing: dependency_1.ExistingBehavior.Replace,
}));
(0, dependencies_1.removePackageJsonDependency)(tree, '@angular-devkit/build-angular');
// Add less dependency if any projects contain a Less stylesheet file.
// This check does not consider Node.js packages due to the performance
// cost of searching such a large directory structure. A build time error
// will provide instructions to install the package in this case.
if (hasLessStylesheets(tree)) {
rules.push((0, dependency_1.addDependency)('less', latest_versions_1.latestVersions['less'], {
type: dependency_1.DependencyType.Dev,
existing: dependency_1.ExistingBehavior.Skip,
}));
}
// Add postcss dependency if any projects have a custom postcss configuration file.
// The build system only supports files in a project root or workspace root with
// names of either 'postcss.config.json' or '.postcssrc.json'.
if (hasPostcssConfiguration(tree, workspace)) {
rules.push((0, dependency_1.addDependency)('postcss', latest_versions_1.latestVersions['postcss'], {
type: dependency_1.DependencyType.Dev,
existing: dependency_1.ExistingBehavior.Replace,
}));
}
}
return (0, schematics_1.chain)(rules);
});
}
/**
* Searches the schematic tree for files that have a `.less` extension.
*
* @param tree A Schematics tree instance to search
* @returns true if Less stylesheet files are found; otherwise, false
*/
function hasLessStylesheets(tree) {
const directories = [tree.getDir('/')];
let current;
while ((current = directories.pop())) {
for (const path of current.subfiles) {
if (path.endsWith('.less')) {
return true;
}
}
for (const path of current.subdirs) {
if (path === 'node_modules' || path.startsWith('.')) {
continue;
}
directories.push(current.dir(path));
}
}
}
/**
* Searches for a Postcss configuration file within the workspace root
* or any of the project roots.
*
* @param tree A Schematics tree instance to search
* @param workspace A Workspace to check for projects
* @returns true, if a Postcss configuration file is found; otherwise, false
*/
function hasPostcssConfiguration(tree, workspace) {
// Add workspace root
const searchDirectories = [''];
// Add each project root
for (const { root } of workspace.projects.values()) {
if (root) {
searchDirectories.push(root);
}
}
return searchDirectories.some((dir) => tree.exists((0, posix_1.join)(dir, 'postcss.config.json')) || tree.exists((0, posix_1.join)(dir, '.postcssrc.json')));
}
function* visit(directory) {
for (const path of directory.subfiles) {
const sass = path.endsWith('.scss');
if (path.endsWith('.css') || sass) {
const entry = directory.file(path);
if (entry) {
const content = entry.content;
yield [entry.path, content.toString(), sass];
}
}
}
for (const path of directory.subdirs) {
if (path === 'node_modules' || path.startsWith('.')) {
continue;
}
yield* visit(directory.dir(path));
}
}
// Based on https://github.com/sass/dart-sass/blob/44d6bb6ac72fe6b93f5bfec371a1fffb18e6b76d/lib/src/importer/utils.dart
function* potentialSassImports(specifier, base, fromImport) {
const directory = (0, posix_1.join)(base, (0, posix_1.dirname)(specifier));
const extension = (0, posix_1.extname)(specifier);
const hasStyleExtension = extension === '.scss' || extension === '.sass' || extension === '.css';
// Remove the style extension if present to allow adding the `.import` suffix
const filename = (0, posix_1.basename)(specifier, hasStyleExtension ? extension : undefined);
if (hasStyleExtension) {
if (fromImport) {
yield (0, posix_1.join)(directory, filename + '.import' + extension);
yield (0, posix_1.join)(directory, '_' + filename + '.import' + extension);
}
yield (0, posix_1.join)(directory, filename + extension);
yield (0, posix_1.join)(directory, '_' + filename + extension);
}
else {
if (fromImport) {
yield (0, posix_1.join)(directory, filename + '.import.scss');
yield (0, posix_1.join)(directory, filename + '.import.sass');
yield (0, posix_1.join)(directory, filename + '.import.css');
yield (0, posix_1.join)(directory, '_' + filename + '.import.scss');
yield (0, posix_1.join)(directory, '_' + filename + '.import.sass');
yield (0, posix_1.join)(directory, '_' + filename + '.import.css');
}
yield (0, posix_1.join)(directory, filename + '.scss');
yield (0, posix_1.join)(directory, filename + '.sass');
yield (0, posix_1.join)(directory, filename + '.css');
yield (0, posix_1.join)(directory, '_' + filename + '.scss');
yield (0, posix_1.join)(directory, '_' + filename + '.sass');
yield (0, posix_1.join)(directory, '_' + filename + '.css');
}
}
function updateStyleImports(tree, projectSourceRoot, buildTarget) {
const external = new Set();
let needWorkspaceIncludePath = false;
for (const file of visit(tree.getDir(projectSourceRoot))) {
const [path, content, sass] = file;
const relativeBase = (0, posix_1.dirname)(path);
let updater;
for (const { start, specifier, fromUse } of (0, css_import_lexer_1.findImports)(content, sass)) {
if (specifier[0] === '~') {
updater ??= tree.beginUpdate(path);
// start position includes the opening quote
updater.remove(start + 1, 1);
}
else if (specifier[0] === '^') {
updater ??= tree.beginUpdate(path);
// start position includes the opening quote
updater.remove(start + 1, 1);
// Add to externalDependencies
external.add(specifier.slice(1));
}
else if (sass &&
[...potentialSassImports(specifier, relativeBase, !fromUse)].every((v) => !tree.exists(v)) &&
[...potentialSassImports(specifier, '/', !fromUse)].some((v) => tree.exists(v))) {
needWorkspaceIncludePath = true;
}
}
if (updater) {
tree.commitUpdate(updater);
}
}
if (needWorkspaceIncludePath) {
buildTarget.options ??= {};
buildTarget.options['stylePreprocessorOptions'] ??= {};
(buildTarget.options['stylePreprocessorOptions']['includePaths'] ??= []).push('.');
}
if (external.size > 0) {
buildTarget.options ??= {};
(buildTarget.options['externalDependencies'] ??= []).push(...external);
}
}
function deleteFile(path) {
return (tree) => {
tree.delete(path);
};
}
function updateJsonFile(path, updater) {
return (tree, ctx) => {
if (tree.exists(path)) {
updater(new json_file_1.JSONFile(tree, path));
}
else {
ctx.logger.info(`Skipping updating '${path}' as it does not exist.`);
}
};
}
/**
* Migration main entrypoint
*/
function default_1() {
return (0, schematics_1.chain)([
updateProjects,
// Delete package.json helper scripts
updateJsonFile('package.json', (pkgJson) => ['build:ssr', 'dev:ssr', 'serve:ssr', 'prerender'].forEach((s) => pkgJson.remove(['scripts', s]))),
// Update main tsconfig
updateJsonFile('tsconfig.json', (rootJson) => {
rootJson.modify(['compilerOptions', 'esModuleInterop'], true);
rootJson.modify(['compilerOptions', 'downlevelIteration'], undefined);
rootJson.modify(['compilerOptions', 'allowSyntheticDefaultImports'], undefined);
}),
]);
}