@wordpress/asset-loader 1.1.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/CHANGELOG.md +9 -0
- package/LICENSE.md +788 -0
- package/README.md +140 -0
- package/build/index.js +185 -0
- package/build/index.js.map +7 -0
- package/build-module/index.js +164 -0
- package/build-module/index.js.map +7 -0
- package/build-types/index.d.ts +17 -0
- package/build-types/index.d.ts.map +1 -0
- package/package.json +44 -0
- package/src/index.ts +255 -0
- package/tsconfig.json +4 -0
- package/tsconfig.tsbuildinfo +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Asset Loader
|
|
2
|
+
|
|
3
|
+
Utility to dynamically load WordPress scripts and styles with dependency resolution.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides a function to dynamically inject WordPress assets (scripts and styles) into the DOM with:
|
|
8
|
+
|
|
9
|
+
- **Dependency resolution** - Respects WordPress dependency graphs via topological sort
|
|
10
|
+
- **Parallel loading** - External scripts load in parallel for performance
|
|
11
|
+
- **Sequential execution** - Inline scripts execute in the correct order
|
|
12
|
+
- **Inline scripts/styles** - Supports before/after inline content per handle
|
|
13
|
+
- **WordPress compatibility** - Mimics `wp_enqueue_script`/`wp_enqueue_style` behavior
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
Install the module:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @wordpress/asset-loader --save
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### Basic Usage
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import loadAssets from '@wordpress/asset-loader';
|
|
29
|
+
|
|
30
|
+
const assets = {
|
|
31
|
+
scripts: {
|
|
32
|
+
'wp-blocks': {
|
|
33
|
+
src: 'https://example.com/wp-includes/js/dist/blocks.min.js',
|
|
34
|
+
deps: [ 'wp-element', 'wp-data' ],
|
|
35
|
+
version: '1.0.0',
|
|
36
|
+
in_footer: true,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
styles: {
|
|
40
|
+
'wp-block-library': {
|
|
41
|
+
src: 'https://example.com/wp-includes/css/dist/block-library/style.min.css',
|
|
42
|
+
deps: [],
|
|
43
|
+
version: '1.0.0',
|
|
44
|
+
media: 'all',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
inline_scripts: {
|
|
48
|
+
before: {},
|
|
49
|
+
after: {
|
|
50
|
+
'wp-blocks': 'wp.blocks.registerBlockType(...)',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
inline_styles: {
|
|
54
|
+
before: {},
|
|
55
|
+
after: {},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
await loadAssets(
|
|
60
|
+
assets.scripts,
|
|
61
|
+
assets.inline_scripts,
|
|
62
|
+
assets.styles,
|
|
63
|
+
assets.inline_styles
|
|
64
|
+
);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### With @wordpress/core-data
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { resolveSelect } from '@wordpress/data';
|
|
71
|
+
import { store as coreDataStore } from '@wordpress/core-data';
|
|
72
|
+
import { unlock } from './lock-unlock';
|
|
73
|
+
import loadAssets from '@wordpress/asset-loader';
|
|
74
|
+
|
|
75
|
+
async function loadEditorAssets() {
|
|
76
|
+
// Get assets from the REST API endpoint
|
|
77
|
+
const assets = await unlock(
|
|
78
|
+
resolveSelect( coreDataStore )
|
|
79
|
+
).getEditorAssets();
|
|
80
|
+
|
|
81
|
+
// Load them into the DOM
|
|
82
|
+
await loadAssets(
|
|
83
|
+
assets.scripts || {},
|
|
84
|
+
assets.inline_scripts || { before: {}, after: {} },
|
|
85
|
+
assets.styles || {},
|
|
86
|
+
assets.inline_styles || { before: {}, after: {} }
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## API
|
|
92
|
+
|
|
93
|
+
### loadAssets(scriptsData, inlineScripts, stylesData, inlineStyles)
|
|
94
|
+
|
|
95
|
+
Loads WordPress assets with dependency resolution.
|
|
96
|
+
|
|
97
|
+
#### Parameters
|
|
98
|
+
|
|
99
|
+
- **scriptsData** `Record<string, Script>` - Map of script handles to script data
|
|
100
|
+
- **inlineScripts** `Record<'before' | 'after', Record<string, string | string[]>>` - Inline scripts
|
|
101
|
+
- **stylesData** `Record<string, Style>` - Map of style handles to style data
|
|
102
|
+
- **inlineStyles** `Record<'before' | 'after', Record<string, string | string[]>>` - Inline styles
|
|
103
|
+
|
|
104
|
+
#### Returns
|
|
105
|
+
|
|
106
|
+
`Promise<void>` - Resolves when all assets are loaded and executed
|
|
107
|
+
|
|
108
|
+
#### Types
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
type Script = {
|
|
112
|
+
src: string;
|
|
113
|
+
deps?: string[];
|
|
114
|
+
version?: string;
|
|
115
|
+
in_footer?: boolean;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
type Style = {
|
|
119
|
+
src: string;
|
|
120
|
+
deps?: string[];
|
|
121
|
+
version?: string;
|
|
122
|
+
media?: string;
|
|
123
|
+
};
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## How It Works
|
|
127
|
+
|
|
128
|
+
1. **Topological Sort** - Orders assets based on dependencies using depth-first search
|
|
129
|
+
2. **Stylesheet Loading** - Loads CSS files in dependency order with inline styles
|
|
130
|
+
3. **Script Loading** - Separates head/body scripts based on `in_footer` flag
|
|
131
|
+
4. **Parallel Execution** - External scripts load in parallel (with `async=false` for order)
|
|
132
|
+
5. **Inline Scripts** - Execute after their corresponding external scripts load
|
|
133
|
+
|
|
134
|
+
## Contributing
|
|
135
|
+
|
|
136
|
+
See [CONTRIBUTING.md](../../CONTRIBUTING.md).
|
|
137
|
+
|
|
138
|
+
## License
|
|
139
|
+
|
|
140
|
+
GPL-2.0-or-later
|
package/build/index.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// packages/asset-loader/src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
default: () => index_default
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
function loadStylesheet(handle, styleData) {
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
if (!styleData.src) {
|
|
29
|
+
resolve();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const existingLink = document.getElementById(handle + "-css");
|
|
33
|
+
if (existingLink) {
|
|
34
|
+
resolve();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const link = document.createElement("link");
|
|
38
|
+
link.rel = "stylesheet";
|
|
39
|
+
link.href = styleData.src + (styleData.version ? "?ver=" + styleData.version : "");
|
|
40
|
+
link.id = handle + "-css";
|
|
41
|
+
link.media = styleData.media || "all";
|
|
42
|
+
link.onload = () => resolve();
|
|
43
|
+
link.onerror = () => {
|
|
44
|
+
console.error(`Failed to load stylesheet: ${handle}`);
|
|
45
|
+
resolve();
|
|
46
|
+
};
|
|
47
|
+
document.head.appendChild(link);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
function loadScript(handle, scriptData) {
|
|
51
|
+
if (!scriptData.src) {
|
|
52
|
+
const marker = document.createElement("script");
|
|
53
|
+
marker.id = handle + "-js";
|
|
54
|
+
marker.textContent = "// Processed: " + handle;
|
|
55
|
+
return marker;
|
|
56
|
+
}
|
|
57
|
+
const script = document.createElement("script");
|
|
58
|
+
script.src = scriptData.src + (scriptData.version ? "?ver=" + scriptData.version : "");
|
|
59
|
+
script.id = handle + "-js";
|
|
60
|
+
script.async = false;
|
|
61
|
+
return script;
|
|
62
|
+
}
|
|
63
|
+
function injectInlineStyle(handle, inlineStyle, position) {
|
|
64
|
+
let styleContent = "";
|
|
65
|
+
if (Array.isArray(inlineStyle)) {
|
|
66
|
+
styleContent = inlineStyle.join("\n");
|
|
67
|
+
} else if (typeof inlineStyle === "string") {
|
|
68
|
+
styleContent = inlineStyle;
|
|
69
|
+
}
|
|
70
|
+
if (styleContent && styleContent.trim()) {
|
|
71
|
+
const styleId = handle + "-" + position + "-inline-css";
|
|
72
|
+
if (!document.getElementById(styleId)) {
|
|
73
|
+
const style = document.createElement("style");
|
|
74
|
+
style.id = styleId;
|
|
75
|
+
style.textContent = styleContent.trim();
|
|
76
|
+
document.head.appendChild(style);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function injectInlineScript(handle, inlineScript, position) {
|
|
81
|
+
let scriptContent = inlineScript;
|
|
82
|
+
if (Array.isArray(scriptContent)) {
|
|
83
|
+
scriptContent = scriptContent.join("\n");
|
|
84
|
+
}
|
|
85
|
+
const script = document.createElement("script");
|
|
86
|
+
script.id = handle + "-" + position + "-js";
|
|
87
|
+
script.textContent = scriptContent.trim();
|
|
88
|
+
return script;
|
|
89
|
+
}
|
|
90
|
+
function buildDependencyOrderedList(assetsData) {
|
|
91
|
+
const visited = /* @__PURE__ */ new Set();
|
|
92
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
93
|
+
const orderedList = [];
|
|
94
|
+
function visit(handle) {
|
|
95
|
+
if (visited.has(handle)) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (visiting.has(handle)) {
|
|
99
|
+
console.warn(
|
|
100
|
+
`Circular dependency detected for handle: ${handle}`
|
|
101
|
+
);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
visiting.add(handle);
|
|
105
|
+
if (assetsData[handle]) {
|
|
106
|
+
const deps = assetsData[handle].deps || [];
|
|
107
|
+
deps.forEach((dep) => {
|
|
108
|
+
if (assetsData[dep]) {
|
|
109
|
+
visit(dep);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
visiting.delete(handle);
|
|
114
|
+
visited.add(handle);
|
|
115
|
+
if (assetsData[handle]) {
|
|
116
|
+
orderedList.push(handle);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
Object.keys(assetsData).forEach((handle) => {
|
|
120
|
+
visit(handle);
|
|
121
|
+
});
|
|
122
|
+
return orderedList;
|
|
123
|
+
}
|
|
124
|
+
async function performScriptLoad(scriptElements, destination) {
|
|
125
|
+
let parallel = [];
|
|
126
|
+
for (const scriptElement of scriptElements) {
|
|
127
|
+
if (scriptElement.src) {
|
|
128
|
+
const loader = Promise.withResolvers();
|
|
129
|
+
scriptElement.onload = () => loader.resolve();
|
|
130
|
+
scriptElement.onerror = () => {
|
|
131
|
+
console.error(`Failed to load script: ${scriptElement.id}`);
|
|
132
|
+
loader.resolve();
|
|
133
|
+
};
|
|
134
|
+
parallel.push(loader.promise);
|
|
135
|
+
} else {
|
|
136
|
+
await Promise.all(parallel);
|
|
137
|
+
parallel = [];
|
|
138
|
+
}
|
|
139
|
+
destination.appendChild(scriptElement);
|
|
140
|
+
}
|
|
141
|
+
await Promise.all(parallel);
|
|
142
|
+
parallel = [];
|
|
143
|
+
}
|
|
144
|
+
async function loadAssets(scriptsData, inlineScripts, stylesData, inlineStyles) {
|
|
145
|
+
const orderedStyles = buildDependencyOrderedList(stylesData);
|
|
146
|
+
const orderedScripts = buildDependencyOrderedList(scriptsData);
|
|
147
|
+
const stylePromises = [];
|
|
148
|
+
for (const handle of orderedStyles) {
|
|
149
|
+
const beforeInline = inlineStyles.before?.[handle];
|
|
150
|
+
if (beforeInline) {
|
|
151
|
+
injectInlineStyle(handle, beforeInline, "before");
|
|
152
|
+
}
|
|
153
|
+
stylePromises.push(loadStylesheet(handle, stylesData[handle]));
|
|
154
|
+
const afterInline = inlineStyles.after?.[handle];
|
|
155
|
+
if (afterInline) {
|
|
156
|
+
injectInlineStyle(handle, afterInline, "after");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const scriptElementsHead = [];
|
|
160
|
+
const scriptElementsBody = [];
|
|
161
|
+
for (const handle of orderedScripts) {
|
|
162
|
+
const inFooter = scriptsData[handle].in_footer || false;
|
|
163
|
+
const scriptElements = inFooter ? scriptElementsBody : scriptElementsHead;
|
|
164
|
+
const beforeInline = inlineScripts.before?.[handle];
|
|
165
|
+
if (beforeInline) {
|
|
166
|
+
scriptElements.push(
|
|
167
|
+
injectInlineScript(handle, beforeInline, "before")
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
scriptElements.push(loadScript(handle, scriptsData[handle]));
|
|
171
|
+
const afterInline = inlineScripts.after?.[handle];
|
|
172
|
+
if (afterInline) {
|
|
173
|
+
scriptElements.push(
|
|
174
|
+
injectInlineScript(handle, afterInline, "after")
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const scriptsPromise = (async () => {
|
|
179
|
+
await performScriptLoad(scriptElementsHead, document.head);
|
|
180
|
+
await performScriptLoad(scriptElementsBody, document.body);
|
|
181
|
+
})();
|
|
182
|
+
await Promise.all([Promise.all(stylePromises), scriptsPromise]);
|
|
183
|
+
}
|
|
184
|
+
var index_default = loadAssets;
|
|
185
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["type Style = {\n\tsrc: string;\n\tdeps?: string[];\n\tversion?: string;\n\tmedia?: string;\n};\n\ntype InlineStyle = string | string[];\n\ntype Script = {\n\tsrc: string;\n\tdeps?: string[];\n\tversion?: string;\n\tin_footer?: boolean;\n};\n\ntype InlineScript = string | string[];\n\nfunction loadStylesheet( handle: string, styleData: Style ): Promise< void > {\n\treturn new Promise( ( resolve ) => {\n\t\tif ( ! styleData.src ) {\n\t\t\tresolve(); // No external file to load\n\t\t\treturn;\n\t\t}\n\n\t\tconst existingLink = document.getElementById( handle + '-css' );\n\t\tif ( existingLink ) {\n\t\t\tresolve(); // Already loaded\n\t\t\treturn;\n\t\t}\n\n\t\tconst link = document.createElement( 'link' );\n\t\tlink.rel = 'stylesheet';\n\t\tlink.href =\n\t\t\tstyleData.src +\n\t\t\t( styleData.version ? '?ver=' + styleData.version : '' );\n\t\tlink.id = handle + '-css';\n\t\tlink.media = styleData.media || 'all';\n\n\t\tlink.onload = () => resolve();\n\t\tlink.onerror = () => {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.error( `Failed to load stylesheet: ${ handle }` );\n\t\t\tresolve();\n\t\t};\n\n\t\tdocument.head.appendChild( link );\n\t} );\n}\n\nfunction loadScript( handle: string, scriptData: Script ): HTMLScriptElement {\n\t// If no external script source, just mark as processed and resolve\n\tif ( ! scriptData.src ) {\n\t\t// Still mark as processed with an ID so we don't repeat processing\n\t\tconst marker = document.createElement( 'script' );\n\t\tmarker.id = handle + '-js';\n\t\tmarker.textContent = '// Processed: ' + handle;\n\t\treturn marker;\n\t}\n\n\tconst script = document.createElement( 'script' );\n\tscript.src =\n\t\tscriptData.src +\n\t\t( scriptData.version ? '?ver=' + scriptData.version : '' );\n\tscript.id = handle + '-js';\n\tscript.async = false;\n\n\treturn script;\n}\n\n// Function to inject inline styles\nfunction injectInlineStyle(\n\thandle: string,\n\tinlineStyle: InlineStyle,\n\tposition: 'before' | 'after'\n) {\n\t// Handle both string and array formats\n\tlet styleContent = '';\n\tif ( Array.isArray( inlineStyle ) ) {\n\t\tstyleContent = inlineStyle.join( '\\n' );\n\t} else if ( typeof inlineStyle === 'string' ) {\n\t\tstyleContent = inlineStyle;\n\t}\n\n\tif ( styleContent && styleContent.trim() ) {\n\t\tconst styleId = handle + '-' + position + '-inline-css';\n\t\tif ( ! document.getElementById( styleId ) ) {\n\t\t\tconst style = document.createElement( 'style' );\n\t\t\tstyle.id = styleId;\n\t\t\tstyle.textContent = styleContent.trim();\n\t\t\tdocument.head.appendChild( style );\n\t\t}\n\t}\n}\n\nfunction injectInlineScript(\n\thandle: string,\n\tinlineScript: InlineScript,\n\tposition: 'before' | 'after'\n): HTMLScriptElement {\n\tlet scriptContent = inlineScript;\n\tif ( Array.isArray( scriptContent ) ) {\n\t\tscriptContent = scriptContent.join( '\\n' );\n\t}\n\n\tconst script = document.createElement( 'script' );\n\tscript.id = handle + '-' + position + '-js';\n\tscript.textContent = scriptContent.trim();\n\n\treturn script;\n}\n\n// Function to create dependency-ordered list respecting WordPress dependency graph\nfunction buildDependencyOrderedList< T extends Style | Script >(\n\tassetsData: Record< string, T >\n) {\n\tconst visited = new Set();\n\tconst visiting = new Set();\n\tconst orderedList: string[] = [];\n\n\tfunction visit( handle: string ) {\n\t\tif ( visited.has( handle ) ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( visiting.has( handle ) ) {\n\t\t\t// Circular dependency detected, skip to avoid infinite loop\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(\n\t\t\t\t`Circular dependency detected for handle: ${ handle }`\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvisiting.add( handle );\n\n\t\tif ( assetsData[ handle ] ) {\n\t\t\t// Visit all dependencies first\n\t\t\tconst deps = assetsData[ handle ].deps || [];\n\t\t\tdeps.forEach( ( dep ) => {\n\t\t\t\tif ( assetsData[ dep ] ) {\n\t\t\t\t\tvisit( dep );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tvisiting.delete( handle );\n\t\tvisited.add( handle );\n\n\t\tif ( assetsData[ handle ] ) {\n\t\t\torderedList.push( handle );\n\t\t}\n\t}\n\n\t// Visit all handles\n\tObject.keys( assetsData ).forEach( ( handle ) => {\n\t\tvisit( handle );\n\t} );\n\n\treturn orderedList;\n}\n\nasync function performScriptLoad(\n\tscriptElements: HTMLScriptElement[],\n\tdestination: HTMLElement\n) {\n\tlet parallel = [];\n\tfor ( const scriptElement of scriptElements ) {\n\t\tif ( scriptElement.src ) {\n\t\t\t// External scripts can be loaded in parallel. They will be executed in DOM order\n\t\t\t// because the `script` tags have an `async = false` attribute. Therefore cross-script\n\t\t\t// dependencies are guaranteed to be satisfied.\n\t\t\tconst loader = Promise.withResolvers< void >();\n\t\t\tscriptElement.onload = () => loader.resolve();\n\t\t\tscriptElement.onerror = () => {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error( `Failed to load script: ${ scriptElement.id }` );\n\t\t\t\tloader.resolve();\n\t\t\t};\n\t\t\tparallel.push( loader.promise );\n\t\t} else {\n\t\t\t// We've encountered an inline script. Inline scripts are executed immediately after\n\t\t\t// inserting them to the DOM. Therefore we need to wait for all external scripts to load.\n\t\t\tawait Promise.all( parallel );\n\t\t\tparallel = [];\n\t\t}\n\t\t// Append the `script` element (external or inline) to the DOM and trigger the load.\n\t\tdestination.appendChild( scriptElement );\n\t}\n\t// Wait for all the remainingexternal scripts to load.\n\tawait Promise.all( parallel );\n\tparallel = [];\n}\n\n// Main async function to load all assets and return editor settings\nasync function loadAssets(\n\tscriptsData: Record< string, Script >,\n\tinlineScripts: Record< 'before' | 'after', Record< string, InlineScript > >,\n\tstylesData: Record< string, Style >,\n\tinlineStyles: Record< 'before' | 'after', Record< string, InlineStyle > >\n): Promise< void > {\n\t// Build dependency-ordered lists\n\tconst orderedStyles = buildDependencyOrderedList( stylesData );\n\tconst orderedScripts = buildDependencyOrderedList( scriptsData );\n\n\tconst stylePromises: Promise< void >[] = [];\n\n\t// Load stylesheets in dependency order\n\tfor ( const handle of orderedStyles ) {\n\t\tconst beforeInline = inlineStyles.before?.[ handle ];\n\t\tif ( beforeInline ) {\n\t\t\tinjectInlineStyle( handle, beforeInline, 'before' );\n\t\t}\n\t\tstylePromises.push( loadStylesheet( handle, stylesData[ handle ] ) );\n\t\tconst afterInline = inlineStyles.after?.[ handle ];\n\t\tif ( afterInline ) {\n\t\t\tinjectInlineStyle( handle, afterInline, 'after' );\n\t\t}\n\t}\n\n\t// Load scripts in dependency order\n\tconst scriptElementsHead: HTMLScriptElement[] = [];\n\tconst scriptElementsBody: HTMLScriptElement[] = [];\n\n\tfor ( const handle of orderedScripts ) {\n\t\tconst inFooter = scriptsData[ handle ].in_footer || false;\n\t\tconst scriptElements = inFooter\n\t\t\t? scriptElementsBody\n\t\t\t: scriptElementsHead;\n\n\t\tconst beforeInline = inlineScripts.before?.[ handle ];\n\t\tif ( beforeInline ) {\n\t\t\tscriptElements.push(\n\t\t\t\tinjectInlineScript( handle, beforeInline, 'before' )\n\t\t\t);\n\t\t}\n\n\t\tscriptElements.push( loadScript( handle, scriptsData[ handle ] ) );\n\n\t\tconst afterInline = inlineScripts.after?.[ handle ];\n\t\tif ( afterInline ) {\n\t\t\tscriptElements.push(\n\t\t\t\tinjectInlineScript( handle, afterInline, 'after' )\n\t\t\t);\n\t\t}\n\t}\n\n\tconst scriptsPromise = ( async () => {\n\t\tawait performScriptLoad( scriptElementsHead, document.head );\n\t\tawait performScriptLoad( scriptElementsBody, document.body );\n\t} )();\n\n\tawait Promise.all( [ Promise.all( stylePromises ), scriptsPromise ] );\n}\n\nexport default loadAssets;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// packages/asset-loader/src/index.ts
|
|
2
|
+
function loadStylesheet(handle, styleData) {
|
|
3
|
+
return new Promise((resolve) => {
|
|
4
|
+
if (!styleData.src) {
|
|
5
|
+
resolve();
|
|
6
|
+
return;
|
|
7
|
+
}
|
|
8
|
+
const existingLink = document.getElementById(handle + "-css");
|
|
9
|
+
if (existingLink) {
|
|
10
|
+
resolve();
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const link = document.createElement("link");
|
|
14
|
+
link.rel = "stylesheet";
|
|
15
|
+
link.href = styleData.src + (styleData.version ? "?ver=" + styleData.version : "");
|
|
16
|
+
link.id = handle + "-css";
|
|
17
|
+
link.media = styleData.media || "all";
|
|
18
|
+
link.onload = () => resolve();
|
|
19
|
+
link.onerror = () => {
|
|
20
|
+
console.error(`Failed to load stylesheet: ${handle}`);
|
|
21
|
+
resolve();
|
|
22
|
+
};
|
|
23
|
+
document.head.appendChild(link);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function loadScript(handle, scriptData) {
|
|
27
|
+
if (!scriptData.src) {
|
|
28
|
+
const marker = document.createElement("script");
|
|
29
|
+
marker.id = handle + "-js";
|
|
30
|
+
marker.textContent = "// Processed: " + handle;
|
|
31
|
+
return marker;
|
|
32
|
+
}
|
|
33
|
+
const script = document.createElement("script");
|
|
34
|
+
script.src = scriptData.src + (scriptData.version ? "?ver=" + scriptData.version : "");
|
|
35
|
+
script.id = handle + "-js";
|
|
36
|
+
script.async = false;
|
|
37
|
+
return script;
|
|
38
|
+
}
|
|
39
|
+
function injectInlineStyle(handle, inlineStyle, position) {
|
|
40
|
+
let styleContent = "";
|
|
41
|
+
if (Array.isArray(inlineStyle)) {
|
|
42
|
+
styleContent = inlineStyle.join("\n");
|
|
43
|
+
} else if (typeof inlineStyle === "string") {
|
|
44
|
+
styleContent = inlineStyle;
|
|
45
|
+
}
|
|
46
|
+
if (styleContent && styleContent.trim()) {
|
|
47
|
+
const styleId = handle + "-" + position + "-inline-css";
|
|
48
|
+
if (!document.getElementById(styleId)) {
|
|
49
|
+
const style = document.createElement("style");
|
|
50
|
+
style.id = styleId;
|
|
51
|
+
style.textContent = styleContent.trim();
|
|
52
|
+
document.head.appendChild(style);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function injectInlineScript(handle, inlineScript, position) {
|
|
57
|
+
let scriptContent = inlineScript;
|
|
58
|
+
if (Array.isArray(scriptContent)) {
|
|
59
|
+
scriptContent = scriptContent.join("\n");
|
|
60
|
+
}
|
|
61
|
+
const script = document.createElement("script");
|
|
62
|
+
script.id = handle + "-" + position + "-js";
|
|
63
|
+
script.textContent = scriptContent.trim();
|
|
64
|
+
return script;
|
|
65
|
+
}
|
|
66
|
+
function buildDependencyOrderedList(assetsData) {
|
|
67
|
+
const visited = /* @__PURE__ */ new Set();
|
|
68
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
69
|
+
const orderedList = [];
|
|
70
|
+
function visit(handle) {
|
|
71
|
+
if (visited.has(handle)) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (visiting.has(handle)) {
|
|
75
|
+
console.warn(
|
|
76
|
+
`Circular dependency detected for handle: ${handle}`
|
|
77
|
+
);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
visiting.add(handle);
|
|
81
|
+
if (assetsData[handle]) {
|
|
82
|
+
const deps = assetsData[handle].deps || [];
|
|
83
|
+
deps.forEach((dep) => {
|
|
84
|
+
if (assetsData[dep]) {
|
|
85
|
+
visit(dep);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
visiting.delete(handle);
|
|
90
|
+
visited.add(handle);
|
|
91
|
+
if (assetsData[handle]) {
|
|
92
|
+
orderedList.push(handle);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
Object.keys(assetsData).forEach((handle) => {
|
|
96
|
+
visit(handle);
|
|
97
|
+
});
|
|
98
|
+
return orderedList;
|
|
99
|
+
}
|
|
100
|
+
async function performScriptLoad(scriptElements, destination) {
|
|
101
|
+
let parallel = [];
|
|
102
|
+
for (const scriptElement of scriptElements) {
|
|
103
|
+
if (scriptElement.src) {
|
|
104
|
+
const loader = Promise.withResolvers();
|
|
105
|
+
scriptElement.onload = () => loader.resolve();
|
|
106
|
+
scriptElement.onerror = () => {
|
|
107
|
+
console.error(`Failed to load script: ${scriptElement.id}`);
|
|
108
|
+
loader.resolve();
|
|
109
|
+
};
|
|
110
|
+
parallel.push(loader.promise);
|
|
111
|
+
} else {
|
|
112
|
+
await Promise.all(parallel);
|
|
113
|
+
parallel = [];
|
|
114
|
+
}
|
|
115
|
+
destination.appendChild(scriptElement);
|
|
116
|
+
}
|
|
117
|
+
await Promise.all(parallel);
|
|
118
|
+
parallel = [];
|
|
119
|
+
}
|
|
120
|
+
async function loadAssets(scriptsData, inlineScripts, stylesData, inlineStyles) {
|
|
121
|
+
const orderedStyles = buildDependencyOrderedList(stylesData);
|
|
122
|
+
const orderedScripts = buildDependencyOrderedList(scriptsData);
|
|
123
|
+
const stylePromises = [];
|
|
124
|
+
for (const handle of orderedStyles) {
|
|
125
|
+
const beforeInline = inlineStyles.before?.[handle];
|
|
126
|
+
if (beforeInline) {
|
|
127
|
+
injectInlineStyle(handle, beforeInline, "before");
|
|
128
|
+
}
|
|
129
|
+
stylePromises.push(loadStylesheet(handle, stylesData[handle]));
|
|
130
|
+
const afterInline = inlineStyles.after?.[handle];
|
|
131
|
+
if (afterInline) {
|
|
132
|
+
injectInlineStyle(handle, afterInline, "after");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const scriptElementsHead = [];
|
|
136
|
+
const scriptElementsBody = [];
|
|
137
|
+
for (const handle of orderedScripts) {
|
|
138
|
+
const inFooter = scriptsData[handle].in_footer || false;
|
|
139
|
+
const scriptElements = inFooter ? scriptElementsBody : scriptElementsHead;
|
|
140
|
+
const beforeInline = inlineScripts.before?.[handle];
|
|
141
|
+
if (beforeInline) {
|
|
142
|
+
scriptElements.push(
|
|
143
|
+
injectInlineScript(handle, beforeInline, "before")
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
scriptElements.push(loadScript(handle, scriptsData[handle]));
|
|
147
|
+
const afterInline = inlineScripts.after?.[handle];
|
|
148
|
+
if (afterInline) {
|
|
149
|
+
scriptElements.push(
|
|
150
|
+
injectInlineScript(handle, afterInline, "after")
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const scriptsPromise = (async () => {
|
|
155
|
+
await performScriptLoad(scriptElementsHead, document.head);
|
|
156
|
+
await performScriptLoad(scriptElementsBody, document.body);
|
|
157
|
+
})();
|
|
158
|
+
await Promise.all([Promise.all(stylePromises), scriptsPromise]);
|
|
159
|
+
}
|
|
160
|
+
var index_default = loadAssets;
|
|
161
|
+
export {
|
|
162
|
+
index_default as default
|
|
163
|
+
};
|
|
164
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["type Style = {\n\tsrc: string;\n\tdeps?: string[];\n\tversion?: string;\n\tmedia?: string;\n};\n\ntype InlineStyle = string | string[];\n\ntype Script = {\n\tsrc: string;\n\tdeps?: string[];\n\tversion?: string;\n\tin_footer?: boolean;\n};\n\ntype InlineScript = string | string[];\n\nfunction loadStylesheet( handle: string, styleData: Style ): Promise< void > {\n\treturn new Promise( ( resolve ) => {\n\t\tif ( ! styleData.src ) {\n\t\t\tresolve(); // No external file to load\n\t\t\treturn;\n\t\t}\n\n\t\tconst existingLink = document.getElementById( handle + '-css' );\n\t\tif ( existingLink ) {\n\t\t\tresolve(); // Already loaded\n\t\t\treturn;\n\t\t}\n\n\t\tconst link = document.createElement( 'link' );\n\t\tlink.rel = 'stylesheet';\n\t\tlink.href =\n\t\t\tstyleData.src +\n\t\t\t( styleData.version ? '?ver=' + styleData.version : '' );\n\t\tlink.id = handle + '-css';\n\t\tlink.media = styleData.media || 'all';\n\n\t\tlink.onload = () => resolve();\n\t\tlink.onerror = () => {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.error( `Failed to load stylesheet: ${ handle }` );\n\t\t\tresolve();\n\t\t};\n\n\t\tdocument.head.appendChild( link );\n\t} );\n}\n\nfunction loadScript( handle: string, scriptData: Script ): HTMLScriptElement {\n\t// If no external script source, just mark as processed and resolve\n\tif ( ! scriptData.src ) {\n\t\t// Still mark as processed with an ID so we don't repeat processing\n\t\tconst marker = document.createElement( 'script' );\n\t\tmarker.id = handle + '-js';\n\t\tmarker.textContent = '// Processed: ' + handle;\n\t\treturn marker;\n\t}\n\n\tconst script = document.createElement( 'script' );\n\tscript.src =\n\t\tscriptData.src +\n\t\t( scriptData.version ? '?ver=' + scriptData.version : '' );\n\tscript.id = handle + '-js';\n\tscript.async = false;\n\n\treturn script;\n}\n\n// Function to inject inline styles\nfunction injectInlineStyle(\n\thandle: string,\n\tinlineStyle: InlineStyle,\n\tposition: 'before' | 'after'\n) {\n\t// Handle both string and array formats\n\tlet styleContent = '';\n\tif ( Array.isArray( inlineStyle ) ) {\n\t\tstyleContent = inlineStyle.join( '\\n' );\n\t} else if ( typeof inlineStyle === 'string' ) {\n\t\tstyleContent = inlineStyle;\n\t}\n\n\tif ( styleContent && styleContent.trim() ) {\n\t\tconst styleId = handle + '-' + position + '-inline-css';\n\t\tif ( ! document.getElementById( styleId ) ) {\n\t\t\tconst style = document.createElement( 'style' );\n\t\t\tstyle.id = styleId;\n\t\t\tstyle.textContent = styleContent.trim();\n\t\t\tdocument.head.appendChild( style );\n\t\t}\n\t}\n}\n\nfunction injectInlineScript(\n\thandle: string,\n\tinlineScript: InlineScript,\n\tposition: 'before' | 'after'\n): HTMLScriptElement {\n\tlet scriptContent = inlineScript;\n\tif ( Array.isArray( scriptContent ) ) {\n\t\tscriptContent = scriptContent.join( '\\n' );\n\t}\n\n\tconst script = document.createElement( 'script' );\n\tscript.id = handle + '-' + position + '-js';\n\tscript.textContent = scriptContent.trim();\n\n\treturn script;\n}\n\n// Function to create dependency-ordered list respecting WordPress dependency graph\nfunction buildDependencyOrderedList< T extends Style | Script >(\n\tassetsData: Record< string, T >\n) {\n\tconst visited = new Set();\n\tconst visiting = new Set();\n\tconst orderedList: string[] = [];\n\n\tfunction visit( handle: string ) {\n\t\tif ( visited.has( handle ) ) {\n\t\t\treturn;\n\t\t}\n\t\tif ( visiting.has( handle ) ) {\n\t\t\t// Circular dependency detected, skip to avoid infinite loop\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(\n\t\t\t\t`Circular dependency detected for handle: ${ handle }`\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tvisiting.add( handle );\n\n\t\tif ( assetsData[ handle ] ) {\n\t\t\t// Visit all dependencies first\n\t\t\tconst deps = assetsData[ handle ].deps || [];\n\t\t\tdeps.forEach( ( dep ) => {\n\t\t\t\tif ( assetsData[ dep ] ) {\n\t\t\t\t\tvisit( dep );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\tvisiting.delete( handle );\n\t\tvisited.add( handle );\n\n\t\tif ( assetsData[ handle ] ) {\n\t\t\torderedList.push( handle );\n\t\t}\n\t}\n\n\t// Visit all handles\n\tObject.keys( assetsData ).forEach( ( handle ) => {\n\t\tvisit( handle );\n\t} );\n\n\treturn orderedList;\n}\n\nasync function performScriptLoad(\n\tscriptElements: HTMLScriptElement[],\n\tdestination: HTMLElement\n) {\n\tlet parallel = [];\n\tfor ( const scriptElement of scriptElements ) {\n\t\tif ( scriptElement.src ) {\n\t\t\t// External scripts can be loaded in parallel. They will be executed in DOM order\n\t\t\t// because the `script` tags have an `async = false` attribute. Therefore cross-script\n\t\t\t// dependencies are guaranteed to be satisfied.\n\t\t\tconst loader = Promise.withResolvers< void >();\n\t\t\tscriptElement.onload = () => loader.resolve();\n\t\t\tscriptElement.onerror = () => {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error( `Failed to load script: ${ scriptElement.id }` );\n\t\t\t\tloader.resolve();\n\t\t\t};\n\t\t\tparallel.push( loader.promise );\n\t\t} else {\n\t\t\t// We've encountered an inline script. Inline scripts are executed immediately after\n\t\t\t// inserting them to the DOM. Therefore we need to wait for all external scripts to load.\n\t\t\tawait Promise.all( parallel );\n\t\t\tparallel = [];\n\t\t}\n\t\t// Append the `script` element (external or inline) to the DOM and trigger the load.\n\t\tdestination.appendChild( scriptElement );\n\t}\n\t// Wait for all the remainingexternal scripts to load.\n\tawait Promise.all( parallel );\n\tparallel = [];\n}\n\n// Main async function to load all assets and return editor settings\nasync function loadAssets(\n\tscriptsData: Record< string, Script >,\n\tinlineScripts: Record< 'before' | 'after', Record< string, InlineScript > >,\n\tstylesData: Record< string, Style >,\n\tinlineStyles: Record< 'before' | 'after', Record< string, InlineStyle > >\n): Promise< void > {\n\t// Build dependency-ordered lists\n\tconst orderedStyles = buildDependencyOrderedList( stylesData );\n\tconst orderedScripts = buildDependencyOrderedList( scriptsData );\n\n\tconst stylePromises: Promise< void >[] = [];\n\n\t// Load stylesheets in dependency order\n\tfor ( const handle of orderedStyles ) {\n\t\tconst beforeInline = inlineStyles.before?.[ handle ];\n\t\tif ( beforeInline ) {\n\t\t\tinjectInlineStyle( handle, beforeInline, 'before' );\n\t\t}\n\t\tstylePromises.push( loadStylesheet( handle, stylesData[ handle ] ) );\n\t\tconst afterInline = inlineStyles.after?.[ handle ];\n\t\tif ( afterInline ) {\n\t\t\tinjectInlineStyle( handle, afterInline, 'after' );\n\t\t}\n\t}\n\n\t// Load scripts in dependency order\n\tconst scriptElementsHead: HTMLScriptElement[] = [];\n\tconst scriptElementsBody: HTMLScriptElement[] = [];\n\n\tfor ( const handle of orderedScripts ) {\n\t\tconst inFooter = scriptsData[ handle ].in_footer || false;\n\t\tconst scriptElements = inFooter\n\t\t\t? scriptElementsBody\n\t\t\t: scriptElementsHead;\n\n\t\tconst beforeInline = inlineScripts.before?.[ handle ];\n\t\tif ( beforeInline ) {\n\t\t\tscriptElements.push(\n\t\t\t\tinjectInlineScript( handle, beforeInline, 'before' )\n\t\t\t);\n\t\t}\n\n\t\tscriptElements.push( loadScript( handle, scriptsData[ handle ] ) );\n\n\t\tconst afterInline = inlineScripts.after?.[ handle ];\n\t\tif ( afterInline ) {\n\t\t\tscriptElements.push(\n\t\t\t\tinjectInlineScript( handle, afterInline, 'after' )\n\t\t\t);\n\t\t}\n\t}\n\n\tconst scriptsPromise = ( async () => {\n\t\tawait performScriptLoad( scriptElementsHead, document.head );\n\t\tawait performScriptLoad( scriptElementsBody, document.body );\n\t} )();\n\n\tawait Promise.all( [ Promise.all( stylePromises ), scriptsPromise ] );\n}\n\nexport default loadAssets;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
type Style = {
|
|
2
|
+
src: string;
|
|
3
|
+
deps?: string[];
|
|
4
|
+
version?: string;
|
|
5
|
+
media?: string;
|
|
6
|
+
};
|
|
7
|
+
type InlineStyle = string | string[];
|
|
8
|
+
type Script = {
|
|
9
|
+
src: string;
|
|
10
|
+
deps?: string[];
|
|
11
|
+
version?: string;
|
|
12
|
+
in_footer?: boolean;
|
|
13
|
+
};
|
|
14
|
+
type InlineScript = string | string[];
|
|
15
|
+
declare function loadAssets(scriptsData: Record<string, Script>, inlineScripts: Record<'before' | 'after', Record<string, InlineScript>>, stylesData: Record<string, Style>, inlineStyles: Record<'before' | 'after', Record<string, InlineStyle>>): Promise<void>;
|
|
16
|
+
export default loadAssets;
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,KAAK,KAAK,GAAG;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAErC,KAAK,MAAM,GAAG;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,YAAY,GAAG,MAAM,GAAG,MAAM,EAAE,CAAC;AAkLtC,iBAAe,UAAU,CACxB,WAAW,EAAE,MAAM,CAAE,MAAM,EAAE,MAAM,CAAE,EACrC,aAAa,EAAE,MAAM,CAAE,QAAQ,GAAG,OAAO,EAAE,MAAM,CAAE,MAAM,EAAE,YAAY,CAAE,CAAE,EAC3E,UAAU,EAAE,MAAM,CAAE,MAAM,EAAE,KAAK,CAAE,EACnC,YAAY,EAAE,MAAM,CAAE,QAAQ,GAAG,OAAO,EAAE,MAAM,CAAE,MAAM,EAAE,WAAW,CAAE,CAAE,GACvE,OAAO,CAAE,IAAI,CAAE,CAqDjB;AAED,eAAe,UAAU,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wordpress/asset-loader",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Utility to dynamically load WordPress scripts and styles with dependency resolution.",
|
|
5
|
+
"author": "The WordPress Contributors",
|
|
6
|
+
"license": "GPL-2.0-or-later",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"wordpress",
|
|
9
|
+
"gutenberg",
|
|
10
|
+
"assets",
|
|
11
|
+
"scripts",
|
|
12
|
+
"styles",
|
|
13
|
+
"loader"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/WordPress/gutenberg/tree/HEAD/packages/asset-loader/README.md",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/WordPress/gutenberg.git",
|
|
19
|
+
"directory": "packages/asset-loader"
|
|
20
|
+
},
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/WordPress/gutenberg/issues"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18.12.0",
|
|
26
|
+
"npm": ">=8.19.2"
|
|
27
|
+
},
|
|
28
|
+
"main": "build/index.js",
|
|
29
|
+
"module": "build-module/index.js",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./build-types/index.d.ts",
|
|
33
|
+
"import": "./build-module/index.js",
|
|
34
|
+
"default": "./build/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"react-native": "src/index",
|
|
39
|
+
"types": "build-types",
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"gitHead": "77aa1f194edceafe8ac2a1b9438bf84b557e76e3"
|
|
44
|
+
}
|