diff --git a/adev/angular.json b/adev/angular.json index 2995538736b..7047b7996a1 100644 --- a/adev/angular.json +++ b/adev/angular.json @@ -33,7 +33,13 @@ "polyfills": [], "tsConfig": "tsconfig.app.json", "inlineStyleLanguage": "scss", - "assets": ["src/favicon.ico", "src/robots.txt", "src/assets", "src/llms.txt"], + "assets": [ + "src/favicon.ico", + "src/robots.txt", + "src/assets", + "src/llms.txt", + "src/llms-full.txt" + ], "styles": ["@angular/docs/styles/global-styles.scss", "./src/local-styles.scss"], "scripts": [], "webWorkerTsConfig": "tsconfig.worker.json", diff --git a/adev/scripts/shared/llms-list.md b/adev/scripts/shared/llms-list.md new file mode 100644 index 00000000000..e574b7bb657 --- /dev/null +++ b/adev/scripts/shared/llms-list.md @@ -0,0 +1,107 @@ + +## Table of contents + +adev/src/content/introduction/what-is-angular.md +adev/src/content/introduction/installation.md +adev/src/content/best-practices/style-guide.md + +## Components + +adev/src/content/introduction/essentials/components.md +adev/src/content/guide/components/selectors.md +adev/src/content/guide/components/styling.md +adev/src/content/guide/components/inputs.md +adev/src/content/guide/components/outputs.md +adev/src/content/guide/components/content-projection.md +adev/src/content/guide/components/lifecycle.md + +## Template guides + +adev/src/content/introduction/essentials/templates.md +adev/src/content/guide/templates/event-listeners.md +adev/src/content/guide/templates/binding.md +adev/src/content/guide/templates/control-flow.md +adev/src/content/guide/templates/variables.md +adev/src/content/guide/templates/defer.md +adev/src/content/guide/templates/expression-syntax.md + +## Directives + +adev/src/content/guide/directives/attribute-directives.md +adev/src/content/guide/directives/structural-directives.md +adev/src/content/guide/directives/directive-composition-api.md +adev/src/content/guide/image-optimization.md + +## Signals + +adev/src/content/introduction/essentials/signals.md +adev/src/content/guide/signals/linked-signal.md +adev/src/content/guide/signals/resource.md + +## Dependency injection + +adev/src/content/guide/di/dependency-injection.md +adev/src/content/guide/di/creating-injectable-service.md +adev/src/content/guide/di/dependency-injection-providers.md +adev/src/content/guide/di/dependency-injection-context.md +adev/src/content/guide/di/hierarchical-dependency-injection.md +adev/src/content/guide/di/lightweight-injection-tokens.md + +## Rxjs + +adev/src/content/ecosystem/rxjs-interop/signals-interop.md +adev/src/content/ecosystem/rxjs-interop/output-interop.md + +## Http + +adev/src/content/guide/http/setup.md +adev/src/content/guide/http/making-requests.md +adev/src/content/guide/http/interceptors.md +adev/src/content/guide/http/testing.md + +## Forms + +adev/src/content/guide/forms/reactive-forms.md +adev/src/content/guide/forms/typed-forms.md +adev/src/content/guide/forms/template-driven-forms.md +adev/src/content/guide/forms/form-validation.md +adev/src/content/guide/forms/dynamic-forms.md + +## Routing + +adev/src/content/guide/routing/common-router-tasks.md +adev/src/content/guide/routing/router-tutorial.md +adev/src/content/guide/routing/routing-with-urlmatcher.md + +## SSR + +adev/src/content/guide/ssr.md +adev/src/content/guide/hydration.md +adev/src/content/guide/incremental-hydration.md + +## Testing + +adev/src/content/guide/testing/overview.md +adev/src/content/guide/testing/code-coverage.md +adev/src/content/guide/testing/services.md +adev/src/content/guide/testing/components-basics.md +adev/src/content/guide/testing/components-scenarios.md +adev/src/content/guide/testing/debugging.md +adev/src/content/guide/testing/utility-apis.md +adev/src/content/guide/testing/component-harnesses-overview.md +adev/src/content/guide/testing/using-component-harnesses.md +adev/src/content/guide/testing/creating-component-harnesses.md + +## Animations + +adev/src/content/guide/animations/css.md +adev/src/content/guide/animations/route-animations.md +adev/src/content/guide/animations/migration.md + +## Others + +adev/src/content/guide/zoneless.md +adev/src/content/reference/roadmap.md +adev/src/content/best-practices/update.md +adev/src/content/guide/http/security.md +adev/src/content/guide/i18n/overview.md \ No newline at end of file diff --git a/adev/scripts/shared/llms.mjs b/adev/scripts/shared/llms.mjs new file mode 100644 index 00000000000..13bf058ee2c --- /dev/null +++ b/adev/scripts/shared/llms.mjs @@ -0,0 +1,140 @@ +/** + * @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 + */ + +// The purpose of this script is to generate a llms-full.txt +// Run with `node adev/scripts/shared/llms.mjs` to generate llms-full.txt from the list in llms-list.md + +//tslint:disable:no-console +import fs from 'fs/promises'; +import path from 'path'; + +const INPUT_MD_FILENAME = 'adev/scripts/shared/llms-list.md'; +const OUTPUT_FILENAME = 'adev/src/llms-full.txt'; + +function postProcessOutputContent(content) { + // Helper to map custom languages to standard Markdown languages + const mapLanguage = (lang) => { + if (!lang) return ''; // For code blocks without a specified language + const lowerLang = lang.trim().toLowerCase(); + if (lowerLang === 'angular-ts') return 'typescript'; + if (lowerLang === 'angular-html') return 'html'; + return lowerLang; // Use as is for other languages like shell, etc. + }; + + // Process docs-code-multifile and their inner docs-code elements + content = content.replace( + /([\s\S]*?)<\/docs-code-multifile>/gs, + (match, innerHTML) => { + let multifileResult = ''; + // Regex for within , expecting 'header' and optional 'language' + const codeRegex = + /]*>([\s\S]*?)<\/docs-code>/gs; + let codeMatch; + while ((codeMatch = codeRegex.exec(innerHTML)) !== null) { + const header = codeMatch[1].trim(); + const langAttr = codeMatch[2]; // Language attribute might be undefined + const language = mapLanguage(langAttr); + let code = codeMatch[3].trim(); + // Note: If code content includes HTML entities like <, they would need unescaping here. + // e.g., code = code.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&'); + multifileResult += `\`\`\`${language}\n// ${header}\n${code}\n\`\`\`\n`; + } + return multifileResult; + }, + ); + + // Process standalone docs-code elements + content = content.replace( + /]*>([\s\S]*?)<\/docs-code>/gs, + (match, langAttr, codeContent) => { + const language = mapLanguage(langAttr); + let code = codeContent.trim(); + // Note: HTML entity unescaping might be needed here as well. + return `\`\`\`${language}\n${code}\n\`\`\`\n`; + }, + ); + + // Process code block languages + content = content.replace(/```([\w-]+)\s*/gs, (match, lang, code) => { + const mappedLang = mapLanguage(lang); // lang can be undefined if no language was specified + return `\`\`\`${mappedLang}\n`; + }); + + // Remove docs-decorative-header elements + content = content.replace( + /]*>[\s\S]*?<\/docs-decorative-header>/gs, + '', + ); + + // Remove docs-card elements + content = content.replace(/]*>[\s\S]*?<\/docs-card>/gi, ''); + + // remove docs-pill-row elements + content = content.replace(/]*>[\s\S]*?<\/docs-pill-row>/gi, ''); + + // Remove docs-callout tags, keeping the content within them + content = content.replace(/]*>([\s\S]*?)<\/docs-callout>/gis, '$1'); + + // Remove docs-card-container tags, keeping the content within them + content = content.replace(//g, ''); + content = content.replace(/<\/docs-card-container>/g, ''); + + return content; +} + +async function main() { + const inputFilePath = path.resolve(process.cwd(), INPUT_MD_FILENAME); + const baseDirForIncludes = path.dirname(inputFilePath); + + console.log(`Starting processing of: ${inputFilePath}`); + + let mainFileContent; + try { + mainFileContent = await fs.readFile(inputFilePath, 'utf-8'); + } catch (error) { + console.error(`Error: Failed to read input file "${inputFilePath}".`); + console.error(error.message); + process.exit(1); // Exit with error code + } + + let processedContent = mainFileContent; + const matches = [...mainFileContent.matchAll(/(.*\.md)/g)]; + + console.log(`Found ${matches.length} files`); + + let resultString = ''; + + for (const match of matches) { + const filePath = match[0]; + const absolutePathToIncludeFile = path.resolve(filePath); + + try { + console.log(` Including content from: ${absolutePathToIncludeFile}`); + const includedFileContent = await fs.readFile(absolutePathToIncludeFile, 'utf-8'); + const processedFile = postProcessOutputContent(includedFileContent); + resultString += processedFile; // Append the content of the included file + } catch (fileReadError) { + console.warn(` Warning: Could not read file "${absolutePathToIncludeFile}"`); + } + } + + // Basic cleanup of blank lines + processedContent = resultString.replace(/(?:\s*\n){3,}/g, '\n'); + + const outputFilePath = path.resolve(process.cwd(), OUTPUT_FILENAME); + try { + await fs.writeFile(outputFilePath, processedContent, 'utf-8'); + console.log(`Successfully generated combined file: ${outputFilePath}`); + } catch (error) { + console.error(`Error: Failed to write output file "${outputFilePath}".`); + console.error(error.message); + process.exit(1); // Exit with error code + } +} + +main(); diff --git a/adev/src/llms-full.txt b/adev/src/llms-full.txt new file mode 100644 index 00000000000..96db9c13c0d --- /dev/null +++ b/adev/src/llms-full.txt @@ -0,0 +1,12982 @@ + + + +Angular is a web framework that empowers developers to build fast, reliable applications. + + +Maintained by a dedicated team at Google, Angular provides a broad suite of tools, APIs, and +libraries to simplify and streamline your development workflow. Angular gives you +a solid platform on which to build fast, reliable applications that scale with both the size of +your team and the size of your codebase. + +**Want to see some code?** Jump over to our [Essentials](essentials) for a quick overview of +what it's like to use Angular, or get started in the [Tutorial](tutorials/learn-angular) if you +prefer following step-by-step instructions. + +## Features that power your development +## Develop applications faster than ever +## Ship with confidence +## Works at any scale +## Open-source first +## A thriving community +Get started with Angular quickly with online starters or locally with your terminal. + +## Play Online + +If you just want to play around with Angular in your browser without setting up a project, you can use our online sandbox: +## Set up a new project locally + +If you're starting a new project, you'll most likely want to create a local project so that you can use tooling such as Git. + +### Prerequisites + +- **Node.js** - [v20.11.1 or newer](/reference/versions) +- **Text editor** - We recommend [Visual Studio Code](https://code.visualstudio.com/) +- **Terminal** - Required for running Angular CLI commands +- **Development Tool** - To improve your development workflow, we recommend the [Angular Language Service](/tools/language-service) + +### Instructions + +The following guide will walk you through setting up a local Angular project. + +#### Install Angular CLI + +Open a terminal (if you're using [Visual Studio Code](https://code.visualstudio.com/), you can open an [integrated terminal](https://code.visualstudio.com/docs/editor/integrated-terminal)) and run the following command: + +``` +// npm +npm install -g @angular/cli +``` +``` +// pnpm +pnpm install -g @angular/cli +``` +``` +// yarn +yarn global add @angular/cli +``` +``` +// bun +bun install -g @angular/cli +``` +If you are having issues running this command in Windows or Unix, check out the [CLI docs](/tools/cli/setup-local#install-the-angular-cli) for more info. + +#### Create a new project + +In your terminal, run the CLI command `ng new` with the desired project name. In the following examples, we'll be using the example project name of `my-first-angular-app`. + +```shell +ng new +``` +You will be presented with some configuration options for your project. Use the arrow and enter keys to navigate and select which options you desire. + +If you don't have any preferences, just hit the enter key to take the default options and continue with the setup. + +After you select the configuration options and the CLI runs through the setup, you should see the following message: + +```shell +✔ Packages installed successfully. + Successfully initialized git. +``` + +At this point, you're now ready to run your project locally! + +#### Running your new project locally + +In your terminal, switch to your new Angular project. + +```shell +cd my-first-angular-app +``` +All of your dependencies should be installed at this point (which you can verify by checking for the existent for a `node_modules` folder in your project), so you can start your project by running the command: + +```shell +npm start +``` +If everything is successful, you should see a similar confirmation message in your terminal: + +```shell +Watch mode enabled. Watching for file changes... +NOTE: Raw file sizes do not reflect development server per-request transformations. + ➜ Local: http://localhost:4200/ + ➜ press h + enter to show help +``` + +And now you can visit the path in `Local` (e.g., `http://localhost:4200`) to see your application. Happy coding! 🎉 + +## Next steps + +Now that you've created your Angular project, you can learn more about Angular in our [Essentials guide](/essentials) or choose a topic in our in-depth guides! +# Angular coding style guide + +## Introduction + +This guide covers a range of style conventions for Angular application code. These recommendations +are not required for Angular to work, but instead establish a set of coding practices that promote +consistency across the Angular ecosystem. A consistent set of practices makes it easier to share +code and move between projects. + +This guide does _not_ cover TypeScript or general coding practices unrelated to Angular. For +TypeScript, check +out [Google's TypeScript style guide](https://google.github.io/styleguide/tsguide.html). + +### When in doubt, prefer consistency + +Whenever you encounter a situation in which these rules contradict the style of a particular file, +prioritize maintaining consistency within a file. Mixing different style conventions in a single +file creates more confusion than diverging from the recommendations in this guide. + +## Naming + +### Separate words in file names with hyphens + +Separate words within a file name with hyphens (`-`). For example, a component named `UserProfile` +has a file name `user-profile.ts`. + +### Use the same name for a file's tests with `.spec` at the end + +For unit tests, end file names with `.spec.ts`. For example, the unit test file for +the `UserProfile` component has the file name `user-profile.spec.ts`. + +### Match file names to the TypeScript identifier within + +File names should generally describe the contents of the code in the file. When the file contains a +TypeScript class, the file name should reflect that class name. For example, a file containing a +component named `UserProfile` has the name `user-profile.ts`. + +If the file contains more than one primary namable identifier, choose a name that describes the +common theme to the code within. If the code in a file does not fit within a common theme or feature +area, consider breaking the code up into different files. Avoid overly generic file names +like `helpers.ts`, `utils.ts`, or `common.ts`. + +### Use the same file name for a component's TypeScript, template, and styles + +Components typically consist of one TypeScript file, one template file, and one style file. These +files should share the same name with different file extensions. For example, a `UserProfile` +component can have the files `user-profile.ts`, `user-profile.html`, and `user-profile.css`. + +If a component has more than one style file, append the name with additional words that describe the +styles specific to that file. For example, `UserProfile` might have style +files `user-profile-settings.css` and `user-profile-subscription.css`. + +## Project structure + +### All the application's code goes in a directory named `src` + +All of your Angular UI code (TypeScript, HTML, and styles) should live inside a directory +named `src`. Code that's not related to UI, such as configuration files or scripts, should live +outside the `src` directory. + +This keeps the root application directory consistent between different Angular projects and creates +a clear separation between UI code and other code in your project. + +### Bootstrap your application in a file named `main.ts` directly inside `src` + +The code to start up, or **bootstrap**, an Angular application should always live in a file +named `main.ts`. This represents the primary entry point to the application. + +### Group closely related files together in the same directory + +Angular components consist of a TypeScript file and, optionally, a template and one or more style +files. You should group these together in the same directory. + +Unit tests should live in the same directory as the code-under-test. Avoid collecting unrelated +tests into a single `tests` directory. + +### Organize your project by feature areas + +Organize your project into subdirectories based on the features or your application or common themes +to the code in those directories. For example, the project structure for a movie theater site, +MovieReel, might look like this: + +``` +src/ +├─ movie-reel/ +│ ├─ show-times/ +│ │ ├─ film-calendar/ +│ │ ├─ film-details/ +│ ├─ reserve-tickets/ +│ │ ├─ payment-info/ +│ │ ├─ purchase-confirmation/ +``` + +Avoid creating subdirectories based on the type of code that lives in those directories. For +example, avoid creating directories like `components`, `directives`, and `services`. + +Avoid putting so many files into one directory that it becomes hard to read or navigate. As the +number files in a directory grows, consider splitting further into additional sub-directories. + +### One concept per file + +Prefer focusing source files on a single _concept_. For Angular classes specifically, this usually +means one component, directive, or service per file. However, it's okay if a file contains more than +one component or directive if your classes are relatively small and they tie together as part of a +single concept. + +When in doubt, go with the approach that leads to smaller files. + +## Dependency injection + +### Prefer the `inject` function over constructor parameter injection + +Prefer using the `inject` function over injecting constructor parameters. The `inject` function works the same way as constructor parameter injection, but offers several style advantages: + +* `inject` is generally more readable, especially when a class injects many dependencies. +* It's more syntactically straightforward to add comments to injected dependencies +* `inject` offers better type inference. +* When targeting ES2022+ with [`useDefineForClassFields`](https://www.typescriptlang.org/tsconfig/#useDefineForClassFields), you can avoid separating field declaration and initialization when fields read on injected dependencies. + +[You can refactor existing code to `inject` with an automatic tool](reference/migrations/inject-function). + +## Components and directives + +### Choosing component selectors + +See +the [Components guide for details on choosing component selectors](guide/components/selectors#choosing-a-selector). + +### Naming component and directive members + +See the Components guide for details +on [naming input properties](guide/components/inputs#choosing-input-names) +and [naming output properties](guide/components/outputs#choosing-event-names). + +### Choosing directive selectors + +Directives should use the +same [application-specific prefix](guide/components/selectors#selector-prefixes) +as your components. + +When using an attribute selector for a directive, use a camelCase attribute name. For example, if +your application is named "MovieReel" and you build a directive that adds a tooltip to an element, +you might use the selector `[mrTooltip]`. + +### Group Angular-specific properties before methods + +Components and directives should group Angular-specific properties together, typically near the top +of the class declaration. This includes injected dependencies, inputs, outputs, and queries. Define +these and other properties before the class's methods. + +This practice makes it easier to find the class's template APIs and dependencies. + +### Keep components and directives focused on presentation + +Code inside your components and directives should generally relate to the UI shown on the page. For +code that makes sense on its own, decoupled from the UI, prefer refactoring to other files. For +example, you can factor form validation rules or data transformations into separate functions or +classes. + +### Avoid overly complex logic in templates + +Angular templates are designed to +accommodate [JavaScript-like expressions](guide/templates/expression-syntax). +You should take advantage of these expressions to capture relatively straightforward logic directly +in template expressions. + +When the code in a template gets too complex, though, refactor logic into the TypeScript code ( +typically with a [computed](guide/signals#computed-signals)). + +There's no one hard-and-fast rule that determines what constitutes "complex". Use your best +judgement. + +### Use `protected` on class members that are only used by a component's template + +A component class's public members intrinsically define a public API that's accessible via +dependency injection and [queries](guide/components/queries). Prefer `protected` +access for any members that are meant to be read from the component's template. + +```ts +@Component({ + ..., + template: `

{{ fullName() }}

`, +}) +export class UserProfile { + firstName = input(); + lastName = input(); + +// `fullName` is not part of the component's public API, but is used in the template. + protected fullName = computed(() => `${this.firstName()} ${this.lastName()}`); +} +``` + +### Use `readonly` on properties that are initialized by Angular + +Mark component and directive properties initialized by Angular as `readonly`. This includes +properties initialized by `input`, `model`, `output`, and queries. The readonly access modifier +ensures that the value set by Angular is not overwritten. + +```ts +@Component({/* ... */}) +export class UserProfile { + readonly userId = input(); + readonly userSaved = output(); +} +``` + +For components and directives that use the decorator-based `@Input`, `@Output`, and query APIs, this +advice applies to output properties and queries, but not input properties. + +```ts +@Component({/* ... */}) +export class UserProfile { + @Output() readonly userSaved = new EventEmitter(); + @ViewChildren(PaymentMethod) readonly paymentMethods?: QueryList; +} +``` + +### Prefer `class` and `style` over `ngClass` and `ngStyle` + +Prefer `class` and `style` bindings over using the `NgClass` and `NgStyle` directives. + +```html + +
+ + +
+``` + +Both `class` and `style` bindings use a more straightforward syntax that aligns closely with +standard HTML attributes. This makes your templates easier to read and understand, especially for +developers familiar with basic HTML. + +Additionally, the `NgClass` and `NgStyle` directives incur an additional performance cost compared +to the built-in `class` and `style` binding syntax. + +### Name event handlers for what they _do_, not for the triggering event + +Prefer naming event handlers for the action they perform rather than for the triggering event: + +```html + + + + + +``` + +Using meaningful names like this makes it easier to tell what an event does from reading the +template. + +For keyboard events, you can use Angular's key event modifiers with specific handler names: + +```html +