| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- 'use strict';
- const CONSTANTS = require('./constants.js');
- const SYNC = 'sync';
- const ATTRIBUTE_PRIORITIES = [SYNC, 'async', 'defer'];
- const common = require('./common.js');
- const debug = common.debug;
- const matches = common.matches;
- const getScriptName = common.getScriptName;
- const shouldUpdate = (options) => {
- if (ATTRIBUTE_PRIORITIES.indexOf(options.defaultAttribute) < 0) {
- throw new Error(`${CONSTANTS.PLUGIN}: invalid default attribute`);
- }
- return !(options.defaultAttribute === SYNC &&
- options.inline.test.length === 0 &&
- options.async.test.length === 0 &&
- options.defer.test.length === 0 &&
- options.module.test.length === 0);
- };
- const update = (assets, options, tags) => {
- const update = updateElement.bind(null, assets, options);
- return tags.map(update);
- };
- const updateElement = (assets, options, tag) => {
- return (isScript(tag))
- ? updateScriptElement(assets, options, tag)
- : tag;
- };
- const isScript = (tag) => tag.tagName === 'script';
- const updateScriptElement = (assets, options, tag) => {
- debug(`${CONSTANTS.EVENT}: processing <script> element: ${JSON.stringify(tag)}`);
- return (isInline(options, tag))
- ? replaceWithInlineElement(assets, options, tag)
- : updateSrcElement(options, tag);
- };
- const isInline = (options, tag) =>
- matches(getScriptName(options, tag), options.inline.test);
- const replaceWithInlineElement = (assets, options, tag) => {
- const scriptName = getScriptName(options, tag);
- const asset = assets[scriptName];
- if (!asset) throw new Error(`${CONSTANTS.PLUGIN}: no asset with href '${scriptName}'`);
- const newTag = {
- tagName: 'script',
- closeTag: true,
- innerHTML: asset.source()
- };
- debug(`${CONSTANTS.PLUGIN}: replaced by: ${JSON.stringify(newTag)}`);
- return newTag;
- };
- const updateSrcElement = (options, tag) => {
- const scriptName = getScriptName(options, tag);
- // select new attribute, if any, by priority
- let newAttribute;
- ATTRIBUTE_PRIORITIES.some(attribute => {
- if (matches(scriptName, options[attribute].test)) {
- newAttribute = attribute;
- return true;
- }
- });
- if (!newAttribute) newAttribute = options.defaultAttribute;
- if (newAttribute !== SYNC) {
- tag.attributes[newAttribute] = true;
- }
- // possibly overwrite existing type attribute
- if (matches(scriptName, options.module.test)) {
- tag.attributes.type = 'module';
- }
- debug(`${CONSTANTS.PLUGIN}: updated to: ${JSON.stringify(tag)}`);
- return tag;
- };
- module.exports = {
- shouldUpdate,
- update
- };
|