@wordpress/interactivity-router 1.7.0 → 2.0.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/build/head.js +6 -5
- package/build/head.js.map +1 -1
- package/build/index.js +36 -28
- package/build/index.js.map +1 -1
- package/build-module/head.js +6 -5
- package/build-module/head.js.map +1 -1
- package/build-module/index.js +36 -28
- package/build-module/index.js.map +1 -1
- package/build-types/head.d.ts +22 -2
- package/build-types/head.d.ts.map +1 -1
- package/build-types/index.d.ts +40 -34
- package/build-types/index.d.ts.map +1 -1
- package/package.json +5 -4
- package/src/{head.js → head.ts} +17 -11
- package/src/{index.js → index.ts} +79 -44
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 2.0.0 (2024-05-31)
|
|
6
|
+
|
|
7
|
+
### Breaking Changes
|
|
8
|
+
|
|
9
|
+
- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)).
|
|
10
|
+
- Increase the minimum required Node.js version to v18.12.0 matching long-term support releases ([#31270](https://github.com/WordPress/gutenberg/pull/61930)). Learn more about [Node.js releases](https://nodejs.org/en/about/previous-releases).
|
|
11
|
+
|
|
12
|
+
## 1.8.0 (2024-05-16)
|
|
13
|
+
|
|
5
14
|
## 1.7.0 (2024-05-02)
|
|
6
15
|
|
|
7
16
|
## 1.6.0 (2024-04-19)
|
package/build/head.js
CHANGED
|
@@ -8,8 +8,7 @@ exports.updateHead = exports.fetchHeadAssets = void 0;
|
|
|
8
8
|
* Helper to update only the necessary tags in the head.
|
|
9
9
|
*
|
|
10
10
|
* @async
|
|
11
|
-
* @param
|
|
12
|
-
*
|
|
11
|
+
* @param newHead The head elements of the new page.
|
|
13
12
|
*/
|
|
14
13
|
const updateHead = async newHead => {
|
|
15
14
|
// Helper to get the tag id store in the cache.
|
|
@@ -47,10 +46,12 @@ const updateHead = async newHead => {
|
|
|
47
46
|
* Fetches and processes head assets (stylesheets and scripts) from a specified document.
|
|
48
47
|
*
|
|
49
48
|
* @async
|
|
50
|
-
* @param
|
|
51
|
-
* @param
|
|
49
|
+
* @param doc The document from which to fetch head assets. It should support standard DOM querying methods.
|
|
50
|
+
* @param headElements A map of head elements to modify tracking the URLs of already processed assets to avoid duplicates.
|
|
51
|
+
* @param headElements.tag
|
|
52
|
+
* @param headElements.text
|
|
52
53
|
*
|
|
53
|
-
* @return
|
|
54
|
+
* @return Returns an array of HTML elements representing the head assets.
|
|
54
55
|
*/
|
|
55
56
|
exports.updateHead = updateHead;
|
|
56
57
|
const fetchHeadAssets = async (doc, headElements) => {
|
package/build/head.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["updateHead","newHead","getTagId","tag","id","outerHTML","newHeadMap","Map","child","set","toRemove","document","head","children","nodeName","push","has","delete","toAppend","values","forEach","n","remove","append","exports","fetchHeadAssets","doc","headElements","headTags","assets","tagName","selector","attribute","asset","tags","querySelectorAll","Promise","all","Array","from","map","attributeValue","getAttribute","response","fetch","text","e","console","error","headElement","get","element","createElement","innerText","attr","attributes","setAttribute","name","value","querySelector"],"sources":["@wordpress/interactivity-router/src/head.
|
|
1
|
+
{"version":3,"names":["updateHead","newHead","getTagId","tag","id","outerHTML","newHeadMap","Map","child","set","toRemove","document","head","children","nodeName","push","has","delete","toAppend","values","forEach","n","remove","append","exports","fetchHeadAssets","doc","headElements","headTags","assets","tagName","selector","attribute","asset","tags","querySelectorAll","Promise","all","Array","from","map","attributeValue","getAttribute","response","fetch","text","e","console","error","headElement","get","element","createElement","innerText","attr","attributes","setAttribute","name","value","querySelector"],"sources":["@wordpress/interactivity-router/src/head.ts"],"sourcesContent":["/**\n * Helper to update only the necessary tags in the head.\n *\n * @async\n * @param newHead The head elements of the new page.\n */\nexport const updateHead = async ( newHead: HTMLHeadElement[] ) => {\n\t// Helper to get the tag id store in the cache.\n\tconst getTagId = ( tag: Element ) => tag.id || tag.outerHTML;\n\n\t// Map incoming head tags by their content.\n\tconst newHeadMap = new Map< string, Element >();\n\tfor ( const child of newHead ) {\n\t\tnewHeadMap.set( getTagId( child ), child );\n\t}\n\n\tconst toRemove: Element[] = [];\n\n\t// Detect nodes that should be added or removed.\n\tfor ( const child of document.head.children ) {\n\t\tconst id = getTagId( child );\n\t\t// Always remove styles and links as they might change.\n\t\tif ( child.nodeName === 'LINK' || child.nodeName === 'STYLE' ) {\n\t\t\ttoRemove.push( child );\n\t\t} else if ( newHeadMap.has( id ) ) {\n\t\t\tnewHeadMap.delete( id );\n\t\t} else if ( child.nodeName !== 'SCRIPT' && child.nodeName !== 'META' ) {\n\t\t\ttoRemove.push( child );\n\t\t}\n\t}\n\n\t// Prepare new assets.\n\tconst toAppend = [ ...newHeadMap.values() ];\n\n\t// Apply the changes.\n\ttoRemove.forEach( ( n ) => n.remove() );\n\tdocument.head.append( ...toAppend );\n};\n\n/**\n * Fetches and processes head assets (stylesheets and scripts) from a specified document.\n *\n * @async\n * @param doc The document from which to fetch head assets. It should support standard DOM querying methods.\n * @param headElements A map of head elements to modify tracking the URLs of already processed assets to avoid duplicates.\n * @param headElements.tag\n * @param headElements.text\n *\n * @return Returns an array of HTML elements representing the head assets.\n */\nexport const fetchHeadAssets = async (\n\tdoc: Document,\n\theadElements: Map< string, { tag: HTMLElement; text: string } >\n): Promise< HTMLElement[] > => {\n\tconst headTags = [];\n\tconst assets = [\n\t\t{\n\t\t\ttagName: 'style',\n\t\t\tselector: 'link[rel=stylesheet]',\n\t\t\tattribute: 'href',\n\t\t},\n\t\t{ tagName: 'script', selector: 'script[src]', attribute: 'src' },\n\t];\n\tfor ( const asset of assets ) {\n\t\tconst { tagName, selector, attribute } = asset;\n\t\tconst tags = doc.querySelectorAll<\n\t\t\tHTMLScriptElement | HTMLStyleElement\n\t\t>( selector );\n\n\t\t// Use Promise.all to wait for fetch to complete\n\t\tawait Promise.all(\n\t\t\tArray.from( tags ).map( async ( tag ) => {\n\t\t\t\tconst attributeValue = tag.getAttribute( attribute );\n\t\t\t\tif ( ! headElements.has( attributeValue ) ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await fetch( attributeValue );\n\t\t\t\t\t\tconst text = await response.text();\n\t\t\t\t\t\theadElements.set( attributeValue, {\n\t\t\t\t\t\t\ttag,\n\t\t\t\t\t\t\ttext,\n\t\t\t\t\t\t} );\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\t\tconsole.error( e );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst headElement = headElements.get( attributeValue );\n\t\t\t\tconst element = doc.createElement( tagName );\n\t\t\t\telement.innerText = headElement.text;\n\t\t\t\tfor ( const attr of headElement.tag.attributes ) {\n\t\t\t\t\telement.setAttribute( attr.name, attr.value );\n\t\t\t\t}\n\t\t\t\theadTags.push( element );\n\t\t\t} )\n\t\t);\n\t}\n\n\treturn [\n\t\tdoc.querySelector( 'title' ),\n\t\t...doc.querySelectorAll( 'style' ),\n\t\t...headTags,\n\t];\n};\n"],"mappings":"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","ignoreList":[]}
|
package/build/index.js
CHANGED
|
@@ -23,7 +23,6 @@ const {
|
|
|
23
23
|
populateInitialData,
|
|
24
24
|
batch
|
|
25
25
|
} = (0, _interactivity.privateApis)('I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WordPress.');
|
|
26
|
-
|
|
27
26
|
// Check if the navigation mode is full page or region based.
|
|
28
27
|
const navigationMode = (_getConfig$navigation = (0, _interactivity.getConfig)('core/router').navigationMode) !== null && _getConfig$navigation !== void 0 ? _getConfig$navigation : 'regionBased';
|
|
29
28
|
|
|
@@ -34,7 +33,7 @@ const headElements = new Map();
|
|
|
34
33
|
// Helper to remove domain and hash from the URL. We are only interesting in
|
|
35
34
|
// caching the path and the query.
|
|
36
35
|
const getPagePath = url => {
|
|
37
|
-
const u = new URL(url, window.location);
|
|
36
|
+
const u = new URL(url, window.location.href);
|
|
38
37
|
return u.pathname + u.search;
|
|
39
38
|
};
|
|
40
39
|
|
|
@@ -62,9 +61,11 @@ const fetchPage = async (url, {
|
|
|
62
61
|
const regionsToVdom = async (dom, {
|
|
63
62
|
vdom
|
|
64
63
|
} = {}) => {
|
|
65
|
-
const regions = {
|
|
64
|
+
const regions = {
|
|
65
|
+
body: undefined
|
|
66
|
+
};
|
|
66
67
|
let head;
|
|
67
|
-
if (
|
|
68
|
+
if (globalThis.IS_GUTENBERG_PLUGIN) {
|
|
68
69
|
if (navigationMode === 'fullPage') {
|
|
69
70
|
head = await (0, _head.fetchHeadAssets)(dom, headElements);
|
|
70
71
|
regions.body = vdom ? vdom.get(document.body) : toVdom(dom.body);
|
|
@@ -90,7 +91,7 @@ const regionsToVdom = async (dom, {
|
|
|
90
91
|
// Render all interactive regions contained in the given page.
|
|
91
92
|
const renderRegions = page => {
|
|
92
93
|
batch(() => {
|
|
93
|
-
if (
|
|
94
|
+
if (globalThis.IS_GUTENBERG_PLUGIN) {
|
|
94
95
|
if (navigationMode === 'fullPage') {
|
|
95
96
|
// Once this code is tested and more mature, the head should be updated for region based navigation as well.
|
|
96
97
|
(0, _head.updateHead)(page.head);
|
|
@@ -120,8 +121,8 @@ const renderRegions = page => {
|
|
|
120
121
|
* potential feedback indicating that the navigation has finished while the new
|
|
121
122
|
* page is being loaded.
|
|
122
123
|
*
|
|
123
|
-
* @param
|
|
124
|
-
* @return
|
|
124
|
+
* @param href The page href.
|
|
125
|
+
* @return Promise that never resolves.
|
|
125
126
|
*/
|
|
126
127
|
const forcePageReload = href => {
|
|
127
128
|
window.location.assign(href);
|
|
@@ -131,7 +132,7 @@ const forcePageReload = href => {
|
|
|
131
132
|
// Listen to the back and forward buttons and restore the page if it's in the
|
|
132
133
|
// cache.
|
|
133
134
|
window.addEventListener('popstate', async () => {
|
|
134
|
-
const pagePath = getPagePath(window.location); // Remove hash.
|
|
135
|
+
const pagePath = getPagePath(window.location.href); // Remove hash.
|
|
135
136
|
const page = pages.has(pagePath) && (await pages.get(pagePath));
|
|
136
137
|
if (page) {
|
|
137
138
|
renderRegions(page);
|
|
@@ -143,8 +144,9 @@ window.addEventListener('popstate', async () => {
|
|
|
143
144
|
});
|
|
144
145
|
|
|
145
146
|
// Initialize the router and cache the initial page using the initial vDOM.
|
|
146
|
-
// Once this code is tested and more mature, the head should be updated for
|
|
147
|
-
|
|
147
|
+
// Once this code is tested and more mature, the head should be updated for
|
|
148
|
+
// region based navigation as well.
|
|
149
|
+
if (globalThis.IS_GUTENBERG_PLUGIN) {
|
|
148
150
|
if (navigationMode === 'fullPage') {
|
|
149
151
|
// Cache the scripts. Has to be called before fetching the assets.
|
|
150
152
|
[].map.call(document.querySelectorAll('script[src]'), script => {
|
|
@@ -156,7 +158,7 @@ if (process.env.IS_GUTENBERG_PLUGIN) {
|
|
|
156
158
|
await (0, _head.fetchHeadAssets)(document, headElements);
|
|
157
159
|
}
|
|
158
160
|
}
|
|
159
|
-
pages.set(getPagePath(window.location), Promise.resolve(regionsToVdom(document, {
|
|
161
|
+
pages.set(getPagePath(window.location.href), Promise.resolve(regionsToVdom(document, {
|
|
160
162
|
vdom: initialVdom
|
|
161
163
|
})));
|
|
162
164
|
|
|
@@ -185,7 +187,11 @@ const {
|
|
|
185
187
|
navigation: {
|
|
186
188
|
hasStarted: false,
|
|
187
189
|
hasFinished: false,
|
|
188
|
-
texts: {
|
|
190
|
+
texts: {
|
|
191
|
+
loading: '',
|
|
192
|
+
loaded: ''
|
|
193
|
+
},
|
|
194
|
+
message: ''
|
|
189
195
|
}
|
|
190
196
|
},
|
|
191
197
|
actions: {
|
|
@@ -196,16 +202,16 @@ const {
|
|
|
196
202
|
* needed, and updates any interactive regions whose contents have
|
|
197
203
|
* changed. It also creates a new entry in the browser session history.
|
|
198
204
|
*
|
|
199
|
-
* @param
|
|
200
|
-
* @param
|
|
201
|
-
* @param
|
|
202
|
-
* @param
|
|
203
|
-
* @param
|
|
204
|
-
* @param
|
|
205
|
-
* @param
|
|
206
|
-
* @param
|
|
205
|
+
* @param href The page href.
|
|
206
|
+
* @param [options] Options object.
|
|
207
|
+
* @param [options.force] If true, it forces re-fetching the URL.
|
|
208
|
+
* @param [options.html] HTML string to be used instead of fetching the requested URL.
|
|
209
|
+
* @param [options.replace] If true, it replaces the current entry in the browser session history.
|
|
210
|
+
* @param [options.timeout] Time until the navigation is aborted, in milliseconds. Default is 10000.
|
|
211
|
+
* @param [options.loadingAnimation] Whether an animation should be shown while navigating. Default to `true`.
|
|
212
|
+
* @param [options.screenReaderAnnouncement] Whether a message for screen readers should be announced while navigating. Default to `true`.
|
|
207
213
|
*
|
|
208
|
-
* @return
|
|
214
|
+
* @return Promise that resolves once the navigation is completed or aborted.
|
|
209
215
|
*/
|
|
210
216
|
*navigate(href, options = {}) {
|
|
211
217
|
const {
|
|
@@ -277,7 +283,7 @@ const {
|
|
|
277
283
|
// Scroll to the anchor if exits in the link.
|
|
278
284
|
const {
|
|
279
285
|
hash
|
|
280
|
-
} = new URL(href, window.location);
|
|
286
|
+
} = new URL(href, window.location.href);
|
|
281
287
|
if (hash) {
|
|
282
288
|
document.querySelector(hash)?.scrollIntoView();
|
|
283
289
|
}
|
|
@@ -291,10 +297,10 @@ const {
|
|
|
291
297
|
* The function normalizes the URL and stores internally the fetch
|
|
292
298
|
* promise, to avoid triggering a second fetch for an ongoing request.
|
|
293
299
|
*
|
|
294
|
-
* @param
|
|
295
|
-
* @param
|
|
296
|
-
* @param
|
|
297
|
-
* @param
|
|
300
|
+
* @param url The page URL.
|
|
301
|
+
* @param [options] Options object.
|
|
302
|
+
* @param [options.force] Force fetching the URL again.
|
|
303
|
+
* @param [options.html] HTML string to be used instead of fetching the requested URL.
|
|
298
304
|
*/
|
|
299
305
|
prefetch(url, options = {}) {
|
|
300
306
|
const {
|
|
@@ -305,7 +311,9 @@ const {
|
|
|
305
311
|
}
|
|
306
312
|
const pagePath = getPagePath(url);
|
|
307
313
|
if (options.force || !pages.has(pagePath)) {
|
|
308
|
-
pages.set(pagePath, fetchPage(pagePath,
|
|
314
|
+
pages.set(pagePath, fetchPage(pagePath, {
|
|
315
|
+
html: options.html
|
|
316
|
+
}));
|
|
309
317
|
}
|
|
310
318
|
}
|
|
311
319
|
}
|
|
@@ -314,7 +322,7 @@ const {
|
|
|
314
322
|
// Add click and prefetch to all links.
|
|
315
323
|
exports.actions = actions;
|
|
316
324
|
exports.state = state;
|
|
317
|
-
if (
|
|
325
|
+
if (globalThis.IS_GUTENBERG_PLUGIN) {
|
|
318
326
|
if (navigationMode === 'fullPage') {
|
|
319
327
|
// Navigate on click.
|
|
320
328
|
document.addEventListener('click', function (event) {
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_interactivity","require","_head","_getConfig$navigation","directivePrefix","getRegionRootFragment","initialVdom","toVdom","render","parseInitialData","populateInitialData","batch","privateApis","navigationMode","getConfig","pages","Map","headElements","getPagePath","url","u","URL","window","location","pathname","search","fetchPage","html","res","fetch","status","text","dom","DOMParser","parseFromString","regionsToVdom","e","vdom","regions","head","process","env","IS_GUTENBERG_PLUGIN","fetchHeadAssets","body","get","document","attrName","querySelectorAll","forEach","region","id","getAttribute","has","title","querySelector","innerText","initialData","renderRegions","page","updateHead","fragment","forcePageReload","href","assign","Promise","addEventListener","pagePath","state","reload","map","call","script","set","tag","textContent","resolve","isValidLink","ref","HTMLAnchorElement","target","origin","startsWith","searchParams","isValidEvent","event","button","metaKey","ctrlKey","altKey","shiftKey","defaultPrevented","navigatingTo","actions","store","navigation","hasStarted","hasFinished","texts","navigate","options","clientNavigationDisabled","loadingAnimation","screenReaderAnnouncement","timeout","prefetch","timeoutPromise","setTimeout","loadingTimeout","message","loading","race","clearTimeout","config","history","replace","loaded","hash","scrollIntoView","force","exports","closest","preventDefault","nodeName"],"sources":["@wordpress/interactivity-router/src/index.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { store, privateApis, getConfig } from '@wordpress/interactivity';\n\n/**\n * Internal dependencies\n */\nimport { fetchHeadAssets, updateHead } from './head';\n\nconst {\n\tdirectivePrefix,\n\tgetRegionRootFragment,\n\tinitialVdom,\n\ttoVdom,\n\trender,\n\tparseInitialData,\n\tpopulateInitialData,\n\tbatch,\n} = privateApis(\n\t'I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WordPress.'\n);\n\n// Check if the navigation mode is full page or region based.\nconst navigationMode =\n\tgetConfig( 'core/router' ).navigationMode ?? 'regionBased';\n\n// The cache of visited and prefetched pages, stylesheets and scripts.\nconst pages = new Map();\nconst headElements = new Map();\n\n// Helper to remove domain and hash from the URL. We are only interesting in\n// caching the path and the query.\nconst getPagePath = ( url ) => {\n\tconst u = new URL( url, window.location );\n\treturn u.pathname + u.search;\n};\n\n// Fetch a new page and convert it to a static virtual DOM.\nconst fetchPage = async ( url, { html } ) => {\n\ttry {\n\t\tif ( ! html ) {\n\t\t\tconst res = await window.fetch( url );\n\t\t\tif ( res.status !== 200 ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\thtml = await res.text();\n\t\t}\n\t\tconst dom = new window.DOMParser().parseFromString( html, 'text/html' );\n\t\treturn regionsToVdom( dom );\n\t} catch ( e ) {\n\t\treturn false;\n\t}\n};\n\n// Return an object with VDOM trees of those HTML regions marked with a\n// `router-region` directive.\nconst regionsToVdom = async ( dom, { vdom } = {} ) => {\n\tconst regions = {};\n\tlet head;\n\tif ( process.env.IS_GUTENBERG_PLUGIN ) {\n\t\tif ( navigationMode === 'fullPage' ) {\n\t\t\thead = await fetchHeadAssets( dom, headElements );\n\t\t\tregions.body = vdom\n\t\t\t\t? vdom.get( document.body )\n\t\t\t\t: toVdom( dom.body );\n\t\t}\n\t}\n\tif ( navigationMode === 'regionBased' ) {\n\t\tconst attrName = `data-${ directivePrefix }-router-region`;\n\t\tdom.querySelectorAll( `[${ attrName }]` ).forEach( ( region ) => {\n\t\t\tconst id = region.getAttribute( attrName );\n\t\t\tregions[ id ] = vdom?.has( region )\n\t\t\t\t? vdom.get( region )\n\t\t\t\t: toVdom( region );\n\t\t} );\n\t}\n\tconst title = dom.querySelector( 'title' )?.innerText;\n\tconst initialData = parseInitialData( dom );\n\treturn { regions, head, title, initialData };\n};\n\n// Render all interactive regions contained in the given page.\nconst renderRegions = ( page ) => {\n\tbatch( () => {\n\t\tif ( process.env.IS_GUTENBERG_PLUGIN ) {\n\t\t\tif ( navigationMode === 'fullPage' ) {\n\t\t\t\t// Once this code is tested and more mature, the head should be updated for region based navigation as well.\n\t\t\t\tupdateHead( page.head );\n\t\t\t\tconst fragment = getRegionRootFragment( document.body );\n\t\t\t\trender( page.regions.body, fragment );\n\t\t\t}\n\t\t}\n\t\tif ( navigationMode === 'regionBased' ) {\n\t\t\tpopulateInitialData( page.initialData );\n\t\t\tconst attrName = `data-${ directivePrefix }-router-region`;\n\t\t\tdocument\n\t\t\t\t.querySelectorAll( `[${ attrName }]` )\n\t\t\t\t.forEach( ( region ) => {\n\t\t\t\t\tconst id = region.getAttribute( attrName );\n\t\t\t\t\tconst fragment = getRegionRootFragment( region );\n\t\t\t\t\trender( page.regions[ id ], fragment );\n\t\t\t\t} );\n\t\t}\n\t\tif ( page.title ) {\n\t\t\tdocument.title = page.title;\n\t\t}\n\t} );\n};\n\n/**\n * Load the given page forcing a full page reload.\n *\n * The function returns a promise that won't resolve, useful to prevent any\n * potential feedback indicating that the navigation has finished while the new\n * page is being loaded.\n *\n * @param {string} href The page href.\n * @return {Promise} Promise that never resolves.\n */\nconst forcePageReload = ( href ) => {\n\twindow.location.assign( href );\n\treturn new Promise( () => {} );\n};\n\n// Listen to the back and forward buttons and restore the page if it's in the\n// cache.\nwindow.addEventListener( 'popstate', async () => {\n\tconst pagePath = getPagePath( window.location ); // Remove hash.\n\tconst page = pages.has( pagePath ) && ( await pages.get( pagePath ) );\n\tif ( page ) {\n\t\trenderRegions( page );\n\t\t// Update the URL in the state.\n\t\tstate.url = window.location.href;\n\t} else {\n\t\twindow.location.reload();\n\t}\n} );\n\n// Initialize the router and cache the initial page using the initial vDOM.\n// Once this code is tested and more mature, the head should be updated for region based navigation as well.\nif ( process.env.IS_GUTENBERG_PLUGIN ) {\n\tif ( navigationMode === 'fullPage' ) {\n\t\t// Cache the scripts. Has to be called before fetching the assets.\n\t\t[].map.call( document.querySelectorAll( 'script[src]' ), ( script ) => {\n\t\t\theadElements.set( script.getAttribute( 'src' ), {\n\t\t\t\ttag: script,\n\t\t\t\ttext: script.textContent,\n\t\t\t} );\n\t\t} );\n\t\tawait fetchHeadAssets( document, headElements );\n\t}\n}\npages.set(\n\tgetPagePath( window.location ),\n\tPromise.resolve( regionsToVdom( document, { vdom: initialVdom } ) )\n);\n\n// Check if the link is valid for client-side navigation.\nconst isValidLink = ( ref ) =>\n\tref &&\n\tref instanceof window.HTMLAnchorElement &&\n\tref.href &&\n\t( ! ref.target || ref.target === '_self' ) &&\n\tref.origin === window.location.origin &&\n\t! ref.pathname.startsWith( '/wp-admin' ) &&\n\t! ref.pathname.startsWith( '/wp-login.php' ) &&\n\t! ref.getAttribute( 'href' ).startsWith( '#' ) &&\n\t! new URL( ref.href ).searchParams.has( '_wpnonce' );\n\n// Check if the event is valid for client-side navigation.\nconst isValidEvent = ( event ) =>\n\tevent &&\n\tevent.button === 0 && // Left clicks only.\n\t! event.metaKey && // Open in new tab (Mac).\n\t! event.ctrlKey && // Open in new tab (Windows).\n\t! event.altKey && // Download.\n\t! event.shiftKey &&\n\t! event.defaultPrevented;\n\n// Variable to store the current navigation.\nlet navigatingTo = '';\n\nexport const { state, actions } = store( 'core/router', {\n\tstate: {\n\t\turl: window.location.href,\n\t\tnavigation: {\n\t\t\thasStarted: false,\n\t\t\thasFinished: false,\n\t\t\ttexts: {},\n\t\t},\n\t},\n\tactions: {\n\t\t/**\n\t\t * Navigates to the specified page.\n\t\t *\n\t\t * This function normalizes the passed href, fetchs the page HTML if\n\t\t * needed, and updates any interactive regions whose contents have\n\t\t * changed. It also creates a new entry in the browser session history.\n\t\t *\n\t\t * @param {string} href The page href.\n\t\t * @param {Object} [options] Options object.\n\t\t * @param {boolean} [options.force] If true, it forces re-fetching the URL.\n\t\t * @param {string} [options.html] HTML string to be used instead of fetching the requested URL.\n\t\t * @param {boolean} [options.replace] If true, it replaces the current entry in the browser session history.\n\t\t * @param {number} [options.timeout] Time until the navigation is aborted, in milliseconds. Default is 10000.\n\t\t * @param {boolean} [options.loadingAnimation] Whether an animation should be shown while navigating. Default to `true`.\n\t\t * @param {boolean} [options.screenReaderAnnouncement] Whether a message for screen readers should be announced while navigating. Default to `true`.\n\t\t *\n\t\t * @return {Promise} Promise that resolves once the navigation is completed or aborted.\n\t\t */\n\t\t*navigate( href, options = {} ) {\n\t\t\tconst { clientNavigationDisabled } = getConfig();\n\t\t\tif ( clientNavigationDisabled ) {\n\t\t\t\tyield forcePageReload( href );\n\t\t\t}\n\n\t\t\tconst pagePath = getPagePath( href );\n\t\t\tconst { navigation } = state;\n\t\t\tconst {\n\t\t\t\tloadingAnimation = true,\n\t\t\t\tscreenReaderAnnouncement = true,\n\t\t\t\ttimeout = 10000,\n\t\t\t} = options;\n\n\t\t\tnavigatingTo = href;\n\t\t\tactions.prefetch( pagePath, options );\n\n\t\t\t// Create a promise that resolves when the specified timeout ends.\n\t\t\t// The timeout value is 10 seconds by default.\n\t\t\tconst timeoutPromise = new Promise( ( resolve ) =>\n\t\t\t\tsetTimeout( resolve, timeout )\n\t\t\t);\n\n\t\t\t// Don't update the navigation status immediately, wait 400 ms.\n\t\t\tconst loadingTimeout = setTimeout( () => {\n\t\t\t\tif ( navigatingTo !== href ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( loadingAnimation ) {\n\t\t\t\t\tnavigation.hasStarted = true;\n\t\t\t\t\tnavigation.hasFinished = false;\n\t\t\t\t}\n\t\t\t\tif ( screenReaderAnnouncement ) {\n\t\t\t\t\tnavigation.message = navigation.texts.loading;\n\t\t\t\t}\n\t\t\t}, 400 );\n\n\t\t\tconst page = yield Promise.race( [\n\t\t\t\tpages.get( pagePath ),\n\t\t\t\ttimeoutPromise,\n\t\t\t] );\n\n\t\t\t// Dismiss loading message if it hasn't been added yet.\n\t\t\tclearTimeout( loadingTimeout );\n\n\t\t\t// Once the page is fetched, the destination URL could have changed\n\t\t\t// (e.g., by clicking another link in the meantime). If so, bail\n\t\t\t// out, and let the newer execution to update the HTML.\n\t\t\tif ( navigatingTo !== href ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tpage &&\n\t\t\t\t! page.initialData?.config?.[ 'core/router' ]\n\t\t\t\t\t?.clientNavigationDisabled\n\t\t\t) {\n\t\t\t\tyield renderRegions( page );\n\t\t\t\twindow.history[\n\t\t\t\t\toptions.replace ? 'replaceState' : 'pushState'\n\t\t\t\t]( {}, '', href );\n\n\t\t\t\t// Update the URL in the state.\n\t\t\t\tstate.url = href;\n\n\t\t\t\t// Update the navigation status once the the new page rendering\n\t\t\t\t// has been completed.\n\t\t\t\tif ( loadingAnimation ) {\n\t\t\t\t\tnavigation.hasStarted = false;\n\t\t\t\t\tnavigation.hasFinished = true;\n\t\t\t\t}\n\n\t\t\t\tif ( screenReaderAnnouncement ) {\n\t\t\t\t\t// Announce that the page has been loaded. If the message is the\n\t\t\t\t\t// same, we use a no-break space similar to the @wordpress/a11y\n\t\t\t\t\t// package: https://github.com/WordPress/gutenberg/blob/c395242b8e6ee20f8b06c199e4fc2920d7018af1/packages/a11y/src/filter-message.js#L20-L26\n\t\t\t\t\tnavigation.message =\n\t\t\t\t\t\tnavigation.texts.loaded +\n\t\t\t\t\t\t( navigation.message === navigation.texts.loaded\n\t\t\t\t\t\t\t? '\\u00A0'\n\t\t\t\t\t\t\t: '' );\n\t\t\t\t}\n\n\t\t\t\t// Scroll to the anchor if exits in the link.\n\t\t\t\tconst { hash } = new URL( href, window.location );\n\t\t\t\tif ( hash ) {\n\t\t\t\t\tdocument.querySelector( hash )?.scrollIntoView();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tyield forcePageReload( href );\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Prefetchs the page with the passed URL.\n\t\t *\n\t\t * The function normalizes the URL and stores internally the fetch\n\t\t * promise, to avoid triggering a second fetch for an ongoing request.\n\t\t *\n\t\t * @param {string} url The page URL.\n\t\t * @param {Object} [options] Options object.\n\t\t * @param {boolean} [options.force] Force fetching the URL again.\n\t\t * @param {string} [options.html] HTML string to be used instead of fetching the requested URL.\n\t\t */\n\t\tprefetch( url, options = {} ) {\n\t\t\tconst { clientNavigationDisabled } = getConfig();\n\t\t\tif ( clientNavigationDisabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst pagePath = getPagePath( url );\n\t\t\tif ( options.force || ! pages.has( pagePath ) ) {\n\t\t\t\tpages.set( pagePath, fetchPage( pagePath, options ) );\n\t\t\t}\n\t\t},\n\t},\n} );\n\n// Add click and prefetch to all links.\nif ( process.env.IS_GUTENBERG_PLUGIN ) {\n\tif ( navigationMode === 'fullPage' ) {\n\t\t// Navigate on click.\n\t\tdocument.addEventListener(\n\t\t\t'click',\n\t\t\tfunction ( event ) {\n\t\t\t\tconst ref = event.target.closest( 'a' );\n\t\t\t\tif ( isValidLink( ref ) && isValidEvent( event ) ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tactions.navigate( ref.href );\n\t\t\t\t}\n\t\t\t},\n\t\t\ttrue\n\t\t);\n\t\t// Prefetch on hover.\n\t\tdocument.addEventListener(\n\t\t\t'mouseenter',\n\t\t\tfunction ( event ) {\n\t\t\t\tif ( event.target?.nodeName === 'A' ) {\n\t\t\t\t\tconst ref = event.target.closest( 'a' );\n\t\t\t\t\tif ( isValidLink( ref ) && isValidEvent( event ) ) {\n\t\t\t\t\t\tactions.prefetch( ref.href );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\ttrue\n\t\t);\n\t}\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_interactivity","require","_head","_getConfig$navigation","directivePrefix","getRegionRootFragment","initialVdom","toVdom","render","parseInitialData","populateInitialData","batch","privateApis","navigationMode","getConfig","pages","Map","headElements","getPagePath","url","u","URL","window","location","href","pathname","search","fetchPage","html","res","fetch","status","text","dom","DOMParser","parseFromString","regionsToVdom","e","vdom","regions","body","undefined","head","globalThis","IS_GUTENBERG_PLUGIN","fetchHeadAssets","get","document","attrName","querySelectorAll","forEach","region","id","getAttribute","has","title","querySelector","innerText","initialData","renderRegions","page","updateHead","fragment","forcePageReload","assign","Promise","addEventListener","pagePath","state","reload","map","call","script","set","tag","textContent","resolve","isValidLink","ref","HTMLAnchorElement","target","origin","startsWith","searchParams","isValidEvent","event","button","metaKey","ctrlKey","altKey","shiftKey","defaultPrevented","navigatingTo","actions","store","navigation","hasStarted","hasFinished","texts","loading","loaded","message","navigate","options","clientNavigationDisabled","loadingAnimation","screenReaderAnnouncement","timeout","prefetch","timeoutPromise","setTimeout","loadingTimeout","race","clearTimeout","config","history","replace","hash","scrollIntoView","force","exports","closest","preventDefault","nodeName"],"sources":["@wordpress/interactivity-router/src/index.ts"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { store, privateApis, getConfig } from '@wordpress/interactivity';\n\n/**\n * Internal dependencies\n */\nimport { fetchHeadAssets, updateHead } from './head';\n\nconst {\n\tdirectivePrefix,\n\tgetRegionRootFragment,\n\tinitialVdom,\n\ttoVdom,\n\trender,\n\tparseInitialData,\n\tpopulateInitialData,\n\tbatch,\n} = privateApis(\n\t'I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WordPress.'\n);\n\ninterface NavigateOptions {\n\tforce?: boolean;\n\thtml?: string;\n\treplace?: boolean;\n\ttimeout?: number;\n\tloadingAnimation?: boolean;\n\tscreenReaderAnnouncement?: boolean;\n}\n\ninterface PrefetchOptions {\n\tforce?: boolean;\n\thtml?: string;\n}\n\ninterface VdomParams {\n\tvdom?: typeof initialVdom;\n}\n\ninterface Page {\n\tregions: Record< string, any >;\n\thead: HTMLHeadElement[];\n\ttitle: string;\n\tinitialData: any;\n}\n\ntype RegionsToVdom = ( dom: Document, params?: VdomParams ) => Promise< Page >;\n\n// Check if the navigation mode is full page or region based.\nconst navigationMode: 'regionBased' | 'fullPage' =\n\tgetConfig( 'core/router' ).navigationMode ?? 'regionBased';\n\n// The cache of visited and prefetched pages, stylesheets and scripts.\nconst pages = new Map< string, Promise< Page | false > >();\nconst headElements = new Map< string, { tag: HTMLElement; text: string } >();\n\n// Helper to remove domain and hash from the URL. We are only interesting in\n// caching the path and the query.\nconst getPagePath = ( url: string ) => {\n\tconst u = new URL( url, window.location.href );\n\treturn u.pathname + u.search;\n};\n\n// Fetch a new page and convert it to a static virtual DOM.\nconst fetchPage = async ( url: string, { html }: { html: string } ) => {\n\ttry {\n\t\tif ( ! html ) {\n\t\t\tconst res = await window.fetch( url );\n\t\t\tif ( res.status !== 200 ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\thtml = await res.text();\n\t\t}\n\t\tconst dom = new window.DOMParser().parseFromString( html, 'text/html' );\n\t\treturn regionsToVdom( dom );\n\t} catch ( e ) {\n\t\treturn false;\n\t}\n};\n\n// Return an object with VDOM trees of those HTML regions marked with a\n// `router-region` directive.\nconst regionsToVdom: RegionsToVdom = async ( dom, { vdom } = {} ) => {\n\tconst regions = { body: undefined };\n\tlet head: HTMLElement[];\n\tif ( globalThis.IS_GUTENBERG_PLUGIN ) {\n\t\tif ( navigationMode === 'fullPage' ) {\n\t\t\thead = await fetchHeadAssets( dom, headElements );\n\t\t\tregions.body = vdom\n\t\t\t\t? vdom.get( document.body )\n\t\t\t\t: toVdom( dom.body );\n\t\t}\n\t}\n\tif ( navigationMode === 'regionBased' ) {\n\t\tconst attrName = `data-${ directivePrefix }-router-region`;\n\t\tdom.querySelectorAll( `[${ attrName }]` ).forEach( ( region ) => {\n\t\t\tconst id = region.getAttribute( attrName );\n\t\t\tregions[ id ] = vdom?.has( region )\n\t\t\t\t? vdom.get( region )\n\t\t\t\t: toVdom( region );\n\t\t} );\n\t}\n\tconst title = dom.querySelector( 'title' )?.innerText;\n\tconst initialData = parseInitialData( dom );\n\treturn { regions, head, title, initialData };\n};\n\n// Render all interactive regions contained in the given page.\nconst renderRegions = ( page: Page ) => {\n\tbatch( () => {\n\t\tif ( globalThis.IS_GUTENBERG_PLUGIN ) {\n\t\t\tif ( navigationMode === 'fullPage' ) {\n\t\t\t\t// Once this code is tested and more mature, the head should be updated for region based navigation as well.\n\t\t\t\tupdateHead( page.head );\n\t\t\t\tconst fragment = getRegionRootFragment( document.body );\n\t\t\t\trender( page.regions.body, fragment );\n\t\t\t}\n\t\t}\n\t\tif ( navigationMode === 'regionBased' ) {\n\t\t\tpopulateInitialData( page.initialData );\n\t\t\tconst attrName = `data-${ directivePrefix }-router-region`;\n\t\t\tdocument\n\t\t\t\t.querySelectorAll( `[${ attrName }]` )\n\t\t\t\t.forEach( ( region ) => {\n\t\t\t\t\tconst id = region.getAttribute( attrName );\n\t\t\t\t\tconst fragment = getRegionRootFragment( region );\n\t\t\t\t\trender( page.regions[ id ], fragment );\n\t\t\t\t} );\n\t\t}\n\t\tif ( page.title ) {\n\t\t\tdocument.title = page.title;\n\t\t}\n\t} );\n};\n\n/**\n * Load the given page forcing a full page reload.\n *\n * The function returns a promise that won't resolve, useful to prevent any\n * potential feedback indicating that the navigation has finished while the new\n * page is being loaded.\n *\n * @param href The page href.\n * @return Promise that never resolves.\n */\nconst forcePageReload = ( href: string ) => {\n\twindow.location.assign( href );\n\treturn new Promise( () => {} );\n};\n\n// Listen to the back and forward buttons and restore the page if it's in the\n// cache.\nwindow.addEventListener( 'popstate', async () => {\n\tconst pagePath = getPagePath( window.location.href ); // Remove hash.\n\tconst page = pages.has( pagePath ) && ( await pages.get( pagePath ) );\n\tif ( page ) {\n\t\trenderRegions( page );\n\t\t// Update the URL in the state.\n\t\tstate.url = window.location.href;\n\t} else {\n\t\twindow.location.reload();\n\t}\n} );\n\n// Initialize the router and cache the initial page using the initial vDOM.\n// Once this code is tested and more mature, the head should be updated for\n// region based navigation as well.\nif ( globalThis.IS_GUTENBERG_PLUGIN ) {\n\tif ( navigationMode === 'fullPage' ) {\n\t\t// Cache the scripts. Has to be called before fetching the assets.\n\t\t[].map.call( document.querySelectorAll( 'script[src]' ), ( script ) => {\n\t\t\theadElements.set( script.getAttribute( 'src' ), {\n\t\t\t\ttag: script,\n\t\t\t\ttext: script.textContent,\n\t\t\t} );\n\t\t} );\n\t\tawait fetchHeadAssets( document, headElements );\n\t}\n}\npages.set(\n\tgetPagePath( window.location.href ),\n\tPromise.resolve( regionsToVdom( document, { vdom: initialVdom } ) )\n);\n\n// Check if the link is valid for client-side navigation.\nconst isValidLink = ( ref: HTMLAnchorElement ) =>\n\tref &&\n\tref instanceof window.HTMLAnchorElement &&\n\tref.href &&\n\t( ! ref.target || ref.target === '_self' ) &&\n\tref.origin === window.location.origin &&\n\t! ref.pathname.startsWith( '/wp-admin' ) &&\n\t! ref.pathname.startsWith( '/wp-login.php' ) &&\n\t! ref.getAttribute( 'href' ).startsWith( '#' ) &&\n\t! new URL( ref.href ).searchParams.has( '_wpnonce' );\n\n// Check if the event is valid for client-side navigation.\nconst isValidEvent = ( event: MouseEvent ) =>\n\tevent &&\n\tevent.button === 0 && // Left clicks only.\n\t! event.metaKey && // Open in new tab (Mac).\n\t! event.ctrlKey && // Open in new tab (Windows).\n\t! event.altKey && // Download.\n\t! event.shiftKey &&\n\t! event.defaultPrevented;\n\n// Variable to store the current navigation.\nlet navigatingTo = '';\n\nexport const { state, actions } = store( 'core/router', {\n\tstate: {\n\t\turl: window.location.href,\n\t\tnavigation: {\n\t\t\thasStarted: false,\n\t\t\thasFinished: false,\n\t\t\ttexts: {\n\t\t\t\tloading: '',\n\t\t\t\tloaded: '',\n\t\t\t},\n\t\t\tmessage: '',\n\t\t},\n\t},\n\tactions: {\n\t\t/**\n\t\t * Navigates to the specified page.\n\t\t *\n\t\t * This function normalizes the passed href, fetchs the page HTML if\n\t\t * needed, and updates any interactive regions whose contents have\n\t\t * changed. It also creates a new entry in the browser session history.\n\t\t *\n\t\t * @param href The page href.\n\t\t * @param [options] Options object.\n\t\t * @param [options.force] If true, it forces re-fetching the URL.\n\t\t * @param [options.html] HTML string to be used instead of fetching the requested URL.\n\t\t * @param [options.replace] If true, it replaces the current entry in the browser session history.\n\t\t * @param [options.timeout] Time until the navigation is aborted, in milliseconds. Default is 10000.\n\t\t * @param [options.loadingAnimation] Whether an animation should be shown while navigating. Default to `true`.\n\t\t * @param [options.screenReaderAnnouncement] Whether a message for screen readers should be announced while navigating. Default to `true`.\n\t\t *\n\t\t * @return Promise that resolves once the navigation is completed or aborted.\n\t\t */\n\t\t*navigate( href: string, options: NavigateOptions = {} ) {\n\t\t\tconst { clientNavigationDisabled } = getConfig();\n\t\t\tif ( clientNavigationDisabled ) {\n\t\t\t\tyield forcePageReload( href );\n\t\t\t}\n\n\t\t\tconst pagePath = getPagePath( href );\n\t\t\tconst { navigation } = state;\n\t\t\tconst {\n\t\t\t\tloadingAnimation = true,\n\t\t\t\tscreenReaderAnnouncement = true,\n\t\t\t\ttimeout = 10000,\n\t\t\t} = options;\n\n\t\t\tnavigatingTo = href;\n\t\t\tactions.prefetch( pagePath, options );\n\n\t\t\t// Create a promise that resolves when the specified timeout ends.\n\t\t\t// The timeout value is 10 seconds by default.\n\t\t\tconst timeoutPromise = new Promise< void >( ( resolve ) =>\n\t\t\t\tsetTimeout( resolve, timeout )\n\t\t\t);\n\n\t\t\t// Don't update the navigation status immediately, wait 400 ms.\n\t\t\tconst loadingTimeout = setTimeout( () => {\n\t\t\t\tif ( navigatingTo !== href ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( loadingAnimation ) {\n\t\t\t\t\tnavigation.hasStarted = true;\n\t\t\t\t\tnavigation.hasFinished = false;\n\t\t\t\t}\n\t\t\t\tif ( screenReaderAnnouncement ) {\n\t\t\t\t\tnavigation.message = navigation.texts.loading;\n\t\t\t\t}\n\t\t\t}, 400 );\n\n\t\t\tconst page = yield Promise.race( [\n\t\t\t\tpages.get( pagePath ),\n\t\t\t\ttimeoutPromise,\n\t\t\t] );\n\n\t\t\t// Dismiss loading message if it hasn't been added yet.\n\t\t\tclearTimeout( loadingTimeout );\n\n\t\t\t// Once the page is fetched, the destination URL could have changed\n\t\t\t// (e.g., by clicking another link in the meantime). If so, bail\n\t\t\t// out, and let the newer execution to update the HTML.\n\t\t\tif ( navigatingTo !== href ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tpage &&\n\t\t\t\t! page.initialData?.config?.[ 'core/router' ]\n\t\t\t\t\t?.clientNavigationDisabled\n\t\t\t) {\n\t\t\t\tyield renderRegions( page );\n\t\t\t\twindow.history[\n\t\t\t\t\toptions.replace ? 'replaceState' : 'pushState'\n\t\t\t\t]( {}, '', href );\n\n\t\t\t\t// Update the URL in the state.\n\t\t\t\tstate.url = href;\n\n\t\t\t\t// Update the navigation status once the the new page rendering\n\t\t\t\t// has been completed.\n\t\t\t\tif ( loadingAnimation ) {\n\t\t\t\t\tnavigation.hasStarted = false;\n\t\t\t\t\tnavigation.hasFinished = true;\n\t\t\t\t}\n\n\t\t\t\tif ( screenReaderAnnouncement ) {\n\t\t\t\t\t// Announce that the page has been loaded. If the message is the\n\t\t\t\t\t// same, we use a no-break space similar to the @wordpress/a11y\n\t\t\t\t\t// package: https://github.com/WordPress/gutenberg/blob/c395242b8e6ee20f8b06c199e4fc2920d7018af1/packages/a11y/src/filter-message.js#L20-L26\n\t\t\t\t\tnavigation.message =\n\t\t\t\t\t\tnavigation.texts.loaded +\n\t\t\t\t\t\t( navigation.message === navigation.texts.loaded\n\t\t\t\t\t\t\t? '\\u00A0'\n\t\t\t\t\t\t\t: '' );\n\t\t\t\t}\n\n\t\t\t\t// Scroll to the anchor if exits in the link.\n\t\t\t\tconst { hash } = new URL( href, window.location.href );\n\t\t\t\tif ( hash ) {\n\t\t\t\t\tdocument.querySelector( hash )?.scrollIntoView();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tyield forcePageReload( href );\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Prefetchs the page with the passed URL.\n\t\t *\n\t\t * The function normalizes the URL and stores internally the fetch\n\t\t * promise, to avoid triggering a second fetch for an ongoing request.\n\t\t *\n\t\t * @param url The page URL.\n\t\t * @param [options] Options object.\n\t\t * @param [options.force] Force fetching the URL again.\n\t\t * @param [options.html] HTML string to be used instead of fetching the requested URL.\n\t\t */\n\t\tprefetch( url: string, options: PrefetchOptions = {} ) {\n\t\t\tconst { clientNavigationDisabled } = getConfig();\n\t\t\tif ( clientNavigationDisabled ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst pagePath = getPagePath( url );\n\t\t\tif ( options.force || ! pages.has( pagePath ) ) {\n\t\t\t\tpages.set(\n\t\t\t\t\tpagePath,\n\t\t\t\t\tfetchPage( pagePath, { html: options.html } )\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t},\n} );\n\n// Add click and prefetch to all links.\nif ( globalThis.IS_GUTENBERG_PLUGIN ) {\n\tif ( navigationMode === 'fullPage' ) {\n\t\t// Navigate on click.\n\t\tdocument.addEventListener(\n\t\t\t'click',\n\t\t\tfunction ( event ) {\n\t\t\t\tconst ref = ( event.target as Element ).closest( 'a' );\n\t\t\t\tif ( isValidLink( ref ) && isValidEvent( event ) ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\tactions.navigate( ref.href );\n\t\t\t\t}\n\t\t\t},\n\t\t\ttrue\n\t\t);\n\t\t// Prefetch on hover.\n\t\tdocument.addEventListener(\n\t\t\t'mouseenter',\n\t\t\tfunction ( event ) {\n\t\t\t\tif ( ( event.target as Element )?.nodeName === 'A' ) {\n\t\t\t\t\tconst ref = ( event.target as Element ).closest( 'a' );\n\t\t\t\t\tif ( isValidLink( ref ) && isValidEvent( event ) ) {\n\t\t\t\t\t\tactions.prefetch( ref.href );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\ttrue\n\t\t);\n\t}\n}\n"],"mappings":"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","ignoreList":[]}
|
package/build-module/head.js
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
* Helper to update only the necessary tags in the head.
|
|
3
3
|
*
|
|
4
4
|
* @async
|
|
5
|
-
* @param
|
|
6
|
-
*
|
|
5
|
+
* @param newHead The head elements of the new page.
|
|
7
6
|
*/
|
|
8
7
|
export const updateHead = async newHead => {
|
|
9
8
|
// Helper to get the tag id store in the cache.
|
|
@@ -41,10 +40,12 @@ export const updateHead = async newHead => {
|
|
|
41
40
|
* Fetches and processes head assets (stylesheets and scripts) from a specified document.
|
|
42
41
|
*
|
|
43
42
|
* @async
|
|
44
|
-
* @param
|
|
45
|
-
* @param
|
|
43
|
+
* @param doc The document from which to fetch head assets. It should support standard DOM querying methods.
|
|
44
|
+
* @param headElements A map of head elements to modify tracking the URLs of already processed assets to avoid duplicates.
|
|
45
|
+
* @param headElements.tag
|
|
46
|
+
* @param headElements.text
|
|
46
47
|
*
|
|
47
|
-
* @return
|
|
48
|
+
* @return Returns an array of HTML elements representing the head assets.
|
|
48
49
|
*/
|
|
49
50
|
export const fetchHeadAssets = async (doc, headElements) => {
|
|
50
51
|
const headTags = [];
|
package/build-module/head.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["updateHead","newHead","getTagId","tag","id","outerHTML","newHeadMap","Map","child","set","toRemove","document","head","children","nodeName","push","has","delete","toAppend","values","forEach","n","remove","append","fetchHeadAssets","doc","headElements","headTags","assets","tagName","selector","attribute","asset","tags","querySelectorAll","Promise","all","Array","from","map","attributeValue","getAttribute","response","fetch","text","e","console","error","headElement","get","element","createElement","innerText","attr","attributes","setAttribute","name","value","querySelector"],"sources":["@wordpress/interactivity-router/src/head.
|
|
1
|
+
{"version":3,"names":["updateHead","newHead","getTagId","tag","id","outerHTML","newHeadMap","Map","child","set","toRemove","document","head","children","nodeName","push","has","delete","toAppend","values","forEach","n","remove","append","fetchHeadAssets","doc","headElements","headTags","assets","tagName","selector","attribute","asset","tags","querySelectorAll","Promise","all","Array","from","map","attributeValue","getAttribute","response","fetch","text","e","console","error","headElement","get","element","createElement","innerText","attr","attributes","setAttribute","name","value","querySelector"],"sources":["@wordpress/interactivity-router/src/head.ts"],"sourcesContent":["/**\n * Helper to update only the necessary tags in the head.\n *\n * @async\n * @param newHead The head elements of the new page.\n */\nexport const updateHead = async ( newHead: HTMLHeadElement[] ) => {\n\t// Helper to get the tag id store in the cache.\n\tconst getTagId = ( tag: Element ) => tag.id || tag.outerHTML;\n\n\t// Map incoming head tags by their content.\n\tconst newHeadMap = new Map< string, Element >();\n\tfor ( const child of newHead ) {\n\t\tnewHeadMap.set( getTagId( child ), child );\n\t}\n\n\tconst toRemove: Element[] = [];\n\n\t// Detect nodes that should be added or removed.\n\tfor ( const child of document.head.children ) {\n\t\tconst id = getTagId( child );\n\t\t// Always remove styles and links as they might change.\n\t\tif ( child.nodeName === 'LINK' || child.nodeName === 'STYLE' ) {\n\t\t\ttoRemove.push( child );\n\t\t} else if ( newHeadMap.has( id ) ) {\n\t\t\tnewHeadMap.delete( id );\n\t\t} else if ( child.nodeName !== 'SCRIPT' && child.nodeName !== 'META' ) {\n\t\t\ttoRemove.push( child );\n\t\t}\n\t}\n\n\t// Prepare new assets.\n\tconst toAppend = [ ...newHeadMap.values() ];\n\n\t// Apply the changes.\n\ttoRemove.forEach( ( n ) => n.remove() );\n\tdocument.head.append( ...toAppend );\n};\n\n/**\n * Fetches and processes head assets (stylesheets and scripts) from a specified document.\n *\n * @async\n * @param doc The document from which to fetch head assets. It should support standard DOM querying methods.\n * @param headElements A map of head elements to modify tracking the URLs of already processed assets to avoid duplicates.\n * @param headElements.tag\n * @param headElements.text\n *\n * @return Returns an array of HTML elements representing the head assets.\n */\nexport const fetchHeadAssets = async (\n\tdoc: Document,\n\theadElements: Map< string, { tag: HTMLElement; text: string } >\n): Promise< HTMLElement[] > => {\n\tconst headTags = [];\n\tconst assets = [\n\t\t{\n\t\t\ttagName: 'style',\n\t\t\tselector: 'link[rel=stylesheet]',\n\t\t\tattribute: 'href',\n\t\t},\n\t\t{ tagName: 'script', selector: 'script[src]', attribute: 'src' },\n\t];\n\tfor ( const asset of assets ) {\n\t\tconst { tagName, selector, attribute } = asset;\n\t\tconst tags = doc.querySelectorAll<\n\t\t\tHTMLScriptElement | HTMLStyleElement\n\t\t>( selector );\n\n\t\t// Use Promise.all to wait for fetch to complete\n\t\tawait Promise.all(\n\t\t\tArray.from( tags ).map( async ( tag ) => {\n\t\t\t\tconst attributeValue = tag.getAttribute( attribute );\n\t\t\t\tif ( ! headElements.has( attributeValue ) ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await fetch( attributeValue );\n\t\t\t\t\t\tconst text = await response.text();\n\t\t\t\t\t\theadElements.set( attributeValue, {\n\t\t\t\t\t\t\ttag,\n\t\t\t\t\t\t\ttext,\n\t\t\t\t\t\t} );\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\t\tconsole.error( e );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst headElement = headElements.get( attributeValue );\n\t\t\t\tconst element = doc.createElement( tagName );\n\t\t\t\telement.innerText = headElement.text;\n\t\t\t\tfor ( const attr of headElement.tag.attributes ) {\n\t\t\t\t\telement.setAttribute( attr.name, attr.value );\n\t\t\t\t}\n\t\t\t\theadTags.push( element );\n\t\t\t} )\n\t\t);\n\t}\n\n\treturn [\n\t\tdoc.querySelector( 'title' ),\n\t\t...doc.querySelectorAll( 'style' ),\n\t\t...headTags,\n\t];\n};\n"],"mappings":"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","ignoreList":[]}
|
package/build-module/index.js
CHANGED
|
@@ -18,7 +18,6 @@ const {
|
|
|
18
18
|
populateInitialData,
|
|
19
19
|
batch
|
|
20
20
|
} = privateApis('I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WordPress.');
|
|
21
|
-
|
|
22
21
|
// Check if the navigation mode is full page or region based.
|
|
23
22
|
const navigationMode = (_getConfig$navigation = getConfig('core/router').navigationMode) !== null && _getConfig$navigation !== void 0 ? _getConfig$navigation : 'regionBased';
|
|
24
23
|
|
|
@@ -29,7 +28,7 @@ const headElements = new Map();
|
|
|
29
28
|
// Helper to remove domain and hash from the URL. We are only interesting in
|
|
30
29
|
// caching the path and the query.
|
|
31
30
|
const getPagePath = url => {
|
|
32
|
-
const u = new URL(url, window.location);
|
|
31
|
+
const u = new URL(url, window.location.href);
|
|
33
32
|
return u.pathname + u.search;
|
|
34
33
|
};
|
|
35
34
|
|
|
@@ -57,9 +56,11 @@ const fetchPage = async (url, {
|
|
|
57
56
|
const regionsToVdom = async (dom, {
|
|
58
57
|
vdom
|
|
59
58
|
} = {}) => {
|
|
60
|
-
const regions = {
|
|
59
|
+
const regions = {
|
|
60
|
+
body: undefined
|
|
61
|
+
};
|
|
61
62
|
let head;
|
|
62
|
-
if (
|
|
63
|
+
if (globalThis.IS_GUTENBERG_PLUGIN) {
|
|
63
64
|
if (navigationMode === 'fullPage') {
|
|
64
65
|
head = await fetchHeadAssets(dom, headElements);
|
|
65
66
|
regions.body = vdom ? vdom.get(document.body) : toVdom(dom.body);
|
|
@@ -85,7 +86,7 @@ const regionsToVdom = async (dom, {
|
|
|
85
86
|
// Render all interactive regions contained in the given page.
|
|
86
87
|
const renderRegions = page => {
|
|
87
88
|
batch(() => {
|
|
88
|
-
if (
|
|
89
|
+
if (globalThis.IS_GUTENBERG_PLUGIN) {
|
|
89
90
|
if (navigationMode === 'fullPage') {
|
|
90
91
|
// Once this code is tested and more mature, the head should be updated for region based navigation as well.
|
|
91
92
|
updateHead(page.head);
|
|
@@ -115,8 +116,8 @@ const renderRegions = page => {
|
|
|
115
116
|
* potential feedback indicating that the navigation has finished while the new
|
|
116
117
|
* page is being loaded.
|
|
117
118
|
*
|
|
118
|
-
* @param
|
|
119
|
-
* @return
|
|
119
|
+
* @param href The page href.
|
|
120
|
+
* @return Promise that never resolves.
|
|
120
121
|
*/
|
|
121
122
|
const forcePageReload = href => {
|
|
122
123
|
window.location.assign(href);
|
|
@@ -126,7 +127,7 @@ const forcePageReload = href => {
|
|
|
126
127
|
// Listen to the back and forward buttons and restore the page if it's in the
|
|
127
128
|
// cache.
|
|
128
129
|
window.addEventListener('popstate', async () => {
|
|
129
|
-
const pagePath = getPagePath(window.location); // Remove hash.
|
|
130
|
+
const pagePath = getPagePath(window.location.href); // Remove hash.
|
|
130
131
|
const page = pages.has(pagePath) && (await pages.get(pagePath));
|
|
131
132
|
if (page) {
|
|
132
133
|
renderRegions(page);
|
|
@@ -138,8 +139,9 @@ window.addEventListener('popstate', async () => {
|
|
|
138
139
|
});
|
|
139
140
|
|
|
140
141
|
// Initialize the router and cache the initial page using the initial vDOM.
|
|
141
|
-
// Once this code is tested and more mature, the head should be updated for
|
|
142
|
-
|
|
142
|
+
// Once this code is tested and more mature, the head should be updated for
|
|
143
|
+
// region based navigation as well.
|
|
144
|
+
if (globalThis.IS_GUTENBERG_PLUGIN) {
|
|
143
145
|
if (navigationMode === 'fullPage') {
|
|
144
146
|
// Cache the scripts. Has to be called before fetching the assets.
|
|
145
147
|
[].map.call(document.querySelectorAll('script[src]'), script => {
|
|
@@ -151,7 +153,7 @@ if (process.env.IS_GUTENBERG_PLUGIN) {
|
|
|
151
153
|
await fetchHeadAssets(document, headElements);
|
|
152
154
|
}
|
|
153
155
|
}
|
|
154
|
-
pages.set(getPagePath(window.location), Promise.resolve(regionsToVdom(document, {
|
|
156
|
+
pages.set(getPagePath(window.location.href), Promise.resolve(regionsToVdom(document, {
|
|
155
157
|
vdom: initialVdom
|
|
156
158
|
})));
|
|
157
159
|
|
|
@@ -180,7 +182,11 @@ export const {
|
|
|
180
182
|
navigation: {
|
|
181
183
|
hasStarted: false,
|
|
182
184
|
hasFinished: false,
|
|
183
|
-
texts: {
|
|
185
|
+
texts: {
|
|
186
|
+
loading: '',
|
|
187
|
+
loaded: ''
|
|
188
|
+
},
|
|
189
|
+
message: ''
|
|
184
190
|
}
|
|
185
191
|
},
|
|
186
192
|
actions: {
|
|
@@ -191,16 +197,16 @@ export const {
|
|
|
191
197
|
* needed, and updates any interactive regions whose contents have
|
|
192
198
|
* changed. It also creates a new entry in the browser session history.
|
|
193
199
|
*
|
|
194
|
-
* @param
|
|
195
|
-
* @param
|
|
196
|
-
* @param
|
|
197
|
-
* @param
|
|
198
|
-
* @param
|
|
199
|
-
* @param
|
|
200
|
-
* @param
|
|
201
|
-
* @param
|
|
200
|
+
* @param href The page href.
|
|
201
|
+
* @param [options] Options object.
|
|
202
|
+
* @param [options.force] If true, it forces re-fetching the URL.
|
|
203
|
+
* @param [options.html] HTML string to be used instead of fetching the requested URL.
|
|
204
|
+
* @param [options.replace] If true, it replaces the current entry in the browser session history.
|
|
205
|
+
* @param [options.timeout] Time until the navigation is aborted, in milliseconds. Default is 10000.
|
|
206
|
+
* @param [options.loadingAnimation] Whether an animation should be shown while navigating. Default to `true`.
|
|
207
|
+
* @param [options.screenReaderAnnouncement] Whether a message for screen readers should be announced while navigating. Default to `true`.
|
|
202
208
|
*
|
|
203
|
-
* @return
|
|
209
|
+
* @return Promise that resolves once the navigation is completed or aborted.
|
|
204
210
|
*/
|
|
205
211
|
*navigate(href, options = {}) {
|
|
206
212
|
const {
|
|
@@ -272,7 +278,7 @@ export const {
|
|
|
272
278
|
// Scroll to the anchor if exits in the link.
|
|
273
279
|
const {
|
|
274
280
|
hash
|
|
275
|
-
} = new URL(href, window.location);
|
|
281
|
+
} = new URL(href, window.location.href);
|
|
276
282
|
if (hash) {
|
|
277
283
|
document.querySelector(hash)?.scrollIntoView();
|
|
278
284
|
}
|
|
@@ -286,10 +292,10 @@ export const {
|
|
|
286
292
|
* The function normalizes the URL and stores internally the fetch
|
|
287
293
|
* promise, to avoid triggering a second fetch for an ongoing request.
|
|
288
294
|
*
|
|
289
|
-
* @param
|
|
290
|
-
* @param
|
|
291
|
-
* @param
|
|
292
|
-
* @param
|
|
295
|
+
* @param url The page URL.
|
|
296
|
+
* @param [options] Options object.
|
|
297
|
+
* @param [options.force] Force fetching the URL again.
|
|
298
|
+
* @param [options.html] HTML string to be used instead of fetching the requested URL.
|
|
293
299
|
*/
|
|
294
300
|
prefetch(url, options = {}) {
|
|
295
301
|
const {
|
|
@@ -300,14 +306,16 @@ export const {
|
|
|
300
306
|
}
|
|
301
307
|
const pagePath = getPagePath(url);
|
|
302
308
|
if (options.force || !pages.has(pagePath)) {
|
|
303
|
-
pages.set(pagePath, fetchPage(pagePath,
|
|
309
|
+
pages.set(pagePath, fetchPage(pagePath, {
|
|
310
|
+
html: options.html
|
|
311
|
+
}));
|
|
304
312
|
}
|
|
305
313
|
}
|
|
306
314
|
}
|
|
307
315
|
});
|
|
308
316
|
|
|
309
317
|
// Add click and prefetch to all links.
|
|
310
|
-
if (
|
|
318
|
+
if (globalThis.IS_GUTENBERG_PLUGIN) {
|
|
311
319
|
if (navigationMode === 'fullPage') {
|
|
312
320
|
// Navigate on click.
|
|
313
321
|
document.addEventListener('click', function (event) {
|