create-analog 1.8.2 → 1.9.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/files/analog-env.d.ts +13 -0
  2. package/files/styles.css +5 -0
  3. package/files/tailwind.config.ts +9 -0
  4. package/index.js +116 -26
  5. package/package.json +1 -1
  6. package/template-angular-v16/package.json +5 -5
  7. package/template-angular-v17/package.json +5 -5
  8. package/template-blog/README.md +1 -1
  9. package/template-blog/index.html +1 -1
  10. package/template-blog/package.json +5 -5
  11. package/template-blog/src/app/app-root.ag +25 -0
  12. package/template-blog/src/app/app-root.spec.ts +20 -0
  13. package/template-blog/src/app/app.component.spec.ts +5 -2
  14. package/template-blog/src/app/app.component.ts +17 -18
  15. package/template-blog/src/app/pages/blog/[slug].page.ag +24 -0
  16. package/template-blog/src/app/pages/blog/[slug].page.ts +6 -8
  17. package/template-blog/src/app/pages/blog/index.page.ag +32 -0
  18. package/template-blog/src/app/pages/blog/index.page.ts +15 -15
  19. package/template-blog/src/main.server.ts +2 -2
  20. package/template-blog/src/main.ts +2 -2
  21. package/template-blog/vite.config.ts +1 -1
  22. package/template-latest/README.md +1 -1
  23. package/template-latest/index.html +1 -1
  24. package/template-latest/package.json +5 -5
  25. package/template-latest/src/app/app-root.ag +16 -0
  26. package/template-latest/src/app/app-root.spec.ts +20 -0
  27. package/template-latest/src/app/app.component.ts +9 -11
  28. package/template-latest/src/app/pages/index.page.ag +53 -0
  29. package/template-latest/src/app/pages/index.page.ts +20 -20
  30. package/template-latest/src/main.server.ts +2 -2
  31. package/template-latest/src/main.ts +2 -2
  32. package/template-latest/src/styles.css +5 -0
  33. package/template-latest/vite.config.ts +1 -1
  34. package/template-minimal/README.md +1 -1
  35. package/template-minimal/index.html +1 -1
  36. package/template-minimal/package.json +5 -5
  37. package/template-minimal/src/app/app-root.ag +7 -0
  38. package/template-minimal/src/app/app.component.ts +1 -1
  39. package/template-minimal/src/app/pages/index.page.ag +32 -0
  40. package/template-minimal/src/app/pages/index.page.ts +4 -3
  41. package/template-minimal/src/main.server.ts +2 -2
  42. package/template-minimal/src/main.ts +2 -2
  43. package/template-minimal/vite.config.ts +1 -1
  44. package/files/tailwind.config.cjs +0 -8
@@ -0,0 +1,13 @@
1
+ declare module '*.analog' {
2
+ import { Type } from '@angular/core';
3
+
4
+ const cmp: Type<unknown>;
5
+ export default cmp;
6
+ }
7
+
8
+ declare module '*.ag' {
9
+ import { Type } from '@angular/core';
10
+
11
+ const cmp: Type<unknown>;
12
+ export default cmp;
13
+ }
package/files/styles.css CHANGED
@@ -26,6 +26,7 @@ a {
26
26
  color: #646cff;
27
27
  text-decoration: inherit;
28
28
  }
29
+
29
30
  a:hover {
30
31
  color: #535bf2;
31
32
  }
@@ -54,9 +55,11 @@ button {
54
55
  cursor: pointer;
55
56
  transition: border-color 0.25s;
56
57
  }
58
+
57
59
  button:hover {
58
60
  border-color: #646cff;
59
61
  }
62
+
60
63
  button:focus,
61
64
  button:focus-visible {
62
65
  outline: 4px auto -webkit-focus-ring-color;
@@ -75,9 +78,11 @@ button:focus-visible {
75
78
  color: #213547;
76
79
  background-color: #ffffff;
77
80
  }
81
+
78
82
  a:hover {
79
83
  color: #747bff;
80
84
  }
85
+
81
86
  button {
82
87
  background-color: #f9f9f9;
83
88
  }
@@ -0,0 +1,9 @@
1
+ import type { Config } from 'tailwindcss';
2
+
3
+ export default {
4
+ content: ['./index.html', './src/**/*.{html,ts,md,analog,ag}'],
5
+ theme: {
6
+ extend: {},
7
+ },
8
+ plugins: [],
9
+ } satisfies Config;
package/index.js CHANGED
@@ -4,8 +4,8 @@
4
4
  import { blue, green, red, reset, yellow } from 'kolorist';
5
5
  import minimist from 'minimist';
6
6
  import { execSync } from 'node:child_process';
7
- import fs, { readdirSync } from 'node:fs';
8
- import path, { join } from 'node:path';
7
+ import fs from 'node:fs';
8
+ import path from 'node:path';
9
9
  import { fileURLToPath } from 'node:url';
10
10
  import prompts from 'prompts';
11
11
 
@@ -64,7 +64,8 @@ const renameFiles = {
64
64
  async function init() {
65
65
  let targetDir = formatTargetDir(argv._[0]);
66
66
  let template = argv.template || argv.t;
67
- let skipTailwind = argv.skipTailwind || false;
67
+ let skipTailwind = fromBoolArg(argv.skipTailwind);
68
+ let useAnalogSFC = fromBoolArg(argv.analogSFC);
68
69
 
69
70
  const defaultTargetDir = 'analog-project';
70
71
  const getProjectName = () =>
@@ -135,7 +136,12 @@ async function init() {
135
136
  initial: 1,
136
137
  },
137
138
  {
138
- type: skipTailwind ? null : 'confirm',
139
+ type: useAnalogSFC === undefined ? 'confirm' : null,
140
+ name: 'analogSFC',
141
+ message: 'Would you like to use Analog SFCs?',
142
+ },
143
+ {
144
+ type: skipTailwind === undefined ? 'confirm' : null,
139
145
  name: 'tailwind',
140
146
  message: 'Would you like to add Tailwind to your project?',
141
147
  },
@@ -157,6 +163,7 @@ async function init() {
157
163
  overwrite,
158
164
  packageName,
159
165
  variant,
166
+ analogSFC,
160
167
  tailwind,
161
168
  syntaxHighlighter,
162
169
  } = result;
@@ -173,7 +180,8 @@ async function init() {
173
180
  template = variant || framework || template;
174
181
  // determine syntax highlighter
175
182
  let highlighter = syntaxHighlighter ?? (template === 'blog' ? 'prism' : null);
176
- skipTailwind = !tailwind || skipTailwind;
183
+ skipTailwind = skipTailwind ?? !tailwind;
184
+ useAnalogSFC = useAnalogSFC ?? analogSFC;
177
185
 
178
186
  console.log(`\nScaffolding project in ${root}...`);
179
187
 
@@ -221,13 +229,22 @@ async function init() {
221
229
  ensureSyntaxHighlighter(root, pkg, highlighter);
222
230
  }
223
231
 
224
- if (!skipTailwind) addTailwindDevDependencies(pkg);
232
+ if (!skipTailwind) {
233
+ addTailwindDevDependencies(pkg);
234
+ }
235
+
225
236
  if (pkgManager === 'yarn') {
226
237
  addYarnDevDependencies(pkg, template);
227
238
  }
228
239
 
240
+ pkg.dependencies = sortObjectKeys(pkg.dependencies);
241
+ pkg.devDependencies = sortObjectKeys(pkg.devDependencies);
242
+
229
243
  write('package.json', JSON.stringify(pkg, null, 2));
230
244
 
245
+ setProjectTitle(root, getProjectName());
246
+ setComponentFormat(root, filesDir, write, template, useAnalogSFC);
247
+
231
248
  console.log(`\nInitializing git repository:`);
232
249
  execSync(`git init ${targetDir} && cd ${targetDir} && git add .`);
233
250
 
@@ -362,8 +379,8 @@ function addPostCssConfig(write, filesDir) {
362
379
 
363
380
  function addTailwindConfig(write, filesDir) {
364
381
  write(
365
- 'tailwind.config.cjs',
366
- fs.readFileSync(path.join(filesDir, `tailwind.config.cjs`), 'utf-8')
382
+ 'tailwind.config.ts',
383
+ fs.readFileSync(path.join(filesDir, `tailwind.config.ts`), 'utf-8')
367
384
  );
368
385
  }
369
386
 
@@ -389,31 +406,104 @@ function addYarnDevDependencies(pkg, template) {
389
406
  }
390
407
 
391
408
  function ensureSyntaxHighlighter(root, pkg, highlighter) {
392
- const appConfigPath = path.join(root, 'src/app/app.config.ts');
393
- const appConfigContent = fs.readFileSync(appConfigPath, 'utf-8');
394
-
395
- fs.writeFileSync(
396
- appConfigPath,
397
- appConfigContent
398
- .replace(/__HIGHLIGHTER__/g, HIGHLIGHTERS[highlighter].highlighter)
399
- .replace(
400
- /__HIGHLIGHTER_ENTRY_POINT__/g,
401
- HIGHLIGHTERS[highlighter].entryPoint
402
- )
403
- );
409
+ replacePlaceholders(root, 'src/app/app.config.ts', {
410
+ __HIGHLIGHTER__: HIGHLIGHTERS[highlighter].highlighter,
411
+ __HIGHLIGHTER_ENTRY_POINT__: HIGHLIGHTERS[highlighter].entryPoint,
412
+ });
404
413
 
405
414
  const dependencies = HIGHLIGHTERS[highlighter].dependencies;
406
415
  for (const [name, version] of Object.entries(dependencies)) {
407
416
  pkg.dependencies[name] = version;
408
417
  }
409
418
 
410
- const viteConfigPath = path.join(root, 'vite.config.ts');
411
- const viteConfigContent = fs.readFileSync(viteConfigPath, 'utf-8');
419
+ replacePlaceholders(root, 'vite.config.ts', {
420
+ __CONTENT_HIGHLIGHTER__: highlighter,
421
+ });
422
+ }
412
423
 
413
- fs.writeFileSync(
414
- viteConfigPath,
415
- viteConfigContent.replace(/__CONTENT_HIGHLIGHTER__/g, highlighter)
416
- );
424
+ function sortObjectKeys(obj) {
425
+ return Object.keys(obj)
426
+ .sort()
427
+ .reduce((result, key) => {
428
+ result[key] = obj[key];
429
+ return result;
430
+ }, {});
431
+ }
432
+
433
+ function setProjectTitle(root, title) {
434
+ replacePlaceholders(root, ['index.html', 'README.md'], {
435
+ __PROJECT_TITLE__: title,
436
+ });
437
+ }
438
+
439
+ function setComponentFormat(root, filesDir, write, template, useAnalogSFC) {
440
+ const getSFCConfig = () => {
441
+ const sfcConfigOption =
442
+ 'vite: { experimental: { supportAnalogFormat: true } }';
443
+
444
+ return template === 'latest'
445
+ ? `{ ${sfcConfigOption} }`
446
+ : `\n ${sfcConfigOption},`;
447
+ };
448
+
449
+ replacePlaceholders(root, 'vite.config.ts', {
450
+ __ANALOG_SFC_CONFIG__: useAnalogSFC ? getSFCConfig() : '',
451
+ });
452
+ replacePlaceholders(root, ['src/main.ts', 'src/main.server.ts'], {
453
+ __APP_COMPONENT__: useAnalogSFC ? 'App' : 'AppComponent',
454
+ __APP_COMPONENT_IMPORT__: useAnalogSFC
455
+ ? "import App from './app/app-root.ag';"
456
+ : "import { AppComponent } from './app/app.component';",
457
+ });
458
+
459
+ const cmpForDelete = useAnalogSFC ? 'app.component' : 'app-root';
460
+ const deleteExt = useAnalogSFC ? 'ts' : 'ag';
461
+ deleteFiles(root, [
462
+ useAnalogSFC ? `src/app/${cmpForDelete}.ts` : `src/app/${cmpForDelete}.ag`,
463
+ template === 'blog'
464
+ ? [
465
+ `src/app/pages/blog/index.page.${deleteExt}`,
466
+ `src/app/pages/blog/[slug].page.${deleteExt}`,
467
+ ]
468
+ : `src/app/pages/index.page.${deleteExt}`,
469
+ template !== 'minimal' && `src/app/${cmpForDelete}.spec.ts`,
470
+ ]);
471
+
472
+ if (useAnalogSFC) {
473
+ write(
474
+ 'src/analog-env.d.ts',
475
+ fs.readFileSync(path.join(filesDir, 'analog-env.d.ts'), 'utf-8')
476
+ );
477
+ }
478
+ }
479
+
480
+ function replacePlaceholders(root, files, config) {
481
+ for (const file of toFlatArray(files)) {
482
+ const filePath = path.join(root, file);
483
+ const fileContent = fs.readFileSync(filePath, 'utf-8');
484
+ const newFileContent = Object.keys(config).reduce(
485
+ (content, placeholder) =>
486
+ content.replace(RegExp(placeholder, 'g'), config[placeholder]),
487
+ fileContent
488
+ );
489
+ fs.writeFileSync(filePath, newFileContent);
490
+ }
491
+ }
492
+
493
+ function deleteFiles(root, files) {
494
+ for (const file of toFlatArray(files)) {
495
+ fs.unlinkSync(path.join(root, file));
496
+ }
497
+ }
498
+
499
+ function toFlatArray(value) {
500
+ return (Array.isArray(value) ? value : [value]).filter(Boolean).flat();
501
+ }
502
+
503
+ function fromBoolArg(arg) {
504
+ return ['boolean', 'undefined'].includes(typeof arg)
505
+ ? arg
506
+ : ['', 'true'].includes(arg);
417
507
  }
418
508
 
419
509
  init().catch((e) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-analog",
3
- "version": "1.8.2",
3
+ "version": "1.9.0-beta.10",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Brandon Roberts",
@@ -15,8 +15,8 @@
15
15
  "test": "ng test"
16
16
  },
17
17
  "dependencies": {
18
- "@analogjs/content": "^1.8.2",
19
- "@analogjs/router": "^1.8.2",
18
+ "@analogjs/content": "^1.9.0-beta.10",
19
+ "@analogjs/router": "^1.9.0-beta.10",
20
20
  "@angular/animations": "^16.2.0",
21
21
  "@angular/common": "^16.2.0",
22
22
  "@angular/compiler": "^16.2.0",
@@ -38,9 +38,9 @@
38
38
  "zone.js": "~0.13.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@analogjs/platform": "^1.8.2",
42
- "@analogjs/vite-plugin-angular": "^1.8.2",
43
- "@analogjs/vitest-angular": "^1.8.2",
41
+ "@analogjs/platform": "^1.9.0-beta.10",
42
+ "@analogjs/vite-plugin-angular": "^1.9.0-beta.10",
43
+ "@analogjs/vitest-angular": "^1.9.0-beta.10",
44
44
  "@angular-devkit/build-angular": "^16.2.0",
45
45
  "@angular/cli": "^16.2.0",
46
46
  "@angular/compiler-cli": "^16.2.0",
@@ -15,8 +15,8 @@
15
15
  "test": "ng test"
16
16
  },
17
17
  "dependencies": {
18
- "@analogjs/content": "^1.8.2",
19
- "@analogjs/router": "^1.8.2",
18
+ "@analogjs/content": "^1.9.0-beta.10",
19
+ "@analogjs/router": "^1.9.0-beta.10",
20
20
  "@angular/animations": "^17.2.0",
21
21
  "@angular/common": "^17.2.0",
22
22
  "@angular/compiler": "^17.2.0",
@@ -38,9 +38,9 @@
38
38
  "zone.js": "~0.14.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@analogjs/platform": "^1.8.2",
42
- "@analogjs/vite-plugin-angular": "^1.8.2",
43
- "@analogjs/vitest-angular": "^1.8.2",
41
+ "@analogjs/platform": "^1.9.0-beta.10",
42
+ "@analogjs/vite-plugin-angular": "^1.9.0-beta.10",
43
+ "@analogjs/vitest-angular": "^1.9.0-beta.10",
44
44
  "@angular-devkit/build-angular": "^17.2.0",
45
45
  "@angular/cli": "^17.2.0",
46
46
  "@angular/compiler-cli": "^17.2.0",
@@ -1,4 +1,4 @@
1
- # Analog App
1
+ # __PROJECT_TITLE__
2
2
 
3
3
  This project was generated with [Analog](https://analogjs.org), the fullstack meta-framework for Angular.
4
4
 
@@ -2,7 +2,7 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
- <title>My Blog</title>
5
+ <title>__PROJECT_TITLE__</title>
6
6
  <base href="/" />
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1" />
8
8
  <link rel="icon" type="image/x-icon" href="/favicon.ico" />
@@ -15,8 +15,8 @@
15
15
  "test": "ng test"
16
16
  },
17
17
  "dependencies": {
18
- "@analogjs/content": "^1.8.2",
19
- "@analogjs/router": "^1.8.2",
18
+ "@analogjs/content": "^1.9.0-beta.10",
19
+ "@analogjs/router": "^1.9.0-beta.10",
20
20
  "@angular/animations": "^18.0.0",
21
21
  "@angular/build": "^18.0.0",
22
22
  "@angular/common": "^18.0.0",
@@ -36,9 +36,9 @@
36
36
  "zone.js": "~0.14.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@analogjs/platform": "^1.8.2",
40
- "@analogjs/vite-plugin-angular": "^1.8.2",
41
- "@analogjs/vitest-angular": "^1.8.2",
39
+ "@analogjs/platform": "^1.9.0-beta.10",
40
+ "@analogjs/vite-plugin-angular": "^1.9.0-beta.10",
41
+ "@analogjs/vitest-angular": "^1.9.0-beta.10",
42
42
  "@angular/cli": "^18.0.0",
43
43
  "@angular/compiler-cli": "^18.0.0",
44
44
  "jsdom": "^22.1.0",
@@ -0,0 +1,25 @@
1
+ <script lang="ts">
2
+ import { RouterLink, RouterOutlet } from '@angular/router' with { analog: 'imports' };
3
+ </script>
4
+
5
+ <template>
6
+ <nav>
7
+ <a routerLink="/">Home</a>
8
+ </nav>
9
+
10
+ <router-outlet />
11
+ </template>
12
+
13
+ <style>
14
+ :host {
15
+ max-width: 1280px;
16
+ margin: 0 auto;
17
+ padding: 2rem;
18
+ text-align: center;
19
+ }
20
+
21
+ nav {
22
+ text-align: left;
23
+ padding: 0 0 2rem 0;
24
+ }
25
+ </style>
@@ -0,0 +1,20 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+ import { provideRouter } from '@angular/router';
3
+ import { provideLocationMocks } from '@angular/common/testing';
4
+
5
+ import App from './app-root.ag';
6
+
7
+ describe('App', () => {
8
+ beforeEach(async () => {
9
+ await TestBed.configureTestingModule({
10
+ imports: [App],
11
+ providers: [provideRouter([]), provideLocationMocks()],
12
+ }).compileComponents();
13
+ });
14
+
15
+ it('should create the app', () => {
16
+ const fixture = TestBed.createComponent(App);
17
+ const app = fixture.componentInstance;
18
+ expect(app).toBeTruthy();
19
+ });
20
+ });
@@ -1,11 +1,14 @@
1
1
  import { TestBed } from '@angular/core/testing';
2
- import { RouterTestingModule } from '@angular/router/testing';
2
+ import { provideRouter } from '@angular/router';
3
+ import { provideLocationMocks } from '@angular/common/testing';
4
+
3
5
  import { AppComponent } from './app.component';
4
6
 
5
7
  describe('AppComponent', () => {
6
8
  beforeEach(async () => {
7
9
  await TestBed.configureTestingModule({
8
- imports: [RouterTestingModule, AppComponent],
10
+ imports: [AppComponent],
11
+ providers: [provideRouter([]), provideLocationMocks()],
9
12
  }).compileComponents();
10
13
  });
11
14
 
@@ -1,30 +1,29 @@
1
1
  import { Component } from '@angular/core';
2
- import { RouterOutlet } from '@angular/router';
2
+ import { RouterLink, RouterOutlet } from '@angular/router';
3
3
 
4
4
  @Component({
5
5
  selector: 'app-root',
6
6
  standalone: true,
7
- imports: [RouterOutlet],
7
+ imports: [RouterLink, RouterOutlet],
8
8
  template: `
9
9
  <nav>
10
- <a href="/">Home</a>
10
+ <a routerLink="/">Home</a>
11
11
  </nav>
12
- <router-outlet></router-outlet>
12
+
13
+ <router-outlet />
13
14
  `,
14
- styles: [
15
- `
16
- :host {
17
- max-width: 1280px;
18
- margin: 0 auto;
19
- padding: 2rem;
20
- text-align: center;
21
- }
15
+ styles: `
16
+ :host {
17
+ max-width: 1280px;
18
+ margin: 0 auto;
19
+ padding: 2rem;
20
+ text-align: center;
21
+ }
22
22
 
23
- nav {
24
- text-align: left;
25
- padding: 0 0 2rem 0;
26
- }
27
- `,
28
- ],
23
+ nav {
24
+ text-align: left;
25
+ padding: 0 0 2rem 0;
26
+ }
27
+ `,
29
28
  })
30
29
  export class AppComponent {}
@@ -0,0 +1,24 @@
1
+ <script lang="ts">
2
+ import { AsyncPipe } from '@angular/common' with { analog: 'imports' };
3
+ import { MarkdownComponent } from '@analogjs/content' with { analog: 'imports' };
4
+ import { injectContent } from '@analogjs/content';
5
+
6
+ import PostAttributes from '../../post-attributes';
7
+
8
+ const post$ = injectContent<PostAttributes>('slug');
9
+ </script>
10
+
11
+ <template>
12
+ @if (post$ | async; as post) {
13
+ <article>
14
+ <img class="post__image" [src]="post.attributes.coverImage" />
15
+ <analog-markdown [content]="post.content" />
16
+ </article>
17
+ }
18
+ </template>
19
+
20
+ <style>
21
+ .post__image {
22
+ max-height: 40vh;
23
+ }
24
+ </style>
@@ -1,6 +1,6 @@
1
1
  import { Component } from '@angular/core';
2
- import { injectContent, MarkdownComponent } from '@analogjs/content';
3
2
  import { AsyncPipe } from '@angular/common';
3
+ import { injectContent, MarkdownComponent } from '@analogjs/content';
4
4
 
5
5
  import PostAttributes from '../../post-attributes';
6
6
 
@@ -16,13 +16,11 @@ import PostAttributes from '../../post-attributes';
16
16
  </article>
17
17
  }
18
18
  `,
19
- styles: [
20
- `
21
- .post__image {
22
- max-height: 40vh;
23
- }
24
- `,
25
- ],
19
+ styles: `
20
+ .post__image {
21
+ max-height: 40vh;
22
+ }
23
+ `,
26
24
  })
27
25
  export default class BlogPostComponent {
28
26
  readonly post$ = injectContent<PostAttributes>('slug');
@@ -0,0 +1,32 @@
1
+ <script lang="ts">
2
+ import { RouterLink } from '@angular/router' with { analog: 'imports' };
3
+ import { injectContentFiles } from '@analogjs/content';
4
+
5
+ import PostAttributes from '../../post-attributes';
6
+
7
+ const posts = injectContentFiles<PostAttributes>();
8
+ </script>
9
+
10
+ <template>
11
+ <h1>Blog Archive</h1>
12
+
13
+ @for (post of posts; track post.attributes.slug) {
14
+ <a [routerLink]="['/blog/', post.attributes.slug]">
15
+ <h2 class="post__title">{{ post.attributes.title }}</h2>
16
+ <p class="post__desc">{{ post.attributes.description }}</p>
17
+ </a>
18
+ }
19
+ </template>
20
+
21
+ <style>
22
+ a {
23
+ text-align: left;
24
+ display: block;
25
+ margin-bottom: 2rem;
26
+ }
27
+
28
+ .post__title,
29
+ .post__desc {
30
+ margin: 0;
31
+ }
32
+ </style>
@@ -1,7 +1,8 @@
1
1
  import { Component } from '@angular/core';
2
+ import { RouterLink } from '@angular/router';
2
3
  import { injectContentFiles } from '@analogjs/content';
4
+
3
5
  import PostAttributes from '../../post-attributes';
4
- import { RouterLink } from '@angular/router';
5
6
 
6
7
  @Component({
7
8
  selector: 'app-blog',
@@ -9,27 +10,26 @@ import { RouterLink } from '@angular/router';
9
10
  imports: [RouterLink],
10
11
  template: `
11
12
  <h1>Blog Archive</h1>
12
- @for (post of posts;track post.attributes.slug) {
13
+
14
+ @for (post of posts; track post.attributes.slug) {
13
15
  <a [routerLink]="['/blog/', post.attributes.slug]">
14
16
  <h2 class="post__title">{{ post.attributes.title }}</h2>
15
17
  <p class="post__desc">{{ post.attributes.description }}</p>
16
18
  </a>
17
19
  }
18
20
  `,
19
- styles: [
20
- `
21
- a {
22
- text-align: left;
23
- display: block;
24
- margin-bottom: 2rem;
25
- }
21
+ styles: `
22
+ a {
23
+ text-align: left;
24
+ display: block;
25
+ margin-bottom: 2rem;
26
+ }
26
27
 
27
- .post__title,
28
- .post__desc {
29
- margin: 0;
30
- }
31
- `,
32
- ],
28
+ .post__title,
29
+ .post__desc {
30
+ margin: 0;
31
+ }
32
+ `,
33
33
  })
34
34
  export default class BlogComponent {
35
35
  readonly posts = injectContentFiles<PostAttributes>();
@@ -6,15 +6,15 @@ import { renderApplication } from '@angular/platform-server';
6
6
  import { provideServerContext } from '@analogjs/router/server';
7
7
  import { ServerContext } from '@analogjs/router/tokens';
8
8
 
9
+ __APP_COMPONENT_IMPORT__
9
10
  import { config } from './app/app.config.server';
10
- import { AppComponent } from './app/app.component';
11
11
 
12
12
  if (import.meta.env.PROD) {
13
13
  enableProdMode();
14
14
  }
15
15
 
16
16
  export function bootstrap() {
17
- return bootstrapApplication(AppComponent, config);
17
+ return bootstrapApplication(__APP_COMPONENT__, config);
18
18
  }
19
19
 
20
20
  export default async function render(
@@ -1,7 +1,7 @@
1
1
  import 'zone.js';
2
2
  import { bootstrapApplication } from '@angular/platform-browser';
3
3
 
4
- import { AppComponent } from './app/app.component';
4
+ __APP_COMPONENT_IMPORT__
5
5
  import { appConfig } from './app/app.config';
6
6
 
7
- bootstrapApplication(AppComponent, appConfig);
7
+ bootstrapApplication(__APP_COMPONENT__, appConfig);
@@ -18,7 +18,7 @@ export default defineConfig(({ mode }) => ({
18
18
  },
19
19
  prerender: {
20
20
  routes: ['/blog', '/blog/2022-12-27-my-first-post'],
21
- },
21
+ },__ANALOG_SFC_CONFIG__
22
22
  }),
23
23
  ],
24
24
  test: {
@@ -1,4 +1,4 @@
1
- # Analog App
1
+ # __PROJECT_TITLE__
2
2
 
3
3
  This project was generated with [Analog](https://analogjs.org), the fullstack meta-framework for Angular.
4
4
 
@@ -2,7 +2,7 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
- <title>My App</title>
5
+ <title>__PROJECT_TITLE__</title>
6
6
  <base href="/" />
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1" />
8
8
  <link rel="icon" type="image/x-icon" href="/favicon.ico" />
@@ -15,8 +15,8 @@
15
15
  },
16
16
  "private": true,
17
17
  "dependencies": {
18
- "@analogjs/content": "^1.8.2",
19
- "@analogjs/router": "^1.8.2",
18
+ "@analogjs/content": "^1.9.0-beta.10",
19
+ "@analogjs/router": "^1.9.0-beta.10",
20
20
  "@angular/animations": "^18.0.0",
21
21
  "@angular/build": "^18.0.0",
22
22
  "@angular/common": "^18.0.0",
@@ -38,9 +38,9 @@
38
38
  "zone.js": "~0.14.3"
39
39
  },
40
40
  "devDependencies": {
41
- "@analogjs/platform": "^1.8.2",
42
- "@analogjs/vite-plugin-angular": "^1.8.2",
43
- "@analogjs/vitest-angular": "^1.8.2",
41
+ "@analogjs/platform": "^1.9.0-beta.10",
42
+ "@analogjs/vite-plugin-angular": "^1.9.0-beta.10",
43
+ "@analogjs/vitest-angular": "^1.9.0-beta.10",
44
44
  "@angular/cli": "^18.0.0",
45
45
  "@angular/compiler-cli": "^18.0.0",
46
46
  "jsdom": "^22.0.0",
@@ -0,0 +1,16 @@
1
+ <script lang="ts">
2
+ import { RouterOutlet } from '@angular/router' with { analog: 'imports' };
3
+ </script>
4
+
5
+ <template>
6
+ <router-outlet />
7
+ </template>
8
+
9
+ <style>
10
+ :host {
11
+ max-width: 1280px;
12
+ margin: 0 auto;
13
+ padding: 2rem;
14
+ text-align: center;
15
+ }
16
+ </style>
@@ -0,0 +1,20 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+ import { provideRouter } from '@angular/router';
3
+ import { provideLocationMocks } from '@angular/common/testing';
4
+
5
+ import App from './app-root.ag';
6
+
7
+ describe('App', () => {
8
+ beforeEach(async () => {
9
+ await TestBed.configureTestingModule({
10
+ imports: [App],
11
+ providers: [provideRouter([]), provideLocationMocks()],
12
+ }).compileComponents();
13
+ });
14
+
15
+ it('should create the app', () => {
16
+ const fixture = TestBed.createComponent(App);
17
+ const app = fixture.componentInstance;
18
+ expect(app).toBeTruthy();
19
+ });
20
+ });
@@ -5,16 +5,14 @@ import { RouterOutlet } from '@angular/router';
5
5
  selector: 'app-root',
6
6
  standalone: true,
7
7
  imports: [RouterOutlet],
8
- template: ` <router-outlet></router-outlet> `,
9
- styles: [
10
- `
11
- :host {
12
- max-width: 1280px;
13
- margin: 0 auto;
14
- padding: 2rem;
15
- text-align: center;
16
- }
17
- `,
18
- ],
8
+ template: `<router-outlet />`,
9
+ styles: `
10
+ :host {
11
+ max-width: 1280px;
12
+ margin: 0 auto;
13
+ padding: 2rem;
14
+ text-align: center;
15
+ }
16
+ `,
19
17
  })
20
18
  export class AppComponent {}
@@ -0,0 +1,53 @@
1
+ <script lang="ts">
2
+ import { signal } from '@angular/core';
3
+
4
+ const count = signal(0);
5
+
6
+ function increment() {
7
+ this.count.update((count) => count + 1);
8
+ }
9
+ </script>
10
+
11
+ <template>
12
+ <div>
13
+ <a href="https://analogjs.org/" target="_blank">
14
+ <img alt="Analog Logo" class="logo analog" src="/analog.svg" />
15
+ </a>
16
+ </div>
17
+
18
+ <h2>Analog</h2>
19
+
20
+ <h3>The fullstack meta-framework for Angular!</h3>
21
+
22
+ <div class="card">
23
+ <button type="button" (click)="increment()">Count {{ count() }}</button>
24
+ </div>
25
+
26
+ <p class="read-the-docs">
27
+ <a href="https://analogjs.org" target="_blank">Docs</a> |
28
+ <a href="https://github.com/analogjs/analog" target="_blank">GitHub</a> |
29
+ <a href="https://github.com/sponsors/brandonroberts" target="_blank">
30
+ Sponsor
31
+ </a>
32
+ </p>
33
+ </template>
34
+
35
+ <style>
36
+ .logo {
37
+ will-change: filter;
38
+ }
39
+
40
+ .logo:hover {
41
+ filter: drop-shadow(0 0 2em #646cffaa);
42
+ }
43
+
44
+ .read-the-docs > * {
45
+ color: #fff;
46
+ }
47
+
48
+ @media (prefers-color-scheme: light) {
49
+ .read-the-docs > * {
50
+ color: #213547;
51
+ }
52
+ }
53
+ </style>
@@ -21,30 +21,30 @@ import { Component, signal } from '@angular/core';
21
21
  <p class="read-the-docs">
22
22
  <a href="https://analogjs.org" target="_blank">Docs</a> |
23
23
  <a href="https://github.com/analogjs/analog" target="_blank">GitHub</a> |
24
- <a href="https://github.com/sponsors/brandonroberts" target="_blank"
25
- >Sponsor</a
26
- >
24
+ <a href="https://github.com/sponsors/brandonroberts" target="_blank">
25
+ Sponsor
26
+ </a>
27
27
  </p>
28
28
  `,
29
- styles: [
30
- `
31
- .logo {
32
- will-change: filter;
33
- }
34
- .logo:hover {
35
- filter: drop-shadow(0 0 2em #646cffaa);
36
- }
37
- .read-the-docs > * {
38
- color: #fff;
39
- }
29
+ styles: `
30
+ .logo {
31
+ will-change: filter;
32
+ }
40
33
 
41
- @media (prefers-color-scheme: light) {
42
- .read-the-docs > * {
43
- color: #213547;
44
- }
34
+ .logo:hover {
35
+ filter: drop-shadow(0 0 2em #646cffaa);
36
+ }
37
+
38
+ .read-the-docs > * {
39
+ color: #fff;
40
+ }
41
+
42
+ @media (prefers-color-scheme: light) {
43
+ .read-the-docs > * {
44
+ color: #213547;
45
45
  }
46
- `,
47
- ],
46
+ }
47
+ `,
48
48
  })
49
49
  export default class HomeComponent {
50
50
  count = signal(0);
@@ -6,15 +6,15 @@ import { renderApplication } from '@angular/platform-server';
6
6
  import { provideServerContext } from '@analogjs/router/server';
7
7
  import { ServerContext } from '@analogjs/router/tokens';
8
8
 
9
+ __APP_COMPONENT_IMPORT__
9
10
  import { config } from './app/app.config.server';
10
- import { AppComponent } from './app/app.component';
11
11
 
12
12
  if (import.meta.env.PROD) {
13
13
  enableProdMode();
14
14
  }
15
15
 
16
16
  export function bootstrap() {
17
- return bootstrapApplication(AppComponent, config);
17
+ return bootstrapApplication(__APP_COMPONENT__, config);
18
18
  }
19
19
 
20
20
  export default async function render(
@@ -1,7 +1,7 @@
1
1
  import 'zone.js';
2
2
  import { bootstrapApplication } from '@angular/platform-browser';
3
3
 
4
- import { AppComponent } from './app/app.component';
4
+ __APP_COMPONENT_IMPORT__
5
5
  import { appConfig } from './app/app.config';
6
6
 
7
- bootstrapApplication(AppComponent, appConfig);
7
+ bootstrapApplication(__APP_COMPONENT__, appConfig);
@@ -21,6 +21,7 @@ a {
21
21
  color: #646cff;
22
22
  text-decoration: inherit;
23
23
  }
24
+
24
25
  a:hover {
25
26
  color: #535bf2;
26
27
  }
@@ -49,9 +50,11 @@ button {
49
50
  cursor: pointer;
50
51
  transition: border-color 0.25s;
51
52
  }
53
+
52
54
  button:hover {
53
55
  border-color: #646cff;
54
56
  }
57
+
55
58
  button:focus,
56
59
  button:focus-visible {
57
60
  outline: 4px auto -webkit-focus-ring-color;
@@ -66,9 +69,11 @@ button:focus-visible {
66
69
  color: #213547;
67
70
  background-color: #ffffff;
68
71
  }
72
+
69
73
  a:hover {
70
74
  color: #747bff;
71
75
  }
76
+
72
77
  button {
73
78
  background-color: #f9f9f9;
74
79
  }
@@ -11,7 +11,7 @@ export default defineConfig(({ mode }) => ({
11
11
  resolve: {
12
12
  mainFields: ['module'],
13
13
  },
14
- plugins: [analog()],
14
+ plugins: [analog(__ANALOG_SFC_CONFIG__)],
15
15
  test: {
16
16
  globals: true,
17
17
  environment: 'jsdom',
@@ -1,4 +1,4 @@
1
- # Analog App
1
+ # __PROJECT_TITLE__
2
2
 
3
3
  This project was generated with [Analog](https://analogjs.org), the fullstack meta-framework for Angular.
4
4
 
@@ -2,7 +2,7 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
- <title>My App</title>
5
+ <title>__PROJECT_TITLE__</title>
6
6
  <base href="/" />
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1" />
8
8
  <link rel="icon" type="image/x-icon" href="/favicon.ico" />
@@ -15,8 +15,8 @@
15
15
  },
16
16
  "private": true,
17
17
  "dependencies": {
18
- "@analogjs/content": "^1.7.3-beta.1",
19
- "@analogjs/router": "^1.7.3-beta.1",
18
+ "@analogjs/content": "^1.9.0-beta.10",
19
+ "@analogjs/router": "^1.9.0-beta.10",
20
20
  "@angular/animations": "^18.0.0",
21
21
  "@angular/build": "^18.0.0",
22
22
  "@angular/common": "^18.0.0",
@@ -38,9 +38,9 @@
38
38
  "zone.js": "~0.14.3"
39
39
  },
40
40
  "devDependencies": {
41
- "@analogjs/platform": "^1.7.3-beta.1",
42
- "@analogjs/vite-plugin-angular": "^1.7.3-beta.1",
43
- "@analogjs/vitest-angular": "^1.7.3-beta.1",
41
+ "@analogjs/platform": "^1.9.0-beta.10",
42
+ "@analogjs/vite-plugin-angular": "^1.9.0-beta.10",
43
+ "@analogjs/vitest-angular": "^1.9.0-beta.10",
44
44
  "@angular/cli": "^18.0.0",
45
45
  "@angular/compiler-cli": "^18.0.0",
46
46
  "typescript": "~5.4.2",
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ import { RouterOutlet } from '@angular/router' with { analog: 'imports' };
3
+ </script>
4
+
5
+ <template>
6
+ <router-outlet />
7
+ </template>
@@ -5,6 +5,6 @@ import { RouterOutlet } from '@angular/router';
5
5
  selector: 'app-root',
6
6
  standalone: true,
7
7
  imports: [RouterOutlet],
8
- template: `<router-outlet></router-outlet>`,
8
+ template: `<router-outlet />`,
9
9
  })
10
10
  export class AppComponent {}
@@ -0,0 +1,32 @@
1
+ <template>
2
+ <h2>Analog</h2>
3
+
4
+ <h3>The fullstack meta-framework for Angular!</h3>
5
+
6
+ <p class="read-the-docs">
7
+ <a href="https://analogjs.org" target="_blank">Docs</a> |
8
+ <a href="https://github.com/analogjs/analog" target="_blank">GitHub</a> |
9
+ <a href="https://github.com/sponsors/brandonroberts" target="_blank">
10
+ Sponsor
11
+ </a>
12
+ </p>
13
+ </template>
14
+
15
+ <style>
16
+ :host {
17
+ display: flex;
18
+ flex-direction: column;
19
+ justify-content: center;
20
+ align-items: center;
21
+ }
22
+
23
+ .read-the-docs > * {
24
+ color: #fff;
25
+ }
26
+
27
+ @media (prefers-color-scheme: light) {
28
+ .read-the-docs > * {
29
+ color: #213547;
30
+ }
31
+ }
32
+ </style>
@@ -11,9 +11,9 @@ import { Component } from '@angular/core';
11
11
  <p class="read-the-docs">
12
12
  <a href="https://analogjs.org" target="_blank">Docs</a> |
13
13
  <a href="https://github.com/analogjs/analog" target="_blank">GitHub</a> |
14
- <a href="https://github.com/sponsors/brandonroberts" target="_blank"
15
- >Sponsor</a
16
- >
14
+ <a href="https://github.com/sponsors/brandonroberts" target="_blank">
15
+ Sponsor
16
+ </a>
17
17
  </p>
18
18
  `,
19
19
  styles: `
@@ -23,6 +23,7 @@ import { Component } from '@angular/core';
23
23
  justify-content: center;
24
24
  align-items: center;
25
25
  }
26
+
26
27
  .read-the-docs > * {
27
28
  color: #fff;
28
29
  }
@@ -6,15 +6,15 @@ import { renderApplication } from '@angular/platform-server';
6
6
  import { provideServerContext } from '@analogjs/router/server';
7
7
  import { ServerContext } from '@analogjs/router/tokens';
8
8
 
9
+ __APP_COMPONENT_IMPORT__
9
10
  import { config } from './app/app.config.server';
10
- import { AppComponent } from './app/app.component';
11
11
 
12
12
  if (import.meta.env.PROD) {
13
13
  enableProdMode();
14
14
  }
15
15
 
16
16
  export function bootstrap() {
17
- return bootstrapApplication(AppComponent, config);
17
+ return bootstrapApplication(__APP_COMPONENT__, config);
18
18
  }
19
19
 
20
20
  export default async function render(
@@ -1,7 +1,7 @@
1
1
  import 'zone.js';
2
2
  import { bootstrapApplication } from '@angular/platform-browser';
3
3
 
4
- import { AppComponent } from './app/app.component';
4
+ __APP_COMPONENT_IMPORT__
5
5
  import { appConfig } from './app/app.config';
6
6
 
7
- bootstrapApplication(AppComponent, appConfig);
7
+ bootstrapApplication(__APP_COMPONENT__, appConfig);
@@ -17,7 +17,7 @@ export default defineConfig(({ mode }) => ({
17
17
  static: true,
18
18
  prerender: {
19
19
  routes: [],
20
- },
20
+ },__ANALOG_SFC_CONFIG__
21
21
  }),
22
22
  ],
23
23
  }));
@@ -1,8 +0,0 @@
1
- /** @type {import('tailwindcss').Config} */
2
- module.exports = {
3
- content: ['./index.html', './src/**/*.{html,ts,md}'],
4
- theme: {
5
- extend: {},
6
- },
7
- plugins: [],
8
- };