astro 4.4.14 → 4.5.0
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/components/Code.astro +15 -12
- package/dist/@types/astro.d.ts +95 -18
- package/dist/assets/utils/getAssetsPrefix.d.ts +2 -0
- package/dist/assets/utils/getAssetsPrefix.js +14 -0
- package/dist/assets/vite-plugin-assets.js +10 -3
- package/dist/cli/add/index.js +76 -28
- package/dist/cli/install-package.js +2 -2
- package/dist/content/types-generator.js +56 -7
- package/dist/content/vite-plugin-content-assets.js +11 -3
- package/dist/core/app/common.js +2 -0
- package/dist/core/app/index.js +10 -2
- package/dist/core/app/types.d.ts +7 -2
- package/dist/core/base-pipeline.d.ts +2 -1
- package/dist/core/base-pipeline.js +2 -1
- package/dist/core/build/generate.js +1 -0
- package/dist/core/build/internal.d.ts +6 -0
- package/dist/core/build/internal.js +1 -0
- package/dist/core/build/plugins/index.js +6 -1
- package/dist/core/build/plugins/plugin-analyzer.js +10 -98
- package/dist/core/build/plugins/plugin-css.js +27 -1
- package/dist/core/build/plugins/plugin-manifest.js +5 -2
- package/dist/core/build/plugins/plugin-scripts.d.ts +8 -0
- package/dist/core/build/plugins/plugin-scripts.js +34 -0
- package/dist/core/compile/compile.d.ts +1 -7
- package/dist/core/compile/compile.js +5 -4
- package/dist/core/compile/style.d.ts +4 -3
- package/dist/core/compile/style.js +5 -4
- package/dist/core/compile/types.d.ts +11 -0
- package/dist/core/config/schema.d.ts +177 -113
- package/dist/core/config/schema.js +42 -9
- package/dist/core/config/vite-load.js +1 -0
- package/dist/core/constants.d.ts +1 -0
- package/dist/core/constants.js +3 -1
- package/dist/core/create-vite.js +5 -3
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/errors/dev/vite.js +1 -1
- package/dist/core/messages.js +2 -2
- package/dist/core/render/params-and-props.js +2 -1
- package/dist/core/render/ssr-element.d.ts +8 -8
- package/dist/core/render/ssr-element.js +4 -2
- package/dist/core/render-context.js +3 -1
- package/dist/core/routing/astro-designed-error-pages.d.ts +2 -0
- package/dist/core/routing/astro-designed-error-pages.js +21 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/index.d.ts +8 -15
- package/dist/runtime/client/dev-toolbar/apps/audit/index.js +130 -249
- package/dist/runtime/client/dev-toolbar/apps/audit/{a11y.js → rules/a11y.js} +4 -2
- package/dist/runtime/client/dev-toolbar/apps/audit/rules/index.d.ts +35 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/rules/index.js +40 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/{perf.js → rules/perf.js} +2 -2
- package/dist/runtime/client/dev-toolbar/apps/audit/ui/audit-list-item.d.ts +7 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/ui/audit-list-item.js +137 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/ui/audit-list-window.d.ts +23 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/ui/audit-list-window.js +384 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/ui/audit-ui.d.ts +6 -0
- package/dist/runtime/client/dev-toolbar/apps/audit/ui/audit-ui.js +126 -0
- package/dist/runtime/client/dev-toolbar/apps/utils/window.d.ts +1 -1
- package/dist/runtime/client/dev-toolbar/apps/utils/window.js +3 -1
- package/dist/runtime/client/dev-toolbar/entrypoint.js +43 -15
- package/dist/runtime/client/dev-toolbar/settings.d.ts +3 -1
- package/dist/runtime/client/dev-toolbar/settings.js +8 -2
- package/dist/runtime/client/dev-toolbar/toolbar.d.ts +1 -0
- package/dist/runtime/client/dev-toolbar/toolbar.js +10 -8
- package/dist/runtime/client/dev-toolbar/ui-library/badge.d.ts +14 -4
- package/dist/runtime/client/dev-toolbar/ui-library/badge.js +72 -33
- package/dist/runtime/client/dev-toolbar/ui-library/button.d.ts +14 -4
- package/dist/runtime/client/dev-toolbar/ui-library/button.js +100 -47
- package/dist/runtime/client/dev-toolbar/ui-library/card.d.ts +9 -0
- package/dist/runtime/client/dev-toolbar/ui-library/card.js +57 -2
- package/dist/runtime/client/dev-toolbar/ui-library/highlight.d.ts +9 -0
- package/dist/runtime/client/dev-toolbar/ui-library/highlight.js +54 -2
- package/dist/runtime/client/dev-toolbar/ui-library/icons.d.ts +4 -0
- package/dist/runtime/client/dev-toolbar/ui-library/icons.js +5 -1
- package/dist/runtime/client/dev-toolbar/ui-library/toggle.d.ts +9 -0
- package/dist/runtime/client/dev-toolbar/ui-library/toggle.js +64 -5
- package/dist/runtime/compiler/index.d.ts +1 -1
- package/dist/runtime/compiler/index.js +2 -0
- package/dist/runtime/server/hydration.js +3 -2
- package/dist/runtime/server/index.d.ts +1 -1
- package/dist/runtime/server/index.js +2 -0
- package/dist/runtime/server/render/astro/factory.d.ts +1 -1
- package/dist/runtime/server/render/component.js +4 -5
- package/dist/runtime/server/render/index.d.ts +1 -0
- package/dist/runtime/server/render/index.js +2 -0
- package/dist/runtime/server/render/script.d.ts +6 -0
- package/dist/runtime/server/render/script.js +15 -0
- package/dist/transitions/router.js +12 -3
- package/dist/vite-plugin-astro/index.d.ts +2 -2
- package/dist/vite-plugin-astro/index.js +12 -1
- package/dist/vite-plugin-astro/types.d.ts +21 -1
- package/dist/vite-plugin-astro-server/pipeline.js +6 -2
- package/dist/vite-plugin-astro-server/plugin.js +6 -2
- package/dist/vite-plugin-astro-server/response.d.ts +6 -0
- package/dist/vite-plugin-astro-server/response.js +13 -0
- package/dist/vite-plugin-astro-server/route.js +18 -2
- package/package.json +8 -9
- package/tsconfigs/base.json +3 -1
- /package/dist/runtime/client/dev-toolbar/apps/audit/{a11y.d.ts → rules/a11y.d.ts} +0 -0
- /package/dist/runtime/client/dev-toolbar/apps/audit/{perf.d.ts → rules/perf.d.ts} +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Icon } from '../../../ui-library/icons.js';
|
|
2
|
+
import type { Audit } from '../index.js';
|
|
3
|
+
export declare function createRoundedBadge(icon: Icon): {
|
|
4
|
+
badge: import("../../../ui-library/badge.js").DevToolbarBadge;
|
|
5
|
+
updateCount: (count: number) => void;
|
|
6
|
+
};
|
|
7
|
+
export declare class DevToolbarAuditListWindow extends HTMLElement {
|
|
8
|
+
_audits: Audit[];
|
|
9
|
+
shadowRoot: ShadowRoot;
|
|
10
|
+
badges: {
|
|
11
|
+
[key: string]: {
|
|
12
|
+
badge: HTMLElement;
|
|
13
|
+
updateCount: (count: number) => void;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
get audits(): Audit[];
|
|
17
|
+
set audits(value: Audit[]);
|
|
18
|
+
constructor();
|
|
19
|
+
connectedCallback(): void;
|
|
20
|
+
updateAuditList(): void;
|
|
21
|
+
updateBadgeCounts(): void;
|
|
22
|
+
render(): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { getAuditCategory, rulesCategories } from "../rules/index.js";
|
|
2
|
+
function createRoundedBadge(icon) {
|
|
3
|
+
const badge = document.createElement("astro-dev-toolbar-badge");
|
|
4
|
+
badge.shadowRoot.innerHTML += `
|
|
5
|
+
<style>
|
|
6
|
+
:host>div {
|
|
7
|
+
padding: 12px 8px;
|
|
8
|
+
font-size: 14px;
|
|
9
|
+
display: flex;
|
|
10
|
+
gap: 4px;
|
|
11
|
+
}
|
|
12
|
+
</style>
|
|
13
|
+
`;
|
|
14
|
+
badge.innerHTML = `<astro-dev-toolbar-icon icon="${icon}"></astro-dev-toolbar-icon>0`;
|
|
15
|
+
return {
|
|
16
|
+
badge,
|
|
17
|
+
updateCount: (count) => {
|
|
18
|
+
if (count === 0) {
|
|
19
|
+
badge.badgeStyle = "green";
|
|
20
|
+
} else {
|
|
21
|
+
badge.badgeStyle = "purple";
|
|
22
|
+
}
|
|
23
|
+
badge.innerHTML = `<astro-dev-toolbar-icon icon="${icon}"></astro-dev-toolbar-icon>${count}`;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
class DevToolbarAuditListWindow extends HTMLElement {
|
|
28
|
+
_audits = [];
|
|
29
|
+
shadowRoot;
|
|
30
|
+
badges = {};
|
|
31
|
+
get audits() {
|
|
32
|
+
return this._audits;
|
|
33
|
+
}
|
|
34
|
+
set audits(value) {
|
|
35
|
+
this._audits = value;
|
|
36
|
+
this.render();
|
|
37
|
+
}
|
|
38
|
+
constructor() {
|
|
39
|
+
super();
|
|
40
|
+
this.shadowRoot = this.attachShadow({ mode: "open" });
|
|
41
|
+
this.shadowRoot.innerHTML = `<style>
|
|
42
|
+
:host {
|
|
43
|
+
box-sizing: border-box;
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
background: linear-gradient(0deg, #13151a, #13151a), linear-gradient(0deg, #343841, #343841);
|
|
47
|
+
border: 1px solid rgba(52, 56, 65, 1);
|
|
48
|
+
width: min(640px, 100%);
|
|
49
|
+
max-height: 480px;
|
|
50
|
+
border-radius: 12px;
|
|
51
|
+
padding: 24px;
|
|
52
|
+
font-family:
|
|
53
|
+
ui-sans-serif,
|
|
54
|
+
system-ui,
|
|
55
|
+
-apple-system,
|
|
56
|
+
BlinkMacSystemFont,
|
|
57
|
+
"Segoe UI",
|
|
58
|
+
Roboto,
|
|
59
|
+
"Helvetica Neue",
|
|
60
|
+
Arial,
|
|
61
|
+
"Noto Sans",
|
|
62
|
+
sans-serif,
|
|
63
|
+
"Apple Color Emoji",
|
|
64
|
+
"Segoe UI Emoji",
|
|
65
|
+
"Segoe UI Symbol",
|
|
66
|
+
"Noto Color Emoji";
|
|
67
|
+
color: rgba(191, 193, 201, 1);
|
|
68
|
+
position: fixed;
|
|
69
|
+
z-index: 999999999;
|
|
70
|
+
bottom: 72px;
|
|
71
|
+
left: 50%;
|
|
72
|
+
transform: translateX(-50%);
|
|
73
|
+
box-shadow:
|
|
74
|
+
0px 0px 0px 0px rgba(19, 21, 26, 0.3),
|
|
75
|
+
0px 1px 2px 0px rgba(19, 21, 26, 0.29),
|
|
76
|
+
0px 4px 4px 0px rgba(19, 21, 26, 0.26),
|
|
77
|
+
0px 10px 6px 0px rgba(19, 21, 26, 0.15),
|
|
78
|
+
0px 17px 7px 0px rgba(19, 21, 26, 0.04),
|
|
79
|
+
0px 26px 7px 0px rgba(19, 21, 26, 0.01);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@media (forced-colors: active) {
|
|
83
|
+
:host {
|
|
84
|
+
background: white;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@media (max-width: 640px) {
|
|
89
|
+
:host {
|
|
90
|
+
border-radius: 0;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
hr,
|
|
95
|
+
::slotted(hr) {
|
|
96
|
+
border: 1px solid rgba(27, 30, 36, 1);
|
|
97
|
+
margin: 1em 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.reset-button {
|
|
101
|
+
text-align: left;
|
|
102
|
+
border: none;
|
|
103
|
+
margin: 0;
|
|
104
|
+
width: auto;
|
|
105
|
+
overflow: visible;
|
|
106
|
+
background: transparent;
|
|
107
|
+
font: inherit;
|
|
108
|
+
line-height: normal;
|
|
109
|
+
-webkit-font-smoothing: inherit;
|
|
110
|
+
-moz-osx-font-smoothing: inherit;
|
|
111
|
+
-webkit-appearance: none;
|
|
112
|
+
padding: 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
:host {
|
|
116
|
+
left: initial;
|
|
117
|
+
top: 8px;
|
|
118
|
+
right: 8px;
|
|
119
|
+
transform: none;
|
|
120
|
+
width: 350px;
|
|
121
|
+
min-height: 350px;
|
|
122
|
+
max-height: 420px;
|
|
123
|
+
padding: 0;
|
|
124
|
+
overflow: hidden;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
hr {
|
|
128
|
+
margin: 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
header {
|
|
132
|
+
display: flex;
|
|
133
|
+
align-items: center;
|
|
134
|
+
gap: 4px;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
header > section {
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
gap: 1em;
|
|
141
|
+
padding: 18px;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
header.category-header {
|
|
145
|
+
background: rgba(27, 30, 36, 1);
|
|
146
|
+
padding: 10px 16px;
|
|
147
|
+
position: sticky;
|
|
148
|
+
top: 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
header.category-header astro-dev-toolbar-icon {
|
|
152
|
+
opacity: 0.6;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
#audit-counts {
|
|
156
|
+
display: flex;
|
|
157
|
+
gap: 0.5em;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
#audit-counts > div {
|
|
161
|
+
display: flex;
|
|
162
|
+
gap: 8px;
|
|
163
|
+
align-items: center;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
ul,
|
|
167
|
+
li {
|
|
168
|
+
margin: 0;
|
|
169
|
+
padding: 0;
|
|
170
|
+
list-style: none;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
h1 {
|
|
174
|
+
font-size: 24px;
|
|
175
|
+
font-weight: 600;
|
|
176
|
+
color: #fff;
|
|
177
|
+
margin: 0;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
h2 {
|
|
181
|
+
font-weight: 600;
|
|
182
|
+
margin: 0;
|
|
183
|
+
color: white;
|
|
184
|
+
font-size: 14px;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
h3 {
|
|
188
|
+
font-weight: normal;
|
|
189
|
+
margin: 0;
|
|
190
|
+
color: white;
|
|
191
|
+
font-size: 14px;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.audit-header {
|
|
195
|
+
display: flex;
|
|
196
|
+
gap: 8px;
|
|
197
|
+
align-items: center;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.audit-selector {
|
|
201
|
+
color: white;
|
|
202
|
+
font-size: 12px;
|
|
203
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
204
|
+
"Liberation Mono", "Courier New", monospace;
|
|
205
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
206
|
+
border-radius: 4px;
|
|
207
|
+
padding: 4px 6px;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
[active] .audit-selector:hover {
|
|
211
|
+
text-decoration: underline;
|
|
212
|
+
cursor: pointer;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.selector-title-container {
|
|
216
|
+
display: flex;
|
|
217
|
+
align-items: center;
|
|
218
|
+
gap: 8px;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
astro-dev-toolbar-icon {
|
|
222
|
+
color: white;
|
|
223
|
+
fill: white;
|
|
224
|
+
display: inline-block;
|
|
225
|
+
height: 16px;
|
|
226
|
+
width: 16px;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
#audit-list {
|
|
230
|
+
display: flex;
|
|
231
|
+
flex-direction: column;
|
|
232
|
+
overflow: auto;
|
|
233
|
+
overscroll-behavior: contain;
|
|
234
|
+
height: 100%;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
#back-to-list {
|
|
238
|
+
display: none;
|
|
239
|
+
align-items: center;
|
|
240
|
+
justify-content: center;
|
|
241
|
+
background: rgba(27, 30, 36, 1);
|
|
242
|
+
gap: 8px;
|
|
243
|
+
padding: 8px;
|
|
244
|
+
color: white;
|
|
245
|
+
font-size: 14px;
|
|
246
|
+
padding-right: 24px;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
#back-to-list:hover {
|
|
250
|
+
cursor: pointer;
|
|
251
|
+
background: #313236;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
#back-to-list:has(+ #audit-list astro-dev-toolbar-audit-list-item[active]) {
|
|
255
|
+
display: flex;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.no-audit-container {
|
|
259
|
+
display: flex;
|
|
260
|
+
flex-direction: column;
|
|
261
|
+
padding: 24px;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.no-audit-container h1 {
|
|
265
|
+
font-size: 20px;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.no-audit-container astro-dev-toolbar-icon {
|
|
269
|
+
width: auto;
|
|
270
|
+
height: auto;
|
|
271
|
+
margin: 0 auto;
|
|
272
|
+
}
|
|
273
|
+
</style>
|
|
274
|
+
|
|
275
|
+
<template id="category-template">
|
|
276
|
+
<div>
|
|
277
|
+
<header class="category-header">
|
|
278
|
+
</header>
|
|
279
|
+
<div class="category-content"></div>
|
|
280
|
+
</div>
|
|
281
|
+
</template>
|
|
282
|
+
|
|
283
|
+
<header>
|
|
284
|
+
<section id="header-left">
|
|
285
|
+
<h1>Audit</h1>
|
|
286
|
+
<section id="audit-counts"></section>
|
|
287
|
+
</section>
|
|
288
|
+
</header>
|
|
289
|
+
<hr />
|
|
290
|
+
<button id="back-to-list" class="reset-button">
|
|
291
|
+
<astro-dev-toolbar-icon icon="arrow-left"></astro-dev-toolbar-icon>
|
|
292
|
+
Back to list
|
|
293
|
+
</button>
|
|
294
|
+
<div id="audit-list"></div>
|
|
295
|
+
`;
|
|
296
|
+
const auditCounts = this.shadowRoot.getElementById("audit-counts");
|
|
297
|
+
if (auditCounts) {
|
|
298
|
+
rulesCategories.forEach((category) => {
|
|
299
|
+
const headerEntryContainer = document.createElement("div");
|
|
300
|
+
const auditCount = this.audits.filter(
|
|
301
|
+
(audit) => getAuditCategory(audit.rule) === category.code
|
|
302
|
+
).length;
|
|
303
|
+
const categoryBadge = createRoundedBadge(category.icon);
|
|
304
|
+
categoryBadge.updateCount(auditCount);
|
|
305
|
+
headerEntryContainer.append(categoryBadge.badge);
|
|
306
|
+
auditCounts.append(headerEntryContainer);
|
|
307
|
+
this.badges[category.code] = categoryBadge;
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
const backToListButton = this.shadowRoot.getElementById("back-to-list");
|
|
311
|
+
if (backToListButton) {
|
|
312
|
+
backToListButton.addEventListener("click", () => {
|
|
313
|
+
const activeAudit = this.shadowRoot.querySelector(
|
|
314
|
+
"astro-dev-toolbar-audit-list-item[active]"
|
|
315
|
+
);
|
|
316
|
+
if (activeAudit) {
|
|
317
|
+
activeAudit.toggleAttribute("active", false);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
connectedCallback() {
|
|
323
|
+
this.render();
|
|
324
|
+
}
|
|
325
|
+
updateAuditList() {
|
|
326
|
+
const auditListContainer = this.shadowRoot.getElementById("audit-list");
|
|
327
|
+
if (auditListContainer) {
|
|
328
|
+
auditListContainer.innerHTML = "";
|
|
329
|
+
if (this.audits.length > 0) {
|
|
330
|
+
for (const category of rulesCategories) {
|
|
331
|
+
const template = this.shadowRoot.getElementById(
|
|
332
|
+
"category-template"
|
|
333
|
+
);
|
|
334
|
+
if (!template)
|
|
335
|
+
return;
|
|
336
|
+
const clone = document.importNode(template.content, true);
|
|
337
|
+
const categoryContainer = clone.querySelector("div");
|
|
338
|
+
const categoryHeader = clone.querySelector(".category-header");
|
|
339
|
+
categoryHeader.innerHTML = `<astro-dev-toolbar-icon icon="${category.icon}"></astro-dev-toolbar-icon><h2>${category.name}</h2>`;
|
|
340
|
+
categoryContainer.append(categoryHeader);
|
|
341
|
+
const categoryContent = clone.querySelector(".category-content");
|
|
342
|
+
const categoryAudits = this.audits.filter(
|
|
343
|
+
(audit) => getAuditCategory(audit.rule) === category.code
|
|
344
|
+
);
|
|
345
|
+
for (const audit of categoryAudits) {
|
|
346
|
+
if (audit.card)
|
|
347
|
+
categoryContent.append(audit.card);
|
|
348
|
+
}
|
|
349
|
+
categoryContainer.append(categoryContent);
|
|
350
|
+
auditListContainer.append(categoryContainer);
|
|
351
|
+
}
|
|
352
|
+
} else {
|
|
353
|
+
const noAuditContainer = document.createElement("div");
|
|
354
|
+
noAuditContainer.classList.add("no-audit-container");
|
|
355
|
+
noAuditContainer.innerHTML = `
|
|
356
|
+
<header>
|
|
357
|
+
<h1></astro-dev-toolbar-icon>No accessibility or performance issues detected.</h1>
|
|
358
|
+
</header>
|
|
359
|
+
<p>
|
|
360
|
+
Nice work! This app scans the page and highlights common accessibility and performance issues for you, like a missing "alt" attribute on an image, or a image not using performant attributes.
|
|
361
|
+
</p>
|
|
362
|
+
<astro-dev-toolbar-icon icon="houston-detective"></astro-dev-toolbar-icon>
|
|
363
|
+
`;
|
|
364
|
+
auditListContainer.append(noAuditContainer);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
updateBadgeCounts() {
|
|
369
|
+
for (const category of rulesCategories) {
|
|
370
|
+
const auditCount = this.audits.filter(
|
|
371
|
+
(audit) => getAuditCategory(audit.rule) === category.code
|
|
372
|
+
).length;
|
|
373
|
+
this.badges[category.code].updateCount(auditCount);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
render() {
|
|
377
|
+
this.updateAuditList();
|
|
378
|
+
this.updateBadgeCounts();
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
export {
|
|
382
|
+
DevToolbarAuditListWindow,
|
|
383
|
+
createRoundedBadge
|
|
384
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Audit } from '../index.js';
|
|
2
|
+
import type { DevToolbarAuditListItem } from './audit-list-item.js';
|
|
3
|
+
export declare function createAuditUI(audit: Audit, audits: Audit[]): {
|
|
4
|
+
highlight: import("../../../ui-library/highlight.js").DevToolbarHighlight;
|
|
5
|
+
card: DevToolbarAuditListItem;
|
|
6
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { escape as escapeHTML } from "html-escaper";
|
|
2
|
+
import {
|
|
3
|
+
attachTooltipToHighlight,
|
|
4
|
+
createHighlight,
|
|
5
|
+
getElementsPositionInDocument
|
|
6
|
+
} from "../../utils/highlight.js";
|
|
7
|
+
import { resolveAuditRule } from "../rules/index.js";
|
|
8
|
+
function truncate(val, maxLength) {
|
|
9
|
+
return val.length > maxLength ? val.slice(0, maxLength - 1) + "…" : val;
|
|
10
|
+
}
|
|
11
|
+
function createAuditUI(audit, audits) {
|
|
12
|
+
const rect = audit.auditedElement.getBoundingClientRect();
|
|
13
|
+
const highlight = createHighlight(rect, "warning", { "data-audit-code": audit.rule.code });
|
|
14
|
+
const resolvedAuditRule = resolveAuditRule(audit.rule, audit.auditedElement);
|
|
15
|
+
const tooltip = buildAuditTooltip(resolvedAuditRule, audit.auditedElement);
|
|
16
|
+
const card = buildAuditCard(resolvedAuditRule, highlight, audit.auditedElement, audits);
|
|
17
|
+
["focus", "mouseover"].forEach((event) => {
|
|
18
|
+
const attribute = event === "focus" ? "active" : "hovered";
|
|
19
|
+
highlight.addEventListener(event, () => {
|
|
20
|
+
if (event === "focus") {
|
|
21
|
+
audits.forEach((adt) => {
|
|
22
|
+
if (adt.card)
|
|
23
|
+
adt.card.toggleAttribute("active", false);
|
|
24
|
+
});
|
|
25
|
+
if (!card.isManualFocus)
|
|
26
|
+
card.scrollIntoView();
|
|
27
|
+
card.toggleAttribute("active", true);
|
|
28
|
+
} else {
|
|
29
|
+
card.toggleAttribute(attribute, true);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
highlight.addEventListener("mouseout", () => {
|
|
34
|
+
card.toggleAttribute("hovered", false);
|
|
35
|
+
});
|
|
36
|
+
const { isFixed } = getElementsPositionInDocument(audit.auditedElement);
|
|
37
|
+
if (isFixed) {
|
|
38
|
+
tooltip.style.position = highlight.style.position = "fixed";
|
|
39
|
+
}
|
|
40
|
+
attachTooltipToHighlight(highlight, tooltip, audit.auditedElement);
|
|
41
|
+
return { highlight, card };
|
|
42
|
+
}
|
|
43
|
+
function buildAuditTooltip(rule, element) {
|
|
44
|
+
const tooltip = document.createElement("astro-dev-toolbar-tooltip");
|
|
45
|
+
const { title, message } = rule;
|
|
46
|
+
tooltip.sections = [
|
|
47
|
+
{
|
|
48
|
+
icon: "warning",
|
|
49
|
+
title: escapeHTML(title)
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
content: escapeHTML(message)
|
|
53
|
+
}
|
|
54
|
+
];
|
|
55
|
+
const elementFile = element.getAttribute("data-astro-source-file");
|
|
56
|
+
const elementPosition = element.getAttribute("data-astro-source-loc");
|
|
57
|
+
if (elementFile) {
|
|
58
|
+
const elementFileWithPosition = elementFile + (elementPosition ? ":" + elementPosition : "");
|
|
59
|
+
tooltip.sections.push({
|
|
60
|
+
content: elementFileWithPosition.slice(
|
|
61
|
+
window.__astro_dev_toolbar__.root.length - 1
|
|
62
|
+
// We want to keep the final slash, so minus one.
|
|
63
|
+
),
|
|
64
|
+
clickDescription: "Click to go to file",
|
|
65
|
+
async clickAction() {
|
|
66
|
+
await fetch("/__open-in-editor?file=" + encodeURIComponent(elementFileWithPosition));
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return tooltip;
|
|
71
|
+
}
|
|
72
|
+
function buildAuditCard(rule, highlightElement, auditedElement, audits) {
|
|
73
|
+
const card = document.createElement(
|
|
74
|
+
"astro-dev-toolbar-audit-list-item"
|
|
75
|
+
);
|
|
76
|
+
card.clickAction = () => {
|
|
77
|
+
if (card.hasAttribute("active"))
|
|
78
|
+
return;
|
|
79
|
+
audits.forEach((audit) => {
|
|
80
|
+
audit.card?.toggleAttribute("active", false);
|
|
81
|
+
});
|
|
82
|
+
highlightElement.scrollIntoView();
|
|
83
|
+
card.isManualFocus = true;
|
|
84
|
+
highlightElement.focus();
|
|
85
|
+
card.isManualFocus = false;
|
|
86
|
+
};
|
|
87
|
+
const selectorTitleContainer = document.createElement("section");
|
|
88
|
+
selectorTitleContainer.classList.add("selector-title-container");
|
|
89
|
+
const selector = document.createElement("span");
|
|
90
|
+
const selectorName = truncate(auditedElement.tagName.toLowerCase(), 8);
|
|
91
|
+
selector.classList.add("audit-selector");
|
|
92
|
+
selector.innerHTML = escapeHTML(selectorName);
|
|
93
|
+
const title = document.createElement("h3");
|
|
94
|
+
title.classList.add("audit-title");
|
|
95
|
+
title.innerText = rule.title;
|
|
96
|
+
selectorTitleContainer.append(selector, title);
|
|
97
|
+
card.append(selectorTitleContainer);
|
|
98
|
+
const extendedInfo = document.createElement("div");
|
|
99
|
+
extendedInfo.classList.add("extended-info");
|
|
100
|
+
const selectorButton = document.createElement("button");
|
|
101
|
+
selectorButton.className = "audit-selector reset-button";
|
|
102
|
+
selectorButton.innerHTML = `${selectorName} <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M128,136v64a8,8,0,0,1-16,0V155.32L45.66,221.66a8,8,0,0,1-11.32-11.32L100.68,144H56a8,8,0,0,1,0-16h64A8,8,0,0,1,128,136ZM208,32H80A16,16,0,0,0,64,48V96a8,8,0,0,0,16,0V48H208V176H160a8,8,0,0,0,0,16h48a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Z"></path></svg>`;
|
|
103
|
+
selectorButton.addEventListener("click", () => {
|
|
104
|
+
highlightElement.scrollIntoView();
|
|
105
|
+
highlightElement.focus();
|
|
106
|
+
});
|
|
107
|
+
extendedInfo.append(title.cloneNode(true));
|
|
108
|
+
extendedInfo.append(selectorButton);
|
|
109
|
+
extendedInfo.append(document.createElement("hr"));
|
|
110
|
+
const message = document.createElement("p");
|
|
111
|
+
message.classList.add("audit-message");
|
|
112
|
+
message.innerHTML = rule.message;
|
|
113
|
+
extendedInfo.appendChild(message);
|
|
114
|
+
const description = rule.description;
|
|
115
|
+
if (description) {
|
|
116
|
+
const descriptionElement = document.createElement("p");
|
|
117
|
+
descriptionElement.classList.add("audit-description");
|
|
118
|
+
descriptionElement.innerHTML = description;
|
|
119
|
+
extendedInfo.appendChild(descriptionElement);
|
|
120
|
+
}
|
|
121
|
+
card.shadowRoot.appendChild(extendedInfo);
|
|
122
|
+
return card;
|
|
123
|
+
}
|
|
124
|
+
export {
|
|
125
|
+
createAuditUI
|
|
126
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare function createWindowElement(content: string): import("../../ui-library/window.js").DevToolbarWindow;
|
|
2
|
-
export declare function closeOnOutsideClick(eventTarget: EventTarget): void;
|
|
2
|
+
export declare function closeOnOutsideClick(eventTarget: EventTarget, additionalCheck?: (target: Element) => boolean): void;
|
|
@@ -3,7 +3,7 @@ function createWindowElement(content) {
|
|
|
3
3
|
windowElement.innerHTML = content;
|
|
4
4
|
return windowElement;
|
|
5
5
|
}
|
|
6
|
-
function closeOnOutsideClick(eventTarget) {
|
|
6
|
+
function closeOnOutsideClick(eventTarget, additionalCheck) {
|
|
7
7
|
function onPageClick(event) {
|
|
8
8
|
const target = event.target;
|
|
9
9
|
if (!target)
|
|
@@ -12,6 +12,8 @@ function closeOnOutsideClick(eventTarget) {
|
|
|
12
12
|
return;
|
|
13
13
|
if (target.closest("astro-dev-toolbar"))
|
|
14
14
|
return;
|
|
15
|
+
if (additionalCheck && additionalCheck(target))
|
|
16
|
+
return;
|
|
15
17
|
eventTarget.dispatchEvent(
|
|
16
18
|
new CustomEvent("toggle-app", {
|
|
17
19
|
detail: {
|
|
@@ -51,6 +51,12 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
51
51
|
customElements.define("astro-dev-overlay-badge", deprecated(DevToolbarBadge));
|
|
52
52
|
customElements.define("astro-dev-overlay-icon", deprecated(DevToolbarIcon));
|
|
53
53
|
overlay = document.createElement("astro-dev-toolbar");
|
|
54
|
+
const notificationLevels = ["error", "warning", "info"];
|
|
55
|
+
const notificationSVGs = {
|
|
56
|
+
error: '<svg viewBox="0 0 10 10"><rect width="9" height="9" x=".5" y=".5" fill="#B33E66" stroke="#13151A" rx="4.5"/></svg>',
|
|
57
|
+
warning: '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="10" fill="none"><path fill="#B58A2D" stroke="#13151A" d="M7.29904 1.25c-.57735-1-2.02073-1-2.59808 0l-3.4641 6C.65951 8.25 1.3812 9.5 2.5359 9.5h6.9282c1.1547 0 1.8764-1.25 1.299-2.25l-3.46406-6Z"/></svg>',
|
|
58
|
+
info: '<svg viewBox="0 0 10 10"><rect width="9" height="9" x=".5" y=".5" fill="#3645D9" stroke="#13151A" rx="1.5"/></svg>'
|
|
59
|
+
};
|
|
54
60
|
const prepareApp = (appDefinition, builtIn) => {
|
|
55
61
|
const eventTarget = new EventTarget();
|
|
56
62
|
const app = {
|
|
@@ -58,19 +64,26 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
58
64
|
builtIn,
|
|
59
65
|
active: false,
|
|
60
66
|
status: "loading",
|
|
61
|
-
notification: { state: false },
|
|
67
|
+
notification: { state: false, level: void 0 },
|
|
62
68
|
eventTarget
|
|
63
69
|
};
|
|
64
70
|
eventTarget.addEventListener("toggle-notification", (evt) => {
|
|
71
|
+
if (!(evt instanceof CustomEvent))
|
|
72
|
+
return;
|
|
65
73
|
const target = overlay.shadowRoot?.querySelector(`[data-app-id="${app.id}"]`);
|
|
66
|
-
|
|
74
|
+
const notificationElement = target?.querySelector(".notification");
|
|
75
|
+
if (!target || !notificationElement)
|
|
67
76
|
return;
|
|
68
|
-
let newState = true;
|
|
69
|
-
|
|
70
|
-
newState = evt.detail.state ?? true;
|
|
71
|
-
}
|
|
77
|
+
let newState = evt.detail.state ?? true;
|
|
78
|
+
let level = notificationLevels.includes(evt?.detail?.level) ? evt.detail.level : "error";
|
|
72
79
|
app.notification.state = newState;
|
|
73
|
-
|
|
80
|
+
if (newState)
|
|
81
|
+
app.notification.level = level;
|
|
82
|
+
notificationElement.toggleAttribute("data-active", newState);
|
|
83
|
+
if (newState) {
|
|
84
|
+
notificationElement.setAttribute("data-level", level);
|
|
85
|
+
notificationElement.innerHTML = notificationSVGs[level];
|
|
86
|
+
}
|
|
74
87
|
});
|
|
75
88
|
const onToggleApp = async (evt) => {
|
|
76
89
|
let newState = void 0;
|
|
@@ -112,12 +125,13 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
112
125
|
display: none;
|
|
113
126
|
position: absolute;
|
|
114
127
|
top: -4px;
|
|
115
|
-
right: -
|
|
116
|
-
width:
|
|
117
|
-
height:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
right: -5px;
|
|
129
|
+
width: 12px;
|
|
130
|
+
height: 10px;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.notification svg {
|
|
134
|
+
display: block;
|
|
121
135
|
}
|
|
122
136
|
|
|
123
137
|
#dropdown:not([data-no-notification]) .notification[data-active] {
|
|
@@ -189,11 +203,25 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
189
203
|
app.eventTarget.addEventListener("toggle-notification", (evt) => {
|
|
190
204
|
if (!(evt instanceof CustomEvent))
|
|
191
205
|
return;
|
|
192
|
-
|
|
206
|
+
let newState = evt.detail.state ?? true;
|
|
207
|
+
let level = notificationLevels.includes(evt?.detail?.level) ? evt.detail.level : "error";
|
|
208
|
+
notification.toggleAttribute("data-active", newState);
|
|
209
|
+
if (newState) {
|
|
210
|
+
notification.setAttribute("data-level", level);
|
|
211
|
+
notification.innerHTML = notificationSVGs[level];
|
|
212
|
+
}
|
|
213
|
+
app.notification.state = newState;
|
|
214
|
+
if (newState)
|
|
215
|
+
app.notification.level = level;
|
|
193
216
|
eventTarget.dispatchEvent(
|
|
194
217
|
new CustomEvent("toggle-notification", {
|
|
195
218
|
detail: {
|
|
196
|
-
state: hiddenApps.some((p) => p.notification.state === true)
|
|
219
|
+
state: hiddenApps.some((p) => p.notification.state === true),
|
|
220
|
+
level: ["error", "warning", "info"].find(
|
|
221
|
+
(notificationLevel) => hiddenApps.some(
|
|
222
|
+
(p) => p.notification.state === true && p.notification.level === notificationLevel
|
|
223
|
+
)
|
|
224
|
+
) ?? "error"
|
|
197
225
|
}
|
|
198
226
|
})
|
|
199
227
|
);
|
|
@@ -10,7 +10,9 @@ export declare const settings: {
|
|
|
10
10
|
readonly config: Settings;
|
|
11
11
|
updateSetting: (key: keyof Settings, value: boolean) => void;
|
|
12
12
|
logger: {
|
|
13
|
-
log: (message: string) => void;
|
|
13
|
+
log: (message: string, level?: 'log' | 'warn' | 'error') => void;
|
|
14
|
+
warn: (message: string) => void;
|
|
15
|
+
error: (message: string) => void;
|
|
14
16
|
verboseLog: (message: string) => void;
|
|
15
17
|
};
|
|
16
18
|
};
|
|
@@ -18,8 +18,8 @@ function getSettings() {
|
|
|
18
18
|
_settings[key] = value;
|
|
19
19
|
localStorage.setItem("astro:dev-toolbar:settings", JSON.stringify(_settings));
|
|
20
20
|
}
|
|
21
|
-
function log(message) {
|
|
22
|
-
console
|
|
21
|
+
function log(message, level = "log") {
|
|
22
|
+
console[level](
|
|
23
23
|
`%cAstro`,
|
|
24
24
|
"background: linear-gradient(66.77deg, #D83333 0%, #F041FF 100%); color: white; padding-inline: 4px; border-radius: 2px; font-family: monospace;",
|
|
25
25
|
message
|
|
@@ -32,6 +32,12 @@ function getSettings() {
|
|
|
32
32
|
updateSetting,
|
|
33
33
|
logger: {
|
|
34
34
|
log,
|
|
35
|
+
warn: (message) => {
|
|
36
|
+
log(message, "warn");
|
|
37
|
+
},
|
|
38
|
+
error: (message) => {
|
|
39
|
+
log(message, "error");
|
|
40
|
+
},
|
|
35
41
|
verboseLog: (message) => {
|
|
36
42
|
if (_settings.verbose) {
|
|
37
43
|
log(message);
|