|
|
"use strict";
/* eslint-env browser */
/* eslint-disable no-console, func-names */ var normalizeUrl = require('normalize-url');
var srcByModuleId = Object.create(null); var noDocument = typeof document === 'undefined'; var forEach = Array.prototype.forEach;
function debounce(fn, time) { var timeout = 0; return function () { var self = this; // eslint-disable-next-line prefer-rest-params
var args = arguments;
var functionCall = function functionCall() { return fn.apply(self, args); };
clearTimeout(timeout); timeout = setTimeout(functionCall, time); }; }
function noop() {}
function getCurrentScriptUrl(moduleId) { var src = srcByModuleId[moduleId];
if (!src) { if (document.currentScript) { src = document.currentScript.src; } else { var scripts = document.getElementsByTagName('script'); var lastScriptTag = scripts[scripts.length - 1];
if (lastScriptTag) { src = lastScriptTag.src; } }
srcByModuleId[moduleId] = src; }
return function (fileMap) { if (!src) { return null; }
var splitResult = src.split(/([^\\/]+)\.js$/); var filename = splitResult && splitResult[1];
if (!filename) { return [src.replace('.js', '.css')]; }
if (!fileMap) { return [src.replace('.js', '.css')]; }
return fileMap.split(',').map(function (mapRule) { var reg = new RegExp("".concat(filename, "\\.js$"), 'g'); return normalizeUrl(src.replace(reg, "".concat(mapRule.replace(/{fileName}/g, filename), ".css")), { stripWWW: false }); }); }; }
function updateCss(el, url) { if (!url) { if (!el.href) { return; } // eslint-disable-next-line
url = el.href.split('?')[0]; }
if (!isUrlRequest(url)) { return; }
if (el.isLoaded === false) { // We seem to be about to replace a css link that hasn't loaded yet.
// We're probably changing the same file more than once.
return; }
if (!url || !(url.indexOf('.css') > -1)) { return; } // eslint-disable-next-line no-param-reassign
el.visited = true; var newEl = el.cloneNode(); newEl.isLoaded = false; newEl.addEventListener('load', function () { newEl.isLoaded = true; el.parentNode.removeChild(el); }); newEl.addEventListener('error', function () { newEl.isLoaded = true; el.parentNode.removeChild(el); }); newEl.href = "".concat(url, "?").concat(Date.now());
if (el.nextSibling) { el.parentNode.insertBefore(newEl, el.nextSibling); } else { el.parentNode.appendChild(newEl); } }
function getReloadUrl(href, src) { var ret; // eslint-disable-next-line no-param-reassign
href = normalizeUrl(href, { stripWWW: false }); // eslint-disable-next-line array-callback-return
src.some(function (url) { if (href.indexOf(src) > -1) { ret = url; } }); return ret; }
function reloadStyle(src) { var elements = document.querySelectorAll('link'); var loaded = false; forEach.call(elements, function (el) { if (!el.href) { return; }
var url = getReloadUrl(el.href, src);
if (!isUrlRequest(url)) { return; }
if (el.visited === true) { return; }
if (url) { updateCss(el, url); loaded = true; } }); return loaded; }
function reloadAll() { var elements = document.querySelectorAll('link'); forEach.call(elements, function (el) { if (el.visited === true) { return; }
updateCss(el); }); }
function isUrlRequest(url) { // An URL is not an request if
// It is not http or https
if (!/^https?:/i.test(url)) { return false; }
return true; }
module.exports = function (moduleId, options) { if (noDocument) { console.log('no window.document found, will not HMR CSS'); return noop; }
var getScriptSrc = getCurrentScriptUrl(moduleId);
function update() { var src = getScriptSrc(options.filename); var reloaded = reloadStyle(src);
if (options.locals) { console.log('[HMR] Detected local css modules. Reload all css'); reloadAll(); return; }
if (reloaded && !options.reloadAll) { console.log('[HMR] css reload %s', src.join(' ')); } else { console.log('[HMR] Reload all css'); reloadAll(); } }
return debounce(update, 50); };
|