@unhead/angular 2.0.0-rc.8 → 2.0.0-rc.9
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.
- package/README.md +171 -171
- package/client.d.ts +1 -1
- package/dist/README.md +171 -171
- package/dist/fesm2022/unhead-angular-client.mjs.map +1 -1
- package/dist/fesm2022/unhead-angular-server.mjs.map +1 -1
- package/dist/fesm2022/unhead-angular.mjs.map +1 -1
- package/package.json +2 -2
- package/server.d.ts +1 -1
package/README.md
CHANGED
|
@@ -1,171 +1,171 @@
|
|
|
1
|
-
# @unhead/angular
|
|
2
|
-
|
|
3
|
-
> Full-stack `<head>` management for Angular applications
|
|
4
|
-
|
|
5
|
-
[![npm version][npm-version-src]][npm-version-href]
|
|
6
|
-
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
7
|
-
[![License][license-src]][license-href]
|
|
8
|
-
|
|
9
|
-
## Features
|
|
10
|
-
|
|
11
|
-
- 🧩 Angular-optimized head management
|
|
12
|
-
- 🔄 Reactive titles, meta tags, and other head elements
|
|
13
|
-
- 🔍 SEO-friendly head control
|
|
14
|
-
- 🖥️ Server-side rendering support
|
|
15
|
-
- 💉 Angular dependency injection integration
|
|
16
|
-
- 📦 Lightweight with zero dependencies (except for Angular & unhead)
|
|
17
|
-
|
|
18
|
-
## Installation
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
# npm
|
|
22
|
-
npm install @unhead/angular
|
|
23
|
-
|
|
24
|
-
# yarn
|
|
25
|
-
yarn add @unhead/angular
|
|
26
|
-
|
|
27
|
-
# pnpm
|
|
28
|
-
pnpm add @unhead/angular
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Usage
|
|
32
|
-
|
|
33
|
-
### Setup
|
|
34
|
-
|
|
35
|
-
First, provide the Unhead service in your application:
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
// app.config.ts
|
|
39
|
-
import { ApplicationConfig } from '@angular/core'
|
|
40
|
-
import { provideClientHead } from '@unhead/angular'
|
|
41
|
-
|
|
42
|
-
export const appConfig: ApplicationConfig = {
|
|
43
|
-
providers: [
|
|
44
|
-
// ... other providers
|
|
45
|
-
provideClientHead(),
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
For server-side rendering (Angular Universal):
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
// server.ts
|
|
54
|
-
import { provideServerHead } from '@unhead/angular'
|
|
55
|
-
|
|
56
|
-
// In your server module providers:
|
|
57
|
-
providers: [
|
|
58
|
-
// ... other providers
|
|
59
|
-
provideServerHead(),
|
|
60
|
-
]
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Basic Usage
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
// app.component.ts
|
|
67
|
-
import { Component } from '@angular/core'
|
|
68
|
-
import { Unhead } from '@unhead/angular'
|
|
69
|
-
|
|
70
|
-
@Component({
|
|
71
|
-
selector: 'app-root',
|
|
72
|
-
template: '<router-outlet></router-outlet>',
|
|
73
|
-
})
|
|
74
|
-
export class AppComponent {
|
|
75
|
-
constructor(private unhead: Unhead) {
|
|
76
|
-
// Set page title
|
|
77
|
-
this.unhead.useHead({
|
|
78
|
-
title: 'My Application',
|
|
79
|
-
})
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Setting Meta Tags
|
|
85
|
-
|
|
86
|
-
```typescript
|
|
87
|
-
// home.component.ts
|
|
88
|
-
import { Component, OnInit } from '@angular/core'
|
|
89
|
-
import { Unhead } from '@unhead/angular'
|
|
90
|
-
|
|
91
|
-
@Component({
|
|
92
|
-
selector: 'app-home',
|
|
93
|
-
template: '<h1>Home</h1>',
|
|
94
|
-
})
|
|
95
|
-
export class HomeComponent implements OnInit {
|
|
96
|
-
constructor(private unhead: Unhead) {}
|
|
97
|
-
|
|
98
|
-
ngOnInit() {
|
|
99
|
-
this.unhead.useSeoMeta({
|
|
100
|
-
title: 'Home Page',
|
|
101
|
-
description: 'Welcome to our website',
|
|
102
|
-
ogTitle: 'Welcome to Home Page',
|
|
103
|
-
ogDescription: 'Our fantastic home page',
|
|
104
|
-
ogImage: 'https://example.com/image.jpg',
|
|
105
|
-
})
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Reactive Head Elements
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
// profile.component.ts
|
|
114
|
-
import { Component, signal } from '@angular/core'
|
|
115
|
-
import { Unhead } from '@unhead/angular'
|
|
116
|
-
|
|
117
|
-
@Component({
|
|
118
|
-
selector: 'app-profile',
|
|
119
|
-
template: `
|
|
120
|
-
<h1>{{ userName() }}'s Profile</h1>
|
|
121
|
-
<button (click)="updateName('New Name')">Update Name</button>
|
|
122
|
-
`,
|
|
123
|
-
})
|
|
124
|
-
export class ProfileComponent {
|
|
125
|
-
userName = signal('User')
|
|
126
|
-
|
|
127
|
-
constructor(private unhead: Unhead) {
|
|
128
|
-
this.unhead.useHead({
|
|
129
|
-
title: () => `${this.userName()} - Profile`, // Reactive title
|
|
130
|
-
meta: [
|
|
131
|
-
{
|
|
132
|
-
name: 'description',
|
|
133
|
-
content: () => `${this.userName()}'s profile page`, // Reactive description
|
|
134
|
-
},
|
|
135
|
-
],
|
|
136
|
-
})
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
updateName(name: string) {
|
|
140
|
-
this.userName.set(name)
|
|
141
|
-
// Title and meta automatically update!
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## Development
|
|
147
|
-
|
|
148
|
-
```bash
|
|
149
|
-
# Install dependencies
|
|
150
|
-
npm install
|
|
151
|
-
|
|
152
|
-
# Generate build files
|
|
153
|
-
npm run build
|
|
154
|
-
|
|
155
|
-
# Run tests
|
|
156
|
-
npm run test
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
## License
|
|
160
|
-
|
|
161
|
-
[MIT](./LICENSE)
|
|
162
|
-
|
|
163
|
-
<!-- Badges -->
|
|
164
|
-
[npm-version-src]: https://img.shields.io/npm/v/@unhead/angular/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
165
|
-
[npm-version-href]: https://npmjs.com/package/@unhead/angular
|
|
166
|
-
|
|
167
|
-
[npm-downloads-src]: https://img.shields.io/npm/dm/@unhead/angular.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
168
|
-
[npm-downloads-href]: https://npmjs.com/package/@unhead/angular
|
|
169
|
-
|
|
170
|
-
[license-src]: https://img.shields.io/github/license/unjs/unhead.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
171
|
-
[license-href]: https://github.com/unjs/unhead/blob/main/LICENSE
|
|
1
|
+
# @unhead/angular
|
|
2
|
+
|
|
3
|
+
> Full-stack `<head>` management for Angular applications
|
|
4
|
+
|
|
5
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
6
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
7
|
+
[![License][license-src]][license-href]
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 🧩 Angular-optimized head management
|
|
12
|
+
- 🔄 Reactive titles, meta tags, and other head elements
|
|
13
|
+
- 🔍 SEO-friendly head control
|
|
14
|
+
- 🖥️ Server-side rendering support
|
|
15
|
+
- 💉 Angular dependency injection integration
|
|
16
|
+
- 📦 Lightweight with zero dependencies (except for Angular & unhead)
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# npm
|
|
22
|
+
npm install @unhead/angular
|
|
23
|
+
|
|
24
|
+
# yarn
|
|
25
|
+
yarn add @unhead/angular
|
|
26
|
+
|
|
27
|
+
# pnpm
|
|
28
|
+
pnpm add @unhead/angular
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### Setup
|
|
34
|
+
|
|
35
|
+
First, provide the Unhead service in your application:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// app.config.ts
|
|
39
|
+
import { ApplicationConfig } from '@angular/core'
|
|
40
|
+
import { provideClientHead } from '@unhead/angular'
|
|
41
|
+
|
|
42
|
+
export const appConfig: ApplicationConfig = {
|
|
43
|
+
providers: [
|
|
44
|
+
// ... other providers
|
|
45
|
+
provideClientHead(),
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
For server-side rendering (Angular Universal):
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// server.ts
|
|
54
|
+
import { provideServerHead } from '@unhead/angular'
|
|
55
|
+
|
|
56
|
+
// In your server module providers:
|
|
57
|
+
providers: [
|
|
58
|
+
// ... other providers
|
|
59
|
+
provideServerHead(),
|
|
60
|
+
]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Basic Usage
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// app.component.ts
|
|
67
|
+
import { Component } from '@angular/core'
|
|
68
|
+
import { Unhead } from '@unhead/angular'
|
|
69
|
+
|
|
70
|
+
@Component({
|
|
71
|
+
selector: 'app-root',
|
|
72
|
+
template: '<router-outlet></router-outlet>',
|
|
73
|
+
})
|
|
74
|
+
export class AppComponent {
|
|
75
|
+
constructor(private unhead: Unhead) {
|
|
76
|
+
// Set page title
|
|
77
|
+
this.unhead.useHead({
|
|
78
|
+
title: 'My Application',
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Setting Meta Tags
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// home.component.ts
|
|
88
|
+
import { Component, OnInit } from '@angular/core'
|
|
89
|
+
import { Unhead } from '@unhead/angular'
|
|
90
|
+
|
|
91
|
+
@Component({
|
|
92
|
+
selector: 'app-home',
|
|
93
|
+
template: '<h1>Home</h1>',
|
|
94
|
+
})
|
|
95
|
+
export class HomeComponent implements OnInit {
|
|
96
|
+
constructor(private unhead: Unhead) {}
|
|
97
|
+
|
|
98
|
+
ngOnInit() {
|
|
99
|
+
this.unhead.useSeoMeta({
|
|
100
|
+
title: 'Home Page',
|
|
101
|
+
description: 'Welcome to our website',
|
|
102
|
+
ogTitle: 'Welcome to Home Page',
|
|
103
|
+
ogDescription: 'Our fantastic home page',
|
|
104
|
+
ogImage: 'https://example.com/image.jpg',
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Reactive Head Elements
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// profile.component.ts
|
|
114
|
+
import { Component, signal } from '@angular/core'
|
|
115
|
+
import { Unhead } from '@unhead/angular'
|
|
116
|
+
|
|
117
|
+
@Component({
|
|
118
|
+
selector: 'app-profile',
|
|
119
|
+
template: `
|
|
120
|
+
<h1>{{ userName() }}'s Profile</h1>
|
|
121
|
+
<button (click)="updateName('New Name')">Update Name</button>
|
|
122
|
+
`,
|
|
123
|
+
})
|
|
124
|
+
export class ProfileComponent {
|
|
125
|
+
userName = signal('User')
|
|
126
|
+
|
|
127
|
+
constructor(private unhead: Unhead) {
|
|
128
|
+
this.unhead.useHead({
|
|
129
|
+
title: () => `${this.userName()} - Profile`, // Reactive title
|
|
130
|
+
meta: [
|
|
131
|
+
{
|
|
132
|
+
name: 'description',
|
|
133
|
+
content: () => `${this.userName()}'s profile page`, // Reactive description
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
updateName(name: string) {
|
|
140
|
+
this.userName.set(name)
|
|
141
|
+
// Title and meta automatically update!
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Development
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Install dependencies
|
|
150
|
+
npm install
|
|
151
|
+
|
|
152
|
+
# Generate build files
|
|
153
|
+
npm run build
|
|
154
|
+
|
|
155
|
+
# Run tests
|
|
156
|
+
npm run test
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
[MIT](./LICENSE)
|
|
162
|
+
|
|
163
|
+
<!-- Badges -->
|
|
164
|
+
[npm-version-src]: https://img.shields.io/npm/v/@unhead/angular/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
165
|
+
[npm-version-href]: https://npmjs.com/package/@unhead/angular
|
|
166
|
+
|
|
167
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/@unhead/angular.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
168
|
+
[npm-downloads-href]: https://npmjs.com/package/@unhead/angular
|
|
169
|
+
|
|
170
|
+
[license-src]: https://img.shields.io/github/license/unjs/unhead.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
171
|
+
[license-href]: https://github.com/unjs/unhead/blob/main/LICENSE
|
package/client.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './dist/client'
|
|
1
|
+
export * from './dist/client'
|
package/dist/README.md
CHANGED
|
@@ -1,171 +1,171 @@
|
|
|
1
|
-
# @unhead/angular
|
|
2
|
-
|
|
3
|
-
> Full-stack `<head>` management for Angular applications
|
|
4
|
-
|
|
5
|
-
[![npm version][npm-version-src]][npm-version-href]
|
|
6
|
-
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
7
|
-
[![License][license-src]][license-href]
|
|
8
|
-
|
|
9
|
-
## Features
|
|
10
|
-
|
|
11
|
-
- 🧩 Angular-optimized head management
|
|
12
|
-
- 🔄 Reactive titles, meta tags, and other head elements
|
|
13
|
-
- 🔍 SEO-friendly head control
|
|
14
|
-
- 🖥️ Server-side rendering support
|
|
15
|
-
- 💉 Angular dependency injection integration
|
|
16
|
-
- 📦 Lightweight with zero dependencies (except for Angular & unhead)
|
|
17
|
-
|
|
18
|
-
## Installation
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
# npm
|
|
22
|
-
npm install @unhead/angular
|
|
23
|
-
|
|
24
|
-
# yarn
|
|
25
|
-
yarn add @unhead/angular
|
|
26
|
-
|
|
27
|
-
# pnpm
|
|
28
|
-
pnpm add @unhead/angular
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## Usage
|
|
32
|
-
|
|
33
|
-
### Setup
|
|
34
|
-
|
|
35
|
-
First, provide the Unhead service in your application:
|
|
36
|
-
|
|
37
|
-
```typescript
|
|
38
|
-
// app.config.ts
|
|
39
|
-
import { ApplicationConfig } from '@angular/core'
|
|
40
|
-
import { provideClientHead } from '@unhead/angular'
|
|
41
|
-
|
|
42
|
-
export const appConfig: ApplicationConfig = {
|
|
43
|
-
providers: [
|
|
44
|
-
// ... other providers
|
|
45
|
-
provideClientHead(),
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
For server-side rendering (Angular Universal):
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
// server.ts
|
|
54
|
-
import { provideServerHead } from '@unhead/angular'
|
|
55
|
-
|
|
56
|
-
// In your server module providers:
|
|
57
|
-
providers: [
|
|
58
|
-
// ... other providers
|
|
59
|
-
provideServerHead(),
|
|
60
|
-
]
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### Basic Usage
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
// app.component.ts
|
|
67
|
-
import { Component } from '@angular/core'
|
|
68
|
-
import { Unhead } from '@unhead/angular'
|
|
69
|
-
|
|
70
|
-
@Component({
|
|
71
|
-
selector: 'app-root',
|
|
72
|
-
template: '<router-outlet></router-outlet>',
|
|
73
|
-
})
|
|
74
|
-
export class AppComponent {
|
|
75
|
-
constructor(private unhead: Unhead) {
|
|
76
|
-
// Set page title
|
|
77
|
-
this.unhead.useHead({
|
|
78
|
-
title: 'My Application',
|
|
79
|
-
})
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Setting Meta Tags
|
|
85
|
-
|
|
86
|
-
```typescript
|
|
87
|
-
// home.component.ts
|
|
88
|
-
import { Component, OnInit } from '@angular/core'
|
|
89
|
-
import { Unhead } from '@unhead/angular'
|
|
90
|
-
|
|
91
|
-
@Component({
|
|
92
|
-
selector: 'app-home',
|
|
93
|
-
template: '<h1>Home</h1>',
|
|
94
|
-
})
|
|
95
|
-
export class HomeComponent implements OnInit {
|
|
96
|
-
constructor(private unhead: Unhead) {}
|
|
97
|
-
|
|
98
|
-
ngOnInit() {
|
|
99
|
-
this.unhead.useSeoMeta({
|
|
100
|
-
title: 'Home Page',
|
|
101
|
-
description: 'Welcome to our website',
|
|
102
|
-
ogTitle: 'Welcome to Home Page',
|
|
103
|
-
ogDescription: 'Our fantastic home page',
|
|
104
|
-
ogImage: 'https://example.com/image.jpg',
|
|
105
|
-
})
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### Reactive Head Elements
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
// profile.component.ts
|
|
114
|
-
import { Component, signal } from '@angular/core'
|
|
115
|
-
import { Unhead } from '@unhead/angular'
|
|
116
|
-
|
|
117
|
-
@Component({
|
|
118
|
-
selector: 'app-profile',
|
|
119
|
-
template: `
|
|
120
|
-
<h1>{{ userName() }}'s Profile</h1>
|
|
121
|
-
<button (click)="updateName('New Name')">Update Name</button>
|
|
122
|
-
`,
|
|
123
|
-
})
|
|
124
|
-
export class ProfileComponent {
|
|
125
|
-
userName = signal('User')
|
|
126
|
-
|
|
127
|
-
constructor(private unhead: Unhead) {
|
|
128
|
-
this.unhead.useHead({
|
|
129
|
-
title: () => `${this.userName()} - Profile`, // Reactive title
|
|
130
|
-
meta: [
|
|
131
|
-
{
|
|
132
|
-
name: 'description',
|
|
133
|
-
content: () => `${this.userName()}'s profile page`, // Reactive description
|
|
134
|
-
},
|
|
135
|
-
],
|
|
136
|
-
})
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
updateName(name: string) {
|
|
140
|
-
this.userName.set(name)
|
|
141
|
-
// Title and meta automatically update!
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
## Development
|
|
147
|
-
|
|
148
|
-
```bash
|
|
149
|
-
# Install dependencies
|
|
150
|
-
npm install
|
|
151
|
-
|
|
152
|
-
# Generate build files
|
|
153
|
-
npm run build
|
|
154
|
-
|
|
155
|
-
# Run tests
|
|
156
|
-
npm run test
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
## License
|
|
160
|
-
|
|
161
|
-
[MIT](./LICENSE)
|
|
162
|
-
|
|
163
|
-
<!-- Badges -->
|
|
164
|
-
[npm-version-src]: https://img.shields.io/npm/v/@unhead/angular/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
165
|
-
[npm-version-href]: https://npmjs.com/package/@unhead/angular
|
|
166
|
-
|
|
167
|
-
[npm-downloads-src]: https://img.shields.io/npm/dm/@unhead/angular.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
168
|
-
[npm-downloads-href]: https://npmjs.com/package/@unhead/angular
|
|
169
|
-
|
|
170
|
-
[license-src]: https://img.shields.io/github/license/unjs/unhead.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
171
|
-
[license-href]: https://github.com/unjs/unhead/blob/main/LICENSE
|
|
1
|
+
# @unhead/angular
|
|
2
|
+
|
|
3
|
+
> Full-stack `<head>` management for Angular applications
|
|
4
|
+
|
|
5
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
6
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
7
|
+
[![License][license-src]][license-href]
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- 🧩 Angular-optimized head management
|
|
12
|
+
- 🔄 Reactive titles, meta tags, and other head elements
|
|
13
|
+
- 🔍 SEO-friendly head control
|
|
14
|
+
- 🖥️ Server-side rendering support
|
|
15
|
+
- 💉 Angular dependency injection integration
|
|
16
|
+
- 📦 Lightweight with zero dependencies (except for Angular & unhead)
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# npm
|
|
22
|
+
npm install @unhead/angular
|
|
23
|
+
|
|
24
|
+
# yarn
|
|
25
|
+
yarn add @unhead/angular
|
|
26
|
+
|
|
27
|
+
# pnpm
|
|
28
|
+
pnpm add @unhead/angular
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### Setup
|
|
34
|
+
|
|
35
|
+
First, provide the Unhead service in your application:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// app.config.ts
|
|
39
|
+
import { ApplicationConfig } from '@angular/core'
|
|
40
|
+
import { provideClientHead } from '@unhead/angular'
|
|
41
|
+
|
|
42
|
+
export const appConfig: ApplicationConfig = {
|
|
43
|
+
providers: [
|
|
44
|
+
// ... other providers
|
|
45
|
+
provideClientHead(),
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
For server-side rendering (Angular Universal):
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// server.ts
|
|
54
|
+
import { provideServerHead } from '@unhead/angular'
|
|
55
|
+
|
|
56
|
+
// In your server module providers:
|
|
57
|
+
providers: [
|
|
58
|
+
// ... other providers
|
|
59
|
+
provideServerHead(),
|
|
60
|
+
]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Basic Usage
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// app.component.ts
|
|
67
|
+
import { Component } from '@angular/core'
|
|
68
|
+
import { Unhead } from '@unhead/angular'
|
|
69
|
+
|
|
70
|
+
@Component({
|
|
71
|
+
selector: 'app-root',
|
|
72
|
+
template: '<router-outlet></router-outlet>',
|
|
73
|
+
})
|
|
74
|
+
export class AppComponent {
|
|
75
|
+
constructor(private unhead: Unhead) {
|
|
76
|
+
// Set page title
|
|
77
|
+
this.unhead.useHead({
|
|
78
|
+
title: 'My Application',
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Setting Meta Tags
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
// home.component.ts
|
|
88
|
+
import { Component, OnInit } from '@angular/core'
|
|
89
|
+
import { Unhead } from '@unhead/angular'
|
|
90
|
+
|
|
91
|
+
@Component({
|
|
92
|
+
selector: 'app-home',
|
|
93
|
+
template: '<h1>Home</h1>',
|
|
94
|
+
})
|
|
95
|
+
export class HomeComponent implements OnInit {
|
|
96
|
+
constructor(private unhead: Unhead) {}
|
|
97
|
+
|
|
98
|
+
ngOnInit() {
|
|
99
|
+
this.unhead.useSeoMeta({
|
|
100
|
+
title: 'Home Page',
|
|
101
|
+
description: 'Welcome to our website',
|
|
102
|
+
ogTitle: 'Welcome to Home Page',
|
|
103
|
+
ogDescription: 'Our fantastic home page',
|
|
104
|
+
ogImage: 'https://example.com/image.jpg',
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Reactive Head Elements
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// profile.component.ts
|
|
114
|
+
import { Component, signal } from '@angular/core'
|
|
115
|
+
import { Unhead } from '@unhead/angular'
|
|
116
|
+
|
|
117
|
+
@Component({
|
|
118
|
+
selector: 'app-profile',
|
|
119
|
+
template: `
|
|
120
|
+
<h1>{{ userName() }}'s Profile</h1>
|
|
121
|
+
<button (click)="updateName('New Name')">Update Name</button>
|
|
122
|
+
`,
|
|
123
|
+
})
|
|
124
|
+
export class ProfileComponent {
|
|
125
|
+
userName = signal('User')
|
|
126
|
+
|
|
127
|
+
constructor(private unhead: Unhead) {
|
|
128
|
+
this.unhead.useHead({
|
|
129
|
+
title: () => `${this.userName()} - Profile`, // Reactive title
|
|
130
|
+
meta: [
|
|
131
|
+
{
|
|
132
|
+
name: 'description',
|
|
133
|
+
content: () => `${this.userName()}'s profile page`, // Reactive description
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
updateName(name: string) {
|
|
140
|
+
this.userName.set(name)
|
|
141
|
+
// Title and meta automatically update!
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Development
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Install dependencies
|
|
150
|
+
npm install
|
|
151
|
+
|
|
152
|
+
# Generate build files
|
|
153
|
+
npm run build
|
|
154
|
+
|
|
155
|
+
# Run tests
|
|
156
|
+
npm run test
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
[MIT](./LICENSE)
|
|
162
|
+
|
|
163
|
+
<!-- Badges -->
|
|
164
|
+
[npm-version-src]: https://img.shields.io/npm/v/@unhead/angular/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
165
|
+
[npm-version-href]: https://npmjs.com/package/@unhead/angular
|
|
166
|
+
|
|
167
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/@unhead/angular.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
168
|
+
[npm-downloads-href]: https://npmjs.com/package/@unhead/angular
|
|
169
|
+
|
|
170
|
+
[license-src]: https://img.shields.io/github/license/unjs/unhead.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
171
|
+
[license-href]: https://github.com/unjs/unhead/blob/main/LICENSE
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unhead-angular-client.mjs","sources":["../../client/src/client.ts","../../client/src/public_api.ts","../../client/src/unhead-angular-client.ts"],"sourcesContent":["import type { CreateClientHeadOptions } from 'unhead/types'\nimport { DOCUMENT } from '@angular/common'\nimport { inject, makeEnvironmentProviders } from '@angular/core'\nimport { UnheadInjectionToken } from '@unhead/angular'\nimport { createHead as _createClientHead, createDebouncedFn, renderDOMHead } from 'unhead/client'\n\nexport function provideClientHead(options: CreateClientHeadOptions = {}) {\n return makeEnvironmentProviders([{\n provide: UnheadInjectionToken,\n useFactory: () => {\n const document = inject(DOCUMENT)\n const head = _createClientHead({\n document,\n domOptions: {\n render: createDebouncedFn(() => renderDOMHead(head), fn => setTimeout(() => fn(), 0)),\n },\n ...options,\n })\n return head\n },\n }])\n}\n","/*\n * Public API Surface of unhead\n */\n\nexport * from './client'\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["_createClientHead"],"mappings":";;;;;AAMgB,SAAA,iBAAiB,CAAC,OAAA,GAAmC,EAAE,EAAA;IACrE,OAAO,wBAAwB,CAAC,CAAC;AAC/B,YAAA,OAAO,EAAE,oBAAoB;YAC7B,UAAU,EAAE,MAAK;AACf,gBAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;gBACjC,MAAM,IAAI,GAAGA,UAAiB,CAAC;oBAC7B,QAAQ;AACR,oBAAA,UAAU,EAAE;wBACV,MAAM,EAAE,iBAAiB,CAAC,MAAM,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACtF,qBAAA;AACD,oBAAA,GAAG,OAAO;AACX,iBAAA,CAAC;AACF,gBAAA,OAAO,IAAI;aACZ;AACF,SAAA,CAAC,CAAC;AACL;;ACrBA;;AAEG;;ACFH;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"unhead-angular-client.mjs","sources":["../../client/src/client.ts","../../client/src/public_api.ts","../../client/src/unhead-angular-client.ts"],"sourcesContent":["import type { CreateClientHeadOptions } from 'unhead/types'\r\nimport { DOCUMENT } from '@angular/common'\r\nimport { inject, makeEnvironmentProviders } from '@angular/core'\r\nimport { UnheadInjectionToken } from '@unhead/angular'\r\nimport { createHead as _createClientHead, createDebouncedFn, renderDOMHead } from 'unhead/client'\r\n\r\nexport function provideClientHead(options: CreateClientHeadOptions = {}) {\r\n return makeEnvironmentProviders([{\r\n provide: UnheadInjectionToken,\r\n useFactory: () => {\r\n const document = inject(DOCUMENT)\r\n const head = _createClientHead({\r\n document,\r\n domOptions: {\r\n render: createDebouncedFn(() => renderDOMHead(head), fn => setTimeout(() => fn(), 0)),\r\n },\r\n ...options,\r\n })\r\n return head\r\n },\r\n }])\r\n}\r\n","/*\r\n * Public API Surface of unhead\r\n */\r\n\r\nexport * from './client'\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["_createClientHead"],"mappings":";;;;;AAMgB,SAAA,iBAAiB,CAAC,OAAA,GAAmC,EAAE,EAAA;IACrE,OAAO,wBAAwB,CAAC,CAAC;AAC/B,YAAA,OAAO,EAAE,oBAAoB;YAC7B,UAAU,EAAE,MAAK;AACf,gBAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;gBACjC,MAAM,IAAI,GAAGA,UAAiB,CAAC;oBAC7B,QAAQ;AACR,oBAAA,UAAU,EAAE;wBACV,MAAM,EAAE,iBAAiB,CAAC,MAAM,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACtF,qBAAA;AACD,oBAAA,GAAG,OAAO;AACX,iBAAA,CAAC;AACF,gBAAA,OAAO,IAAI;aACZ;AACF,SAAA,CAAC,CAAC;AACL;;ACrBA;;AAEG;;ACFH;;AAEG;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unhead-angular-server.mjs","sources":["../../server/src/ssr.service.ts","../../server/src/server.ts","../../server/src/public_api.ts","../../server/src/unhead-angular-server.ts"],"sourcesContent":["import type { Unhead as UnheadSchema } from 'unhead/types'\nimport { DOCUMENT } from '@angular/common'\nimport { Inject, Injectable } from '@angular/core'\nimport { UnheadInjectionToken } from '@unhead/angular'\nimport { extractUnheadInputFromHtml, renderSSRHead } from 'unhead/server'\n\nfunction attrToElement(element: HTMLElement, acc: string) {\n const [key, value] = acc.match(/([a-z0-9-]+)(?:=\"([^\"]*)\")?/i)?.slice(1, 3) || []\n if (!key)\n return\n\n if (value === undefined) {\n element.setAttribute(key, '')\n }\n else if (key === 'style') {\n const styleObj = value.split(';').reduce((acc, style) => {\n const [prop, val] = style.split(':').map(s => s.trim())\n if (prop && val)\n acc[prop] = val\n return acc\n }, {} as Record<string, string>)\n Object.entries(styleObj).forEach(([prop, val]) => {\n element.style.setProperty(prop, val)\n })\n }\n else if (key === 'class') {\n value.split(' ').forEach(className => element.classList.add(className))\n }\n else {\n element.setAttribute(key, value)\n }\n}\n\nconst attrRegex = /([a-z0-9-]+(?:=\"[^\"]*\")?)/gi\n\n@Injectable({\n providedIn: 'root',\n})\nexport class UnheadSSRService {\n constructor(\n @Inject(DOCUMENT) private document: Document,\n @Inject(UnheadInjectionToken) private unhead: UnheadSchema,\n ) {}\n\n async render() {\n const { input } = extractUnheadInputFromHtml(this.document.documentElement.outerHTML)\n this.unhead.entries.set(0, { _i: 0, input, options: {} })\n const { headTags, htmlAttrs, bodyAttrs, bodyTags, bodyTagsOpen } = await renderSSRHead(this.unhead, {\n omitLineBreaks: false,\n })\n htmlAttrs.match(attrRegex)?.forEach(attr => attrToElement(this.document.documentElement, attr))\n bodyAttrs.match(attrRegex)?.forEach(attr => attrToElement(this.document.body, attr))\n this.document.body.innerHTML = bodyTagsOpen + this.document.body.innerHTML + bodyTags\n this.document.head.innerHTML = headTags\n }\n}\n","import type { CreateServerHeadOptions } from 'unhead/types'\nimport { makeEnvironmentProviders } from '@angular/core'\nimport { BEFORE_APP_SERIALIZED } from '@angular/platform-server'\nimport { UnheadInjectionToken } from '@unhead/angular'\nimport { createHead as _createServerHead } from 'unhead/server'\nimport { UnheadSSRService } from './ssr.service'\n\nexport function provideServerHead(options: CreateServerHeadOptions = {}) {\n const head = _createServerHead(options)\n return makeEnvironmentProviders([\n { provide: UnheadInjectionToken, useValue: head },\n UnheadSSRService,\n {\n provide: BEFORE_APP_SERIALIZED,\n useFactory: (service: UnheadSSRService) => () => {\n return service.render()\n },\n deps: [UnheadSSRService],\n multi: true,\n },\n ])\n}\n","/*\n * Public API Surface of unhead\n */\n\nexport * from './server'\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["_createServerHead"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"unhead-angular-server.mjs","sources":["../../server/src/ssr.service.ts","../../server/src/server.ts","../../server/src/public_api.ts","../../server/src/unhead-angular-server.ts"],"sourcesContent":["import type { Unhead as UnheadSchema } from 'unhead/types'\r\nimport { DOCUMENT } from '@angular/common'\r\nimport { Inject, Injectable } from '@angular/core'\r\nimport { UnheadInjectionToken } from '@unhead/angular'\r\nimport { extractUnheadInputFromHtml, renderSSRHead } from 'unhead/server'\r\n\r\nfunction attrToElement(element: HTMLElement, acc: string) {\r\n const [key, value] = acc.match(/([a-z0-9-]+)(?:=\"([^\"]*)\")?/i)?.slice(1, 3) || []\r\n if (!key)\r\n return\r\n\r\n if (value === undefined) {\r\n element.setAttribute(key, '')\r\n }\r\n else if (key === 'style') {\r\n const styleObj = value.split(';').reduce((acc, style) => {\r\n const [prop, val] = style.split(':').map(s => s.trim())\r\n if (prop && val)\r\n acc[prop] = val\r\n return acc\r\n }, {} as Record<string, string>)\r\n Object.entries(styleObj).forEach(([prop, val]) => {\r\n element.style.setProperty(prop, val)\r\n })\r\n }\r\n else if (key === 'class') {\r\n value.split(' ').forEach(className => element.classList.add(className))\r\n }\r\n else {\r\n element.setAttribute(key, value)\r\n }\r\n}\r\n\r\nconst attrRegex = /([a-z0-9-]+(?:=\"[^\"]*\")?)/gi\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class UnheadSSRService {\r\n constructor(\r\n @Inject(DOCUMENT) private document: Document,\r\n @Inject(UnheadInjectionToken) private unhead: UnheadSchema,\r\n ) {}\r\n\r\n async render() {\r\n const { input } = extractUnheadInputFromHtml(this.document.documentElement.outerHTML)\r\n this.unhead.entries.set(0, { _i: 0, input, options: {} })\r\n const { headTags, htmlAttrs, bodyAttrs, bodyTags, bodyTagsOpen } = await renderSSRHead(this.unhead, {\r\n omitLineBreaks: false,\r\n })\r\n htmlAttrs.match(attrRegex)?.forEach(attr => attrToElement(this.document.documentElement, attr))\r\n bodyAttrs.match(attrRegex)?.forEach(attr => attrToElement(this.document.body, attr))\r\n this.document.body.innerHTML = bodyTagsOpen + this.document.body.innerHTML + bodyTags\r\n this.document.head.innerHTML = headTags\r\n }\r\n}\r\n","import type { CreateServerHeadOptions } from 'unhead/types'\r\nimport { makeEnvironmentProviders } from '@angular/core'\r\nimport { BEFORE_APP_SERIALIZED } from '@angular/platform-server'\r\nimport { UnheadInjectionToken } from '@unhead/angular'\r\nimport { createHead as _createServerHead } from 'unhead/server'\r\nimport { UnheadSSRService } from './ssr.service'\r\n\r\nexport function provideServerHead(options: CreateServerHeadOptions = {}) {\r\n const head = _createServerHead(options)\r\n return makeEnvironmentProviders([\r\n { provide: UnheadInjectionToken, useValue: head },\r\n UnheadSSRService,\r\n {\r\n provide: BEFORE_APP_SERIALIZED,\r\n useFactory: (service: UnheadSSRService) => () => {\r\n return service.render()\r\n },\r\n deps: [UnheadSSRService],\r\n multi: true,\r\n },\r\n ])\r\n}\r\n","/*\r\n * Public API Surface of unhead\r\n */\r\n\r\nexport * from './server'\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["_createServerHead"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unhead-angular.mjs","sources":["../../src/context.ts","../../src/composables.ts","../../src/head.component.ts","../../src/public-api.ts","../../src/unhead-angular.ts"],"sourcesContent":["import type { Unhead } from 'unhead/types'\nimport { InjectionToken } from '@angular/core'\n\nexport const headSymbol = 'usehead'\n\nexport const UnheadInjectionToken = new InjectionToken<Unhead>(headSymbol)\n","import type { UseScriptInput, UseScriptOptions, UseScriptReturn } from 'unhead/scripts'\nimport type { ActiveHeadEntry, HeadEntryOptions, HeadSafe, Unhead, UseHeadInput, UseSeoMetaInput } from 'unhead/types'\nimport { DestroyRef, effect, inject } from '@angular/core'\nimport { useHead as baseHead, useHeadSafe as baseHeadSafe, useSeoMeta as baseSeoMeta, useScript as baseUseScript } from 'unhead'\nimport { UnheadInjectionToken } from './context'\n\nexport function useUnhead() {\n const instance = inject<Unhead>(UnheadInjectionToken)\n if (!instance) {\n throw new Error('useHead() was called without proper injection context.')\n }\n return instance\n}\n\nfunction withSideEffects<T extends ActiveHeadEntry<any>>(input: any, options: any, fn: any): T {\n const head = options.head || useUnhead()\n const entry = fn(head, input, options)\n\n const destroyRef = inject(DestroyRef)\n destroyRef.onDestroy(() => {\n entry.dispose()\n })\n\n return entry\n}\n\nexport function useHead(input: UseHeadInput = {}, options: HeadEntryOptions = {}): ActiveHeadEntry<UseHeadInput> {\n return withSideEffects(input, options, baseHead)\n}\n\nexport function useHeadSafe(input: HeadSafe = {}, options: HeadEntryOptions = {}): ActiveHeadEntry<HeadSafe> {\n return withSideEffects<ActiveHeadEntry<HeadSafe>>(input, options, baseHeadSafe)\n}\n\nexport function useSeoMeta(input: UseSeoMetaInput = {}, options: HeadEntryOptions = {}): ActiveHeadEntry<UseSeoMetaInput> {\n return withSideEffects<ActiveHeadEntry<UseSeoMetaInput>>(input, options, baseSeoMeta)\n}\n\nexport function useScript<T extends Record<symbol | string, any> = Record<symbol | string, any>>(_input: UseScriptInput, _options?: UseScriptOptions<T>): UseScriptReturn<T> {\n const input = (typeof _input === 'string' ? { src: _input } : _input) as UseScriptInput\n const options = _options || {} as UseScriptOptions<T>\n const head = options?.head || useUnhead()\n options.head = head\n\n const mountCbs: (() => void)[] = []\n const sideEffects: (() => void)[] = []\n let isMounted = false\n\n const destroyRef = inject(DestroyRef)\n\n effect(() => {\n isMounted = true\n mountCbs.forEach(i => i())\n })\n\n if (typeof options.trigger === 'undefined') {\n options.trigger = (load) => {\n if (isMounted) {\n load()\n }\n else {\n mountCbs.push(load)\n }\n }\n }\n\n // @ts-expect-error untyped\n const script = baseUseScript(head, input as BaseUseScriptInput, options)\n\n const _registerCb = (key: 'loaded' | 'error', cb: any) => {\n let i: number | null\n const destroy = () => {\n // avoid removing the wrong callback\n if (i) {\n script._cbs[key]?.splice(i - 1, 1)\n i = null\n }\n }\n mountCbs.push(() => {\n if (!script._cbs[key]) {\n cb(script.instance)\n return () => {}\n }\n i = script._cbs[key].push(cb)\n sideEffects.push(destroy)\n return destroy\n })\n }\n\n destroyRef.onDestroy(() => {\n isMounted = false\n script._triggerAbortController?.abort()\n sideEffects.forEach(i => i())\n })\n script.onLoaded = (cb: (instance: T) => void | Promise<void>) => _registerCb('loaded', cb)\n script.onError = (cb: (err?: Error) => void | Promise<void>) => _registerCb('error', cb)\n return script\n}\n","import type { OnDestroy } from '@angular/core'\nimport { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'\nimport { useHead } from './composables'\n\ninterface NodeProps {\n type: string | symbol\n props?: Record<string, any>\n children?: NodeProps[]\n}\n\n@Component({\n selector: 'unhead-head',\n standalone: true,\n template: '<ng-content></ng-content>',\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n})\nexport class Head implements OnDestroy {\n private headEntry = useHead({})\n\n updateHead(nodes: NodeProps[]) {\n const transformed = this.transformNodes(nodes)\n this.headEntry.patch(transformed)\n }\n\n private transformNodes(nodes: NodeProps[]) {\n const result: Record<string, any> = {}\n\n const processNode = (node: NodeProps) => {\n if (typeof node.type === 'symbol') {\n node.children?.forEach(child => processNode(child as NodeProps))\n return\n }\n\n const type = node.type as string\n if (node.children?.length === 1) {\n result[type] = node.children[0]\n }\n else if (Object.keys(node.props || {}).length) {\n result[type] = result[type] || []\n result[type].push(node.props)\n }\n }\n\n nodes.forEach(processNode)\n return result\n }\n\n ngOnDestroy() {\n this.headEntry.dispose()\n }\n}\n","/*\n * Public API Surface of unhead\n */\n\nexport { useHead, useHeadSafe, useScript, useSeoMeta, useUnhead } from './composables'\nexport { headSymbol, UnheadInjectionToken } from './context'\nexport { Head } from './head.component'\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["baseHead","baseHeadSafe","baseSeoMeta","baseUseScript"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"unhead-angular.mjs","sources":["../../src/context.ts","../../src/composables.ts","../../src/head.component.ts","../../src/public-api.ts","../../src/unhead-angular.ts"],"sourcesContent":["import type { Unhead } from 'unhead/types'\r\nimport { InjectionToken } from '@angular/core'\r\n\r\nexport const headSymbol = 'usehead'\r\n\r\nexport const UnheadInjectionToken = new InjectionToken<Unhead>(headSymbol)\r\n","import type { UseScriptInput, UseScriptOptions, UseScriptReturn } from 'unhead/scripts'\r\nimport type { ActiveHeadEntry, HeadEntryOptions, HeadSafe, Unhead, UseHeadInput, UseSeoMetaInput } from 'unhead/types'\r\nimport { DestroyRef, effect, inject } from '@angular/core'\r\nimport { useHead as baseHead, useHeadSafe as baseHeadSafe, useSeoMeta as baseSeoMeta, useScript as baseUseScript } from 'unhead'\r\nimport { UnheadInjectionToken } from './context'\r\n\r\nexport function useUnhead() {\r\n const instance = inject<Unhead>(UnheadInjectionToken)\r\n if (!instance) {\r\n throw new Error('useHead() was called without proper injection context.')\r\n }\r\n return instance\r\n}\r\n\r\nfunction withSideEffects<T extends ActiveHeadEntry<any>>(input: any, options: any, fn: any): T {\r\n const head = options.head || useUnhead()\r\n const entry = fn(head, input, options)\r\n\r\n const destroyRef = inject(DestroyRef)\r\n destroyRef.onDestroy(() => {\r\n entry.dispose()\r\n })\r\n\r\n return entry\r\n}\r\n\r\nexport function useHead(input: UseHeadInput = {}, options: HeadEntryOptions = {}): ActiveHeadEntry<UseHeadInput> {\r\n return withSideEffects(input, options, baseHead)\r\n}\r\n\r\nexport function useHeadSafe(input: HeadSafe = {}, options: HeadEntryOptions = {}): ActiveHeadEntry<HeadSafe> {\r\n return withSideEffects<ActiveHeadEntry<HeadSafe>>(input, options, baseHeadSafe)\r\n}\r\n\r\nexport function useSeoMeta(input: UseSeoMetaInput = {}, options: HeadEntryOptions = {}): ActiveHeadEntry<UseSeoMetaInput> {\r\n return withSideEffects<ActiveHeadEntry<UseSeoMetaInput>>(input, options, baseSeoMeta)\r\n}\r\n\r\nexport function useScript<T extends Record<symbol | string, any> = Record<symbol | string, any>>(_input: UseScriptInput, _options?: UseScriptOptions<T>): UseScriptReturn<T> {\r\n const input = (typeof _input === 'string' ? { src: _input } : _input) as UseScriptInput\r\n const options = _options || {} as UseScriptOptions<T>\r\n const head = options?.head || useUnhead()\r\n options.head = head\r\n\r\n const mountCbs: (() => void)[] = []\r\n const sideEffects: (() => void)[] = []\r\n let isMounted = false\r\n\r\n const destroyRef = inject(DestroyRef)\r\n\r\n effect(() => {\r\n isMounted = true\r\n mountCbs.forEach(i => i())\r\n })\r\n\r\n if (typeof options.trigger === 'undefined') {\r\n options.trigger = (load) => {\r\n if (isMounted) {\r\n load()\r\n }\r\n else {\r\n mountCbs.push(load)\r\n }\r\n }\r\n }\r\n\r\n // @ts-expect-error untyped\r\n const script = baseUseScript(head, input as BaseUseScriptInput, options)\r\n\r\n const _registerCb = (key: 'loaded' | 'error', cb: any) => {\r\n let i: number | null\r\n const destroy = () => {\r\n // avoid removing the wrong callback\r\n if (i) {\r\n script._cbs[key]?.splice(i - 1, 1)\r\n i = null\r\n }\r\n }\r\n mountCbs.push(() => {\r\n if (!script._cbs[key]) {\r\n cb(script.instance)\r\n return () => {}\r\n }\r\n i = script._cbs[key].push(cb)\r\n sideEffects.push(destroy)\r\n return destroy\r\n })\r\n }\r\n\r\n destroyRef.onDestroy(() => {\r\n isMounted = false\r\n script._triggerAbortController?.abort()\r\n sideEffects.forEach(i => i())\r\n })\r\n script.onLoaded = (cb: (instance: T) => void | Promise<void>) => _registerCb('loaded', cb)\r\n script.onError = (cb: (err?: Error) => void | Promise<void>) => _registerCb('error', cb)\r\n return script\r\n}\r\n","import type { OnDestroy } from '@angular/core'\r\nimport { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'\r\nimport { useHead } from './composables'\r\n\r\ninterface NodeProps {\r\n type: string | symbol\r\n props?: Record<string, any>\r\n children?: NodeProps[]\r\n}\r\n\r\n@Component({\r\n selector: 'unhead-head',\r\n standalone: true,\r\n template: '<ng-content></ng-content>',\r\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\r\n})\r\nexport class Head implements OnDestroy {\r\n private headEntry = useHead({})\r\n\r\n updateHead(nodes: NodeProps[]) {\r\n const transformed = this.transformNodes(nodes)\r\n this.headEntry.patch(transformed)\r\n }\r\n\r\n private transformNodes(nodes: NodeProps[]) {\r\n const result: Record<string, any> = {}\r\n\r\n const processNode = (node: NodeProps) => {\r\n if (typeof node.type === 'symbol') {\r\n node.children?.forEach(child => processNode(child as NodeProps))\r\n return\r\n }\r\n\r\n const type = node.type as string\r\n if (node.children?.length === 1) {\r\n result[type] = node.children[0]\r\n }\r\n else if (Object.keys(node.props || {}).length) {\r\n result[type] = result[type] || []\r\n result[type].push(node.props)\r\n }\r\n }\r\n\r\n nodes.forEach(processNode)\r\n return result\r\n }\r\n\r\n ngOnDestroy() {\r\n this.headEntry.dispose()\r\n }\r\n}\r\n","/*\r\n * Public API Surface of unhead\r\n */\r\n\r\nexport { useHead, useHeadSafe, useScript, useSeoMeta, useUnhead } from './composables'\r\nexport { headSymbol, UnheadInjectionToken } from './context'\r\nexport { Head } from './head.component'\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["baseHead","baseHeadSafe","baseSeoMeta","baseUseScript"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unhead/angular",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.0.0-rc.
|
|
4
|
+
"version": "2.0.0-rc.9",
|
|
5
5
|
"description": "Full-stack <head> manager built for Angular.",
|
|
6
6
|
"author": "Harlan Wilton <harlan@harlanzw.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"tslib": "^2.8.1",
|
|
64
|
-
"unhead": "2.0.0-rc.
|
|
64
|
+
"unhead": "2.0.0-rc.9"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@angular/platform-browser-dynamic": "^19.2.0",
|
package/server.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './dist/server'
|
|
1
|
+
export * from './dist/server'
|