@civitai/app-sdk 0.46.0 → 0.48.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/README.md +120 -33
- package/dist/blocks/appStorageLimits.d.ts +113 -0
- package/dist/blocks/appStorageLimits.d.ts.map +1 -0
- package/dist/blocks/appStorageLimits.js +113 -0
- package/dist/blocks/appStorageLimits.js.map +1 -0
- package/dist/blocks/index.d.ts +26 -7
- package/dist/blocks/index.d.ts.map +1 -1
- package/dist/blocks/index.js +25 -5
- package/dist/blocks/index.js.map +1 -1
- package/dist/blocks/manifestError.d.ts +20 -0
- package/dist/blocks/manifestError.d.ts.map +1 -0
- package/dist/blocks/manifestError.js +22 -0
- package/dist/blocks/manifestError.js.map +1 -0
- package/dist/blocks/messages.d.ts.map +1 -1
- package/dist/blocks/messages.js.map +1 -1
- package/dist/blocks/scopes.d.ts +7 -3
- package/dist/blocks/scopes.d.ts.map +1 -1
- package/dist/blocks/scopes.js +7 -3
- package/dist/blocks/scopes.js.map +1 -1
- package/dist/blocks/types.d.ts +197 -50
- package/dist/blocks/types.d.ts.map +1 -1
- package/dist/blocks/types.js +56 -0
- package/dist/blocks/types.js.map +1 -1
- package/dist/manifest/defineBlock.d.ts +145 -0
- package/dist/manifest/defineBlock.d.ts.map +1 -0
- package/dist/manifest/defineBlock.js +390 -0
- package/dist/manifest/defineBlock.js.map +1 -0
- package/dist/manifest/index.d.ts +19 -0
- package/dist/manifest/index.d.ts.map +1 -0
- package/dist/manifest/index.js +17 -0
- package/dist/manifest/index.js.map +1 -0
- package/dist/oauth/token.d.ts +34 -3
- package/dist/oauth/token.d.ts.map +1 -1
- package/dist/oauth/token.js +116 -4
- package/dist/oauth/token.js.map +1 -1
- package/dist/vite/index.d.ts +14 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +61 -0
- package/dist/vite/index.js.map +1 -0
- package/package.json +42 -2
- package/dist/blocks/defineBlock.d.ts +0 -53
- package/dist/blocks/defineBlock.d.ts.map +0 -1
- package/dist/blocks/defineBlock.js +0 -338
- package/dist/blocks/defineBlock.js.map +0 -1
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Build-time / startup validation for a `BlockManifestV1`.
|
|
3
|
-
*
|
|
4
|
-
* This is a subset of what the civitai/civitai server enforces — the client
|
|
5
|
-
* runs it so authoring mistakes surface in `pnpm dev` rather than at
|
|
6
|
-
* `civitai deploy` time. Rules here MUST stay a strict subset of the
|
|
7
|
-
* server's; if the server tightens, mirror the change here.
|
|
8
|
-
*
|
|
9
|
-
* Every check guards `typeof` before pattern-testing — the highest-value
|
|
10
|
-
* caller is `JSON.parse(fs.readFileSync('block.manifest.json'))`, where
|
|
11
|
-
* the TypeScript type is a lie.
|
|
12
|
-
*/
|
|
13
|
-
import { BLOCK_CATEGORIES, BLOCK_SCOPES, BLOCK_SCOPE_PATTERN, BLOCK_TAGLINE_MAX_LENGTH, } from './scopes.js';
|
|
14
|
-
/**
|
|
15
|
-
* Canonical `blockId` rule (https://civitai.com/schemas/app-block/v1.json):
|
|
16
|
-
* lowercase, must start with a letter, end alphanumeric, hyphen-separated,
|
|
17
|
-
* 3–40 chars. This is the DNS-subdomain-safe rule — the blockId becomes
|
|
18
|
-
* `<blockId>.civit.ai`, so it must be a valid DNS label.
|
|
19
|
-
*/
|
|
20
|
-
const BLOCK_ID_PATTERN = /^[a-z][a-z0-9-]*[a-z0-9]$/;
|
|
21
|
-
const BLOCK_ID_MIN_LENGTH = 3;
|
|
22
|
-
const BLOCK_ID_MAX_LENGTH = 40;
|
|
23
|
-
/** The 13 canonical block scopes (enum the schema validates `scopes` against). */
|
|
24
|
-
const KNOWN_BLOCK_SCOPES = new Set(Object.values(BLOCK_SCOPES));
|
|
25
|
-
/** The 7 canonical marketplace categories (enum the schema validates `category` against). */
|
|
26
|
-
const KNOWN_CATEGORIES = new Set(BLOCK_CATEGORIES);
|
|
27
|
-
const NAME_MAX_LENGTH = 80;
|
|
28
|
-
const SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
29
|
-
/** Detects the SubresourceIntegrity hash format (sha256/384/512 + base64). */
|
|
30
|
-
const SRI_PATTERN = /^sha(?:256|384|512)-[A-Za-z0-9+/=]+$/;
|
|
31
|
-
/** Heuristic for "looks PascalCase" — used only to pick the pointed error message. */
|
|
32
|
-
const PASCAL_CASE_PATTERN = /^[A-Z][A-Za-z0-9]*$/;
|
|
33
|
-
const EXPECTED_SCHEMA_URL = 'https://civitai.com/schemas/app-block/v1.json';
|
|
34
|
-
const CONTENT_RATINGS = ['g', 'pg', 'pg13', 'r', 'x'];
|
|
35
|
-
/**
|
|
36
|
-
* W3 v0 — settings type set. Mirrors the meta-schema discriminated union
|
|
37
|
-
* in civitai/civitai's `manifest-settings.meta.schema.ts`. Keep aligned.
|
|
38
|
-
*/
|
|
39
|
-
const SETTING_TYPES = ['number', 'string', 'boolean'];
|
|
40
|
-
const SETTING_SCOPES = ['publisher', 'viewer'];
|
|
41
|
-
const SETTING_KEY_PATTERN = /^[a-z][a-z0-9_]{0,40}$/;
|
|
42
|
-
const MAX_SETTINGS_PER_BLOCK = 32;
|
|
43
|
-
/**
|
|
44
|
-
* All `allow-top-navigation*` sandbox tokens are rejected. The
|
|
45
|
-
* `-by-user-activation` and `-to-custom-protocols` variants gate on a user
|
|
46
|
-
* gesture but produce the same threat (block navigates the host frame) —
|
|
47
|
-
* blocks must route navigation through the `NAVIGATE` postMessage so the
|
|
48
|
-
* host can mediate.
|
|
49
|
-
*/
|
|
50
|
-
const BANNED_SANDBOX_TOKENS = new Set([
|
|
51
|
-
'allow-same-origin',
|
|
52
|
-
'allow-top-navigation',
|
|
53
|
-
'allow-top-navigation-by-user-activation',
|
|
54
|
-
'allow-top-navigation-to-custom-protocols',
|
|
55
|
-
]);
|
|
56
|
-
const REQUIRED_FIELDS = [
|
|
57
|
-
'$schema',
|
|
58
|
-
'appId',
|
|
59
|
-
'blockId',
|
|
60
|
-
'version',
|
|
61
|
-
'name',
|
|
62
|
-
'type',
|
|
63
|
-
'targets',
|
|
64
|
-
'scopes',
|
|
65
|
-
'iframe',
|
|
66
|
-
'contentRating',
|
|
67
|
-
'minApiVersion',
|
|
68
|
-
];
|
|
69
|
-
/** Thrown by `defineBlock` for any manifest violation. */
|
|
70
|
-
export class BlockManifestError extends Error {
|
|
71
|
-
field;
|
|
72
|
-
name = 'BlockManifestError';
|
|
73
|
-
constructor(message,
|
|
74
|
-
/** Dot-path to the offending field, e.g. `iframe.sandbox`. */
|
|
75
|
-
field) {
|
|
76
|
-
super(message);
|
|
77
|
-
this.field = field;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Validates the manifest and returns it unchanged. Acts as a typed identity
|
|
82
|
-
* function — call it at module scope in the block app so violations throw
|
|
83
|
-
* before the app mounts. Mirrors a strict subset of the civitai/civitai server
|
|
84
|
-
* gate, so authoring mistakes surface in `pnpm dev` instead of at submit time.
|
|
85
|
-
* Throws {@link BlockManifestError} (with a `.field` dot-path) on a bad manifest.
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* import { defineBlock } from '@civitai/app-sdk/blocks';
|
|
89
|
-
*
|
|
90
|
-
* export const manifest = defineBlock({
|
|
91
|
-
* manifest: {
|
|
92
|
-
* $schema: 'https://civitai.com/schemas/app-block/v1.json',
|
|
93
|
-
* appId: 'my-app',
|
|
94
|
-
* blockId: 'my-block',
|
|
95
|
-
* version: '1.0.0',
|
|
96
|
-
* name: 'My Block',
|
|
97
|
-
* type: 'block',
|
|
98
|
-
* targets: [{ slotId: 'model.sidebar_top', priority: 100 }],
|
|
99
|
-
* scopes: ['ai:write:budgeted'],
|
|
100
|
-
* iframe: { src: 'https://my-block.civit.ai/', minHeight: 200 },
|
|
101
|
-
* contentRating: 'pg',
|
|
102
|
-
* minApiVersion: '1.0',
|
|
103
|
-
* },
|
|
104
|
-
* });
|
|
105
|
-
*/
|
|
106
|
-
export function defineBlock(config) {
|
|
107
|
-
const { manifest } = config;
|
|
108
|
-
if (manifest == null || typeof manifest !== 'object') {
|
|
109
|
-
throw new BlockManifestError('manifest must be an object');
|
|
110
|
-
}
|
|
111
|
-
for (const field of REQUIRED_FIELDS) {
|
|
112
|
-
if (manifest[field] === undefined || manifest[field] === null) {
|
|
113
|
-
throw new BlockManifestError(`manifest.${field} is required`, field);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (manifest.$schema !== EXPECTED_SCHEMA_URL) {
|
|
117
|
-
throw new BlockManifestError(`manifest.$schema must be "${EXPECTED_SCHEMA_URL}"`, '$schema');
|
|
118
|
-
}
|
|
119
|
-
requireNonEmptyString(manifest.appId, 'appId');
|
|
120
|
-
requireNonEmptyString(manifest.blockId, 'blockId');
|
|
121
|
-
if (manifest.blockId.length < BLOCK_ID_MIN_LENGTH ||
|
|
122
|
-
manifest.blockId.length > BLOCK_ID_MAX_LENGTH ||
|
|
123
|
-
!BLOCK_ID_PATTERN.test(manifest.blockId)) {
|
|
124
|
-
throw new BlockManifestError(`manifest.blockId must match ${BLOCK_ID_PATTERN} and be ${BLOCK_ID_MIN_LENGTH}-${BLOCK_ID_MAX_LENGTH} chars ` +
|
|
125
|
-
`(lowercase, starts with a letter, ends alphanumeric, hyphen-separated — DNS-subdomain-safe since it becomes <blockId>.civit.ai). ` +
|
|
126
|
-
`Got: ${JSON.stringify(manifest.blockId)}`, 'blockId');
|
|
127
|
-
}
|
|
128
|
-
requireNonEmptyString(manifest.version, 'version');
|
|
129
|
-
if (!SEMVER_PATTERN.test(manifest.version)) {
|
|
130
|
-
throw new BlockManifestError(`manifest.version must be semver (e.g. "0.1.0" or "1.2.3-beta.1"). Got: ${JSON.stringify(manifest.version)}`, 'version');
|
|
131
|
-
}
|
|
132
|
-
requireNonEmptyString(manifest.name, 'name');
|
|
133
|
-
if (manifest.name.length > NAME_MAX_LENGTH) {
|
|
134
|
-
throw new BlockManifestError(`manifest.name must be ${NAME_MAX_LENGTH} characters or fewer (got ${manifest.name.length})`, 'name');
|
|
135
|
-
}
|
|
136
|
-
if (manifest.type !== 'block' && manifest.type !== 'embed') {
|
|
137
|
-
throw new BlockManifestError(`manifest.type must be "block" or "embed". Got: ${JSON.stringify(manifest.type)}`, 'type');
|
|
138
|
-
}
|
|
139
|
-
if (!Array.isArray(manifest.scopes) || manifest.scopes.length === 0) {
|
|
140
|
-
throw new BlockManifestError('manifest.scopes must be a non-empty array', 'scopes');
|
|
141
|
-
}
|
|
142
|
-
for (const scope of manifest.scopes) {
|
|
143
|
-
// Authoritative validity = membership in the canonical enum (BLOCK_SCOPES),
|
|
144
|
-
// matching how the published schema validates `scopes`. The format pattern
|
|
145
|
-
// is only used to pick a pointed error message.
|
|
146
|
-
if (typeof scope !== 'string' || !KNOWN_BLOCK_SCOPES.has(scope)) {
|
|
147
|
-
throw new BlockManifestError(buildScopeError(scope), 'scopes');
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (!Array.isArray(manifest.targets) || manifest.targets.length === 0) {
|
|
151
|
-
throw new BlockManifestError('manifest.targets must be a non-empty array', 'targets');
|
|
152
|
-
}
|
|
153
|
-
manifest.targets.forEach((target, i) => validateTarget(target, i));
|
|
154
|
-
if (!CONTENT_RATINGS.includes(manifest.contentRating)) {
|
|
155
|
-
throw new BlockManifestError(`manifest.contentRating must be one of ${CONTENT_RATINGS.join(', ')}. Got: ${JSON.stringify(manifest.contentRating)}`, 'contentRating');
|
|
156
|
-
}
|
|
157
|
-
// `category` is OPTIONAL. When present it must be one of the canonical
|
|
158
|
-
// marketplace categories (mirrors the schema's `category` enum + the server's
|
|
159
|
-
// MARKETPLACE_CATEGORIES). Omission is fine — a moderator categorises then.
|
|
160
|
-
if (manifest.category !== undefined) {
|
|
161
|
-
if (typeof manifest.category !== 'string' || !KNOWN_CATEGORIES.has(manifest.category)) {
|
|
162
|
-
throw new BlockManifestError(`manifest.category must be one of ${BLOCK_CATEGORIES.join(', ')} (or omitted). ` +
|
|
163
|
-
`Got: ${JSON.stringify(manifest.category)}`, 'category');
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
// `tagline` is OPTIONAL. When present it must be a string whose TRIMMED length
|
|
167
|
-
// is 1..BLOCK_TAGLINE_MAX_LENGTH — mirroring the server's authoritative
|
|
168
|
-
// BlockManifestValidator check (which also trims), so a padded-but-fitting
|
|
169
|
-
// value is never rejected here and then accepted at submit. Omission is fine —
|
|
170
|
-
// the store simply renders no tagline.
|
|
171
|
-
if (manifest.tagline !== undefined) {
|
|
172
|
-
const tagline = manifest.tagline;
|
|
173
|
-
if (typeof tagline !== 'string' || tagline.trim().length === 0) {
|
|
174
|
-
throw new BlockManifestError(`manifest.tagline must be a non-empty string (or omitted). Got: ${JSON.stringify(tagline)}`, 'tagline');
|
|
175
|
-
}
|
|
176
|
-
if (tagline.trim().length > BLOCK_TAGLINE_MAX_LENGTH) {
|
|
177
|
-
throw new BlockManifestError(`manifest.tagline must be at most ${BLOCK_TAGLINE_MAX_LENGTH} characters. Got: ${tagline.trim().length}`, 'tagline');
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
requireNonEmptyString(manifest.minApiVersion, 'minApiVersion');
|
|
181
|
-
validateIframe(manifest.iframe);
|
|
182
|
-
if (manifest.assets !== undefined)
|
|
183
|
-
validateAssets(manifest.assets);
|
|
184
|
-
if (manifest.settings !== undefined)
|
|
185
|
-
validateSettings(manifest.settings);
|
|
186
|
-
return manifest;
|
|
187
|
-
}
|
|
188
|
-
function requireNonEmptyString(value, field) {
|
|
189
|
-
if (typeof value !== 'string' || value.length === 0) {
|
|
190
|
-
throw new BlockManifestError(`manifest.${field} must be a non-empty string`, field);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
function buildScopeError(scope) {
|
|
194
|
-
const shown = JSON.stringify(scope);
|
|
195
|
-
const known = Object.values(BLOCK_SCOPES).join(', ');
|
|
196
|
-
if (typeof scope === 'string' && PASCAL_CASE_PATTERN.test(scope)) {
|
|
197
|
-
return (`Block scope strings must use colon-separated lowercase format ` +
|
|
198
|
-
`(e.g. "models:read:self"), not PascalCase (e.g. "ModelsReadSelf"). Got: ${shown}`);
|
|
199
|
-
}
|
|
200
|
-
if (typeof scope === 'string' && !BLOCK_SCOPE_PATTERN.test(scope)) {
|
|
201
|
-
return (`Block scope strings must match ${BLOCK_SCOPE_PATTERN} ` +
|
|
202
|
-
`(three colon-separated lowercase segments, e.g. "models:read:self"). Got: ${shown}`);
|
|
203
|
-
}
|
|
204
|
-
// Well-formed but not one of the known/approved scopes.
|
|
205
|
-
return (`manifest.scopes contains an unknown block scope ${shown}. ` +
|
|
206
|
-
`Must be one of: ${known}.`);
|
|
207
|
-
}
|
|
208
|
-
function validateTarget(target, index) {
|
|
209
|
-
const path = `targets[${index}]`;
|
|
210
|
-
if (target == null || typeof target !== 'object') {
|
|
211
|
-
throw new BlockManifestError(`manifest.${path} must be an object`, path);
|
|
212
|
-
}
|
|
213
|
-
const t = target;
|
|
214
|
-
if (typeof t.slotId !== 'string' || t.slotId.length === 0) {
|
|
215
|
-
throw new BlockManifestError(`manifest.${path}.slotId must be a non-empty string`, `${path}.slotId`);
|
|
216
|
-
}
|
|
217
|
-
if (typeof t.priority !== 'number' || !Number.isInteger(t.priority)) {
|
|
218
|
-
throw new BlockManifestError(`manifest.${path}.priority must be an integer`, `${path}.priority`);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
function validateIframe(iframe) {
|
|
222
|
-
if (iframe == null || typeof iframe !== 'object') {
|
|
223
|
-
throw new BlockManifestError('manifest.iframe must be an object', 'iframe');
|
|
224
|
-
}
|
|
225
|
-
if (typeof iframe.src !== 'string' || iframe.src.length === 0) {
|
|
226
|
-
throw new BlockManifestError('manifest.iframe.src must be a non-empty string', 'iframe.src');
|
|
227
|
-
}
|
|
228
|
-
if (!isAllowedIframeSrc(iframe.src)) {
|
|
229
|
-
throw new BlockManifestError(`manifest.iframe.src must use https:// (http:// only accepted for localhost/127.0.0.1/[::1]/*.localhost). Got: ${JSON.stringify(iframe.src)}`, 'iframe.src');
|
|
230
|
-
}
|
|
231
|
-
if (typeof iframe.sandbox !== 'string') {
|
|
232
|
-
throw new BlockManifestError('manifest.iframe.sandbox must be a string', 'iframe.sandbox');
|
|
233
|
-
}
|
|
234
|
-
const tokens = new Set(iframe.sandbox.split(/\s+/).filter(Boolean));
|
|
235
|
-
for (const banned of BANNED_SANDBOX_TOKENS) {
|
|
236
|
-
if (tokens.has(banned)) {
|
|
237
|
-
throw new BlockManifestError(`manifest.iframe.sandbox must not contain "${banned}". ` +
|
|
238
|
-
(banned === 'allow-same-origin'
|
|
239
|
-
? 'Combined with "allow-scripts" it defeats the sandbox entirely.'
|
|
240
|
-
: 'Blocks must route navigation through the NAVIGATE postMessage so the host can mediate.'), 'iframe.sandbox');
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
if (typeof iframe.minHeight !== 'number' || !Number.isInteger(iframe.minHeight) || iframe.minHeight <= 0) {
|
|
244
|
-
throw new BlockManifestError('manifest.iframe.minHeight must be a positive integer', 'iframe.minHeight');
|
|
245
|
-
}
|
|
246
|
-
if (iframe.maxHeight !== undefined &&
|
|
247
|
-
iframe.maxHeight !== null &&
|
|
248
|
-
(typeof iframe.maxHeight !== 'number' || !Number.isInteger(iframe.maxHeight) || iframe.maxHeight <= 0)) {
|
|
249
|
-
throw new BlockManifestError('manifest.iframe.maxHeight must be a positive integer, null, or omitted', 'iframe.maxHeight');
|
|
250
|
-
}
|
|
251
|
-
if (typeof iframe.resizable !== 'boolean') {
|
|
252
|
-
throw new BlockManifestError('manifest.iframe.resizable must be a boolean', 'iframe.resizable');
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
function validateAssets(assets) {
|
|
256
|
-
if (!Array.isArray(assets)) {
|
|
257
|
-
throw new BlockManifestError('manifest.assets must be an array', 'assets');
|
|
258
|
-
}
|
|
259
|
-
assets.forEach((asset, i) => {
|
|
260
|
-
const path = `assets[${i}]`;
|
|
261
|
-
if (asset == null || typeof asset !== 'object') {
|
|
262
|
-
throw new BlockManifestError(`manifest.${path} must be an object`, path);
|
|
263
|
-
}
|
|
264
|
-
const a = asset;
|
|
265
|
-
if (typeof a.url !== 'string' || a.url.length === 0) {
|
|
266
|
-
throw new BlockManifestError(`manifest.${path}.url must be a non-empty string`, `${path}.url`);
|
|
267
|
-
}
|
|
268
|
-
if (typeof a.integrity !== 'string' || !SRI_PATTERN.test(a.integrity)) {
|
|
269
|
-
throw new BlockManifestError(`manifest.${path}.integrity must be a SubresourceIntegrity hash ` +
|
|
270
|
-
`(sha256/384/512-<base64>). Got: ${JSON.stringify(a.integrity)}`, `${path}.integrity`);
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* W3 v0 settings validation. Manifest authors declare fields as a record
|
|
276
|
-
* keyed by snake_case field name; each entry carries scope, type, label,
|
|
277
|
-
* description, and a widget hint. This is a strict subset of the platform
|
|
278
|
-
* meta-schema (`manifestSettingsSchema`) — keep both sides aligned.
|
|
279
|
-
*/
|
|
280
|
-
function validateSettings(settings) {
|
|
281
|
-
if (settings == null || typeof settings !== 'object' || Array.isArray(settings)) {
|
|
282
|
-
throw new BlockManifestError('manifest.settings must be an object (record keyed by snake_case field name)', 'settings');
|
|
283
|
-
}
|
|
284
|
-
const entries = Object.entries(settings);
|
|
285
|
-
if (entries.length > MAX_SETTINGS_PER_BLOCK) {
|
|
286
|
-
throw new BlockManifestError(`manifest.settings has ${entries.length} entries (max ${MAX_SETTINGS_PER_BLOCK})`, 'settings');
|
|
287
|
-
}
|
|
288
|
-
for (const [key, raw] of entries) {
|
|
289
|
-
const path = `settings.${key}`;
|
|
290
|
-
if (!SETTING_KEY_PATTERN.test(key)) {
|
|
291
|
-
throw new BlockManifestError(`manifest.${path}: key must match ${SETTING_KEY_PATTERN} (snake_case, must start with a letter)`, path);
|
|
292
|
-
}
|
|
293
|
-
if (raw == null || typeof raw !== 'object') {
|
|
294
|
-
throw new BlockManifestError(`manifest.${path} must be an object`, path);
|
|
295
|
-
}
|
|
296
|
-
const s = raw;
|
|
297
|
-
if (typeof s.scope !== 'string' || !SETTING_SCOPES.includes(s.scope)) {
|
|
298
|
-
throw new BlockManifestError(`manifest.${path}.scope must be one of ${SETTING_SCOPES.join(', ')}. Got: ${JSON.stringify(s.scope)}`, `${path}.scope`);
|
|
299
|
-
}
|
|
300
|
-
if (typeof s.type !== 'string' || !SETTING_TYPES.includes(s.type)) {
|
|
301
|
-
throw new BlockManifestError(`manifest.${path}.type must be one of ${SETTING_TYPES.join(', ')}. Got: ${JSON.stringify(s.type)}`, `${path}.type`);
|
|
302
|
-
}
|
|
303
|
-
if (typeof s.label !== 'string' || s.label.length === 0) {
|
|
304
|
-
throw new BlockManifestError(`manifest.${path}.label must be a non-empty string`, `${path}.label`);
|
|
305
|
-
}
|
|
306
|
-
if (typeof s.description !== 'string' || s.description.length === 0) {
|
|
307
|
-
throw new BlockManifestError(`manifest.${path}.description must be a non-empty string`, `${path}.description`);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
function isAllowedIframeSrc(src) {
|
|
312
|
-
let url;
|
|
313
|
-
try {
|
|
314
|
-
url = new URL(src);
|
|
315
|
-
}
|
|
316
|
-
catch {
|
|
317
|
-
return false;
|
|
318
|
-
}
|
|
319
|
-
// Reject URLs with no host even if they parse (e.g. "https://" alone, which
|
|
320
|
-
// some URL parsers permit).
|
|
321
|
-
if (!url.hostname)
|
|
322
|
-
return false;
|
|
323
|
-
if (url.protocol === 'https:')
|
|
324
|
-
return true;
|
|
325
|
-
if (url.protocol !== 'http:')
|
|
326
|
-
return false;
|
|
327
|
-
const host = url.hostname;
|
|
328
|
-
// RFC 6761 reserves `.localhost` for loopback.
|
|
329
|
-
if (host === 'localhost' || host.endsWith('.localhost'))
|
|
330
|
-
return true;
|
|
331
|
-
if (host === '127.0.0.1')
|
|
332
|
-
return true;
|
|
333
|
-
// IPv6 loopback. WHATWG URL parses "[::1]" → hostname "[::1]" or "::1".
|
|
334
|
-
if (host === '[::1]' || host === '::1')
|
|
335
|
-
return true;
|
|
336
|
-
return false;
|
|
337
|
-
}
|
|
338
|
-
//# sourceMappingURL=defineBlock.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"defineBlock.js","sourceRoot":"","sources":["../../src/blocks/defineBlock.ts"],"names":[],"mappings":"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"}
|