astro-helmet 0.0.1
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/.prettierrc.mjs +8 -0
- package/README.md +61 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +138 -0
- package/package.json +28 -0
- package/src/index.ts +172 -0
- package/tsconfig.json +15 -0
package/.prettierrc.mjs
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# astro-helmet
|
|
2
|
+
|
|
3
|
+
`astro-helmet` is a utility for managing the document head of Astro projects. It allows you to define any head tags you need and render them to a string that can be included in your Astro layout. Head tags defined in layouts, pages and components can be easily merged and prioritised to ensure the correct order in the final document.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install `astro-helmet` using npm:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install astro-helmet
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
To use `astro-helmet`, you need to import the `Helmet` component and use it in your Astro project. Here's an example:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { renderHead, type HeadItems } from 'astro-helmet'
|
|
19
|
+
|
|
20
|
+
// Define your head items
|
|
21
|
+
const headItems: HeadItems = {
|
|
22
|
+
title: 'Your Page Title',
|
|
23
|
+
meta: [
|
|
24
|
+
{ charset: 'UTF-8' },
|
|
25
|
+
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
|
26
|
+
{ property: 'og:title', content: 'Your Page Title' }
|
|
27
|
+
],
|
|
28
|
+
link: [{ rel: 'stylesheet', href: '/styles/main.css' }],
|
|
29
|
+
script: [{ src: '/scripts/main.js', defer: true }]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Call the render function to create the HTML string for the the head items
|
|
33
|
+
const head = renderHead([headItems])
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then add the rendered `head` string to your Astro layout:
|
|
37
|
+
|
|
38
|
+
```astro
|
|
39
|
+
<!doctype html>
|
|
40
|
+
<html lang="en">
|
|
41
|
+
<head>
|
|
42
|
+
<Fragment set:html={head} />
|
|
43
|
+
</head>
|
|
44
|
+
<body>
|
|
45
|
+
...
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
- **Dynamic Head Management**: Easily manage and update your document's head tags.
|
|
51
|
+
- **Priority Handling**: Control the order of head elements with priority settings.
|
|
52
|
+
- **Extensible**: Add custom tags and attributes as needed.
|
|
53
|
+
- **Defaults**: Default charset and viewport meta tags are included by default.
|
|
54
|
+
|
|
55
|
+
## Contributing
|
|
56
|
+
|
|
57
|
+
Contributions are welcome! Please open an issue or submit a pull request with your improvements.
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
This project is licensed under the ISC License.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type BaseItem = {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
priority?: number;
|
|
4
|
+
};
|
|
5
|
+
type ContentItem = BaseItem & {
|
|
6
|
+
innerHTML: string;
|
|
7
|
+
};
|
|
8
|
+
export type HeadItems = {
|
|
9
|
+
title?: string;
|
|
10
|
+
meta?: BaseItem[];
|
|
11
|
+
link?: BaseItem[];
|
|
12
|
+
style?: ContentItem[];
|
|
13
|
+
script?: ContentItem[];
|
|
14
|
+
noscript?: ContentItem[];
|
|
15
|
+
};
|
|
16
|
+
export declare function renderHead(headItems: HeadItems[]): string;
|
|
17
|
+
export declare function renderAttrs(item: BaseItem | ContentItem): string;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,KAAK,QAAQ,GAAG;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,KAAK,WAAW,GAAG,QAAQ,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAA;CACjB,CAAA;AAUD,MAAM,MAAM,SAAS,GAAG;IACvB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAA;IACjB,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAA;IACjB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAA;IACrB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAA;IACtB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAA;CACxB,CAAA;AAID,wBAAgB,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,GAAG,MAAM,CA2BzD;AAsGD,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,WAAW,GAAG,MAAM,CAShE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
const DEFAULT_CHARSET = { charset: 'UTF-8' };
|
|
2
|
+
const DEFAULT_VIEWPORT = { content: 'width=device-width, initial-scale=1' };
|
|
3
|
+
export function renderHead(headItems) {
|
|
4
|
+
const items = mergeHeadItems(headItems);
|
|
5
|
+
if (!items.title?.length)
|
|
6
|
+
throw new Error('Missing title tag.');
|
|
7
|
+
const tags = [];
|
|
8
|
+
const tagNames = ['meta', 'link', 'style', 'script', 'noscript'];
|
|
9
|
+
tagNames.forEach((tag) => {
|
|
10
|
+
tags.push(...items[tag].map((item) => ({ ...item, tagName: tag })));
|
|
11
|
+
});
|
|
12
|
+
let prioritisedTags = applyDefaultPriorities(tags);
|
|
13
|
+
prioritisedTags = applyDefaultTags(prioritisedTags);
|
|
14
|
+
const orderedTags = prioritisedTags.sort((a, b) => a.priority - b.priority);
|
|
15
|
+
const preTitleTags = orderedTags
|
|
16
|
+
.filter((i) => i.priority < 0)
|
|
17
|
+
.map((item) => renderHeadTag(item));
|
|
18
|
+
const postTitleTags = orderedTags
|
|
19
|
+
.filter((i) => i.priority > 0)
|
|
20
|
+
.map((item) => renderHeadTag(item));
|
|
21
|
+
return [
|
|
22
|
+
...preTitleTags,
|
|
23
|
+
`<title>${items.title}</title>`,
|
|
24
|
+
...postTitleTags
|
|
25
|
+
].join('\n');
|
|
26
|
+
}
|
|
27
|
+
function mergeHeadItems(items) {
|
|
28
|
+
const mergedHeadItems = {
|
|
29
|
+
title: '',
|
|
30
|
+
meta: [],
|
|
31
|
+
link: [],
|
|
32
|
+
style: [],
|
|
33
|
+
script: [],
|
|
34
|
+
noscript: []
|
|
35
|
+
};
|
|
36
|
+
items.forEach((item) => {
|
|
37
|
+
if (item.title && item.title.length)
|
|
38
|
+
mergedHeadItems.title = item.title;
|
|
39
|
+
if (item.meta)
|
|
40
|
+
mergedHeadItems.meta.push(...item.meta);
|
|
41
|
+
if (item.link)
|
|
42
|
+
mergedHeadItems.link.push(...item.link);
|
|
43
|
+
if (item.style)
|
|
44
|
+
mergedHeadItems.style.push(...item.style);
|
|
45
|
+
if (item.script)
|
|
46
|
+
mergedHeadItems.script.push(...item.script);
|
|
47
|
+
if (item.noscript)
|
|
48
|
+
mergedHeadItems.noscript.push(...item.noscript);
|
|
49
|
+
});
|
|
50
|
+
mergedHeadItems.meta = deduplicateMetaItems(mergedHeadItems.meta);
|
|
51
|
+
return mergedHeadItems;
|
|
52
|
+
}
|
|
53
|
+
function applyDefaultPriorities(tags) {
|
|
54
|
+
const prioritisedTags = [];
|
|
55
|
+
const unprioritisedTags = [];
|
|
56
|
+
tags.forEach((tag) => {
|
|
57
|
+
if (tag.priority !== undefined)
|
|
58
|
+
prioritisedTags.push(tag);
|
|
59
|
+
else
|
|
60
|
+
unprioritisedTags.push(tag);
|
|
61
|
+
});
|
|
62
|
+
unprioritisedTags.forEach((tag) => {
|
|
63
|
+
let priority;
|
|
64
|
+
switch (tag.tagName) {
|
|
65
|
+
case 'meta':
|
|
66
|
+
if (tag.charset)
|
|
67
|
+
priority = -3;
|
|
68
|
+
else if (tag.name === 'viewport')
|
|
69
|
+
priority = -2;
|
|
70
|
+
else if (tag['http-equiv'])
|
|
71
|
+
priority = -1;
|
|
72
|
+
else
|
|
73
|
+
priority = 100;
|
|
74
|
+
break;
|
|
75
|
+
case 'link':
|
|
76
|
+
if (tag.rel === 'preconnect')
|
|
77
|
+
priority = 10;
|
|
78
|
+
else if (tag.rel === 'preload')
|
|
79
|
+
priority = 60;
|
|
80
|
+
else if (tag.rel === 'prefetch')
|
|
81
|
+
priority = 80;
|
|
82
|
+
else if (tag.rel === 'stylesheet')
|
|
83
|
+
priority = 50;
|
|
84
|
+
else
|
|
85
|
+
priority = 90;
|
|
86
|
+
break;
|
|
87
|
+
case 'style':
|
|
88
|
+
priority = tag.innerHTML.includes('@import') ? 30 : 51;
|
|
89
|
+
break;
|
|
90
|
+
case 'script':
|
|
91
|
+
if (tag.async)
|
|
92
|
+
priority = 20;
|
|
93
|
+
else if (tag.defer)
|
|
94
|
+
priority = 70;
|
|
95
|
+
else
|
|
96
|
+
priority = 40;
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
priority = 110;
|
|
100
|
+
}
|
|
101
|
+
prioritisedTags.push({ ...tag, priority });
|
|
102
|
+
});
|
|
103
|
+
return prioritisedTags;
|
|
104
|
+
}
|
|
105
|
+
function applyDefaultTags(tags) {
|
|
106
|
+
if (!tags.some((tag) => tag.tagName === 'meta' && tag.charset))
|
|
107
|
+
tags.push({ ...DEFAULT_CHARSET, tagName: 'meta', priority: -3 });
|
|
108
|
+
if (!tags.some((tag) => tag.tagName === 'meta' && tag.name === 'viewport'))
|
|
109
|
+
tags.push({ ...DEFAULT_VIEWPORT, tagName: 'meta', priority: -2 });
|
|
110
|
+
return tags;
|
|
111
|
+
}
|
|
112
|
+
function deduplicateMetaItems(metaItems) {
|
|
113
|
+
const metaMap = new Map();
|
|
114
|
+
metaItems.forEach((meta) => {
|
|
115
|
+
const key = meta.property || meta.name || meta['http-equiv'];
|
|
116
|
+
if (key)
|
|
117
|
+
metaMap.set(key, meta);
|
|
118
|
+
});
|
|
119
|
+
return Array.from(metaMap.values());
|
|
120
|
+
}
|
|
121
|
+
function renderHeadTag(item) {
|
|
122
|
+
const attrs = renderAttrs(item);
|
|
123
|
+
return ['meta', 'link'].includes(item.tagName)
|
|
124
|
+
? `<${item.tagName} ${attrs} />`
|
|
125
|
+
: `<${item.tagName}${attrs && ' '}${attrs}>${item.innerHTML}</${item.tagName}>`;
|
|
126
|
+
}
|
|
127
|
+
export function renderAttrs(item) {
|
|
128
|
+
return Object.entries(item)
|
|
129
|
+
.filter(([key]) => !['innerHTML', 'priority', 'tagName'].includes(key))
|
|
130
|
+
.map(([key, value]) => {
|
|
131
|
+
if (typeof value === 'boolean')
|
|
132
|
+
return value ? key : '';
|
|
133
|
+
else
|
|
134
|
+
return `${key}="${value}"`;
|
|
135
|
+
})
|
|
136
|
+
.filter((attr) => attr !== '')
|
|
137
|
+
.join(' ');
|
|
138
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "astro-helmet",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"description": "A document head manager for astro.",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"test": "vitest"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"astro",
|
|
14
|
+
"head",
|
|
15
|
+
"seo",
|
|
16
|
+
"meta-tags",
|
|
17
|
+
"html-head",
|
|
18
|
+
"helmet",
|
|
19
|
+
"document-head",
|
|
20
|
+
"web-development"
|
|
21
|
+
],
|
|
22
|
+
"author": "Ryan Voitiskis",
|
|
23
|
+
"license": "ISC",
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"prettier": "^3.3.0",
|
|
26
|
+
"typescript": "^5.4.5"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
const DEFAULT_CHARSET = { charset: 'UTF-8' }
|
|
2
|
+
const DEFAULT_VIEWPORT = { content: 'width=device-width, initial-scale=1' }
|
|
3
|
+
|
|
4
|
+
type TagName = 'meta' | 'link' | 'style' | 'script' | 'noscript'
|
|
5
|
+
|
|
6
|
+
type BaseItem = {
|
|
7
|
+
[key: string]: any
|
|
8
|
+
priority?: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type ContentItem = BaseItem & {
|
|
12
|
+
innerHTML: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type Tag = (BaseItem | ContentItem) & {
|
|
16
|
+
tagName: TagName
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type PrioritisedTag = Tag & {
|
|
20
|
+
priority: number
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type HeadItems = {
|
|
24
|
+
title?: string
|
|
25
|
+
meta?: BaseItem[]
|
|
26
|
+
link?: BaseItem[]
|
|
27
|
+
style?: ContentItem[]
|
|
28
|
+
script?: ContentItem[]
|
|
29
|
+
noscript?: ContentItem[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type MergedHeadItems = Required<HeadItems>
|
|
33
|
+
|
|
34
|
+
export function renderHead(headItems: HeadItems[]): string {
|
|
35
|
+
const items = mergeHeadItems(headItems)
|
|
36
|
+
if (!items.title?.length) throw new Error('Missing title tag.')
|
|
37
|
+
|
|
38
|
+
const tags: Tag[] = []
|
|
39
|
+
const tagNames: TagName[] = ['meta', 'link', 'style', 'script', 'noscript']
|
|
40
|
+
tagNames.forEach((tag) => {
|
|
41
|
+
tags.push(...items[tag].map((item) => ({ ...item, tagName: tag })))
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
let prioritisedTags = applyDefaultPriorities(tags)
|
|
45
|
+
prioritisedTags = applyDefaultTags(prioritisedTags)
|
|
46
|
+
|
|
47
|
+
const orderedTags = prioritisedTags.sort((a, b) => a.priority - b.priority)
|
|
48
|
+
|
|
49
|
+
const preTitleTags = orderedTags
|
|
50
|
+
.filter((i) => i.priority < 0)
|
|
51
|
+
.map((item) => renderHeadTag(item))
|
|
52
|
+
const postTitleTags = orderedTags
|
|
53
|
+
.filter((i) => i.priority > 0)
|
|
54
|
+
.map((item) => renderHeadTag(item))
|
|
55
|
+
|
|
56
|
+
return [
|
|
57
|
+
...preTitleTags,
|
|
58
|
+
`<title>${items.title}</title>`,
|
|
59
|
+
...postTitleTags
|
|
60
|
+
].join('\n')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function mergeHeadItems(items: HeadItems[]): MergedHeadItems {
|
|
64
|
+
const mergedHeadItems: MergedHeadItems = {
|
|
65
|
+
title: '',
|
|
66
|
+
meta: [],
|
|
67
|
+
link: [],
|
|
68
|
+
style: [],
|
|
69
|
+
script: [],
|
|
70
|
+
noscript: []
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
items.forEach((item) => {
|
|
74
|
+
if (item.title && item.title.length) mergedHeadItems.title = item.title
|
|
75
|
+
if (item.meta) mergedHeadItems.meta.push(...item.meta)
|
|
76
|
+
if (item.link) mergedHeadItems.link.push(...item.link)
|
|
77
|
+
if (item.style) mergedHeadItems.style.push(...item.style)
|
|
78
|
+
if (item.script) mergedHeadItems.script.push(...item.script)
|
|
79
|
+
if (item.noscript) mergedHeadItems.noscript.push(...item.noscript)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
mergedHeadItems.meta = deduplicateMetaItems(mergedHeadItems.meta)
|
|
83
|
+
|
|
84
|
+
return mergedHeadItems
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function applyDefaultPriorities(tags: Tag[]): PrioritisedTag[] {
|
|
88
|
+
const prioritisedTags: PrioritisedTag[] = []
|
|
89
|
+
const unprioritisedTags: Tag[] = []
|
|
90
|
+
|
|
91
|
+
tags.forEach((tag) => {
|
|
92
|
+
if (tag.priority !== undefined) prioritisedTags.push(tag as PrioritisedTag)
|
|
93
|
+
else unprioritisedTags.push(tag)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
unprioritisedTags.forEach((tag) => {
|
|
97
|
+
let priority: number
|
|
98
|
+
switch (tag.tagName) {
|
|
99
|
+
case 'meta':
|
|
100
|
+
if (tag.charset) priority = -3
|
|
101
|
+
else if (tag.name === 'viewport') priority = -2
|
|
102
|
+
else if (tag['http-equiv']) priority = -1
|
|
103
|
+
else priority = 100
|
|
104
|
+
break
|
|
105
|
+
|
|
106
|
+
case 'link':
|
|
107
|
+
if (tag.rel === 'preconnect') priority = 10
|
|
108
|
+
else if (tag.rel === 'preload') priority = 60
|
|
109
|
+
else if (tag.rel === 'prefetch') priority = 80
|
|
110
|
+
else if (tag.rel === 'stylesheet') priority = 50
|
|
111
|
+
else priority = 90
|
|
112
|
+
break
|
|
113
|
+
|
|
114
|
+
case 'style':
|
|
115
|
+
priority = tag.innerHTML.includes('@import') ? 30 : 51
|
|
116
|
+
break
|
|
117
|
+
|
|
118
|
+
case 'script':
|
|
119
|
+
if (tag.async) priority = 20
|
|
120
|
+
else if (tag.defer) priority = 70
|
|
121
|
+
else priority = 40
|
|
122
|
+
break
|
|
123
|
+
|
|
124
|
+
default:
|
|
125
|
+
priority = 110
|
|
126
|
+
}
|
|
127
|
+
prioritisedTags.push({ ...tag, priority })
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
return prioritisedTags
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function applyDefaultTags(tags: PrioritisedTag[]): PrioritisedTag[] {
|
|
134
|
+
if (!tags.some((tag) => tag.tagName === 'meta' && tag.charset))
|
|
135
|
+
tags.push({ ...DEFAULT_CHARSET, tagName: 'meta', priority: -3 })
|
|
136
|
+
|
|
137
|
+
if (!tags.some((tag) => tag.tagName === 'meta' && tag.name === 'viewport'))
|
|
138
|
+
tags.push({ ...DEFAULT_VIEWPORT, tagName: 'meta', priority: -2 })
|
|
139
|
+
|
|
140
|
+
return tags
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function deduplicateMetaItems(metaItems: BaseItem[]): BaseItem[] {
|
|
144
|
+
const metaMap = new Map<string, BaseItem>()
|
|
145
|
+
|
|
146
|
+
metaItems.forEach((meta) => {
|
|
147
|
+
const key = meta.property || meta.name || meta['http-equiv']
|
|
148
|
+
if (key) metaMap.set(key, meta)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
return Array.from(metaMap.values())
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function renderHeadTag(item: BaseItem | ContentItem): string {
|
|
155
|
+
const attrs = renderAttrs(item)
|
|
156
|
+
return ['meta', 'link'].includes(item.tagName)
|
|
157
|
+
? `<${item.tagName} ${attrs} />`
|
|
158
|
+
: `<${item.tagName}${attrs && ' '}${attrs}>${item.innerHTML}</${
|
|
159
|
+
item.tagName
|
|
160
|
+
}>`
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function renderAttrs(item: BaseItem | ContentItem): string {
|
|
164
|
+
return Object.entries(item)
|
|
165
|
+
.filter(([key]) => !['innerHTML', 'priority', 'tagName'].includes(key))
|
|
166
|
+
.map(([key, value]) => {
|
|
167
|
+
if (typeof value === 'boolean') return value ? key : ''
|
|
168
|
+
else return `${key}="${value}"`
|
|
169
|
+
})
|
|
170
|
+
.filter((attr) => attr !== '')
|
|
171
|
+
.join(' ')
|
|
172
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"outDir": "./dist",
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"forceConsistentCasingInFileNames": true,
|
|
8
|
+
"strict": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"declaration": true,
|
|
11
|
+
"emitDeclarationOnly": false,
|
|
12
|
+
"declarationMap": true
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*"]
|
|
15
|
+
}
|