unpoly-rails 3.5.2 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,7 +5,7 @@
5
5
  /***/ (() => {
6
6
 
7
7
  window.up = {
8
- version: '3.5.2'
8
+ version: '3.6.0'
9
9
  };
10
10
 
11
11
 
@@ -396,7 +396,8 @@ up.util = (function () {
396
396
  return value[value.length - 1];
397
397
  }
398
398
  function contains(value, subValue) {
399
- return value.indexOf(subValue) >= 0;
399
+ let indexOf = value.indexOf || Array.prototype.indexOf;
400
+ return indexOf.call(value, subValue) >= 0;
400
401
  }
401
402
  function objectContains(object, subObject) {
402
403
  const reducedValue = pick(object, Object.keys(subObject));
@@ -902,14 +903,7 @@ up.browser = (function () {
902
903
  function canJQuery() {
903
904
  return !!window.jQuery;
904
905
  }
905
- const canEval = u.memoize(function () {
906
- try {
907
- return new Function('return true')();
908
- }
909
- catch {
910
- return false;
911
- }
912
- });
906
+ const canHasSelector = u.memoize(() => CSS.supports('selector(:has(*))'));
913
907
  function popCookie(name) {
914
908
  let value = document.cookie.match(new RegExp(name + "=(\\w+)"))?.[1];
915
909
  if (value) {
@@ -928,9 +922,9 @@ up.browser = (function () {
928
922
  submitForm,
929
923
  canPushState,
930
924
  canJQuery,
931
- canEval,
932
925
  assertConfirmed,
933
926
  popCookie,
927
+ canHasSelector,
934
928
  };
935
929
  })();
936
930
 
@@ -1211,9 +1205,6 @@ up.element = (function () {
1211
1205
  let clone = createFromHTML(scriptish.outerHTML);
1212
1206
  scriptish.replaceWith(clone);
1213
1207
  }
1214
- function disableScript(scriptElement) {
1215
- scriptElement.type = 'up-disabled-script';
1216
- }
1217
1208
  function createFromHTML(html) {
1218
1209
  const range = document.createRange();
1219
1210
  range.setStart(document.body, 0);
@@ -1452,16 +1443,12 @@ up.element = (function () {
1452
1443
  jQuery(element).remove();
1453
1444
  }
1454
1445
  }
1455
- function filteredQuery(parent, includeSelectors, excludeSelectors) {
1456
- let fullIncludeSelector = includeSelectors.join();
1457
- let fullExcludeSelector = excludeSelectors.join();
1458
- let elements = parent.querySelectorAll(fullIncludeSelector);
1459
- let isExcluded = (element) => element.matches(fullExcludeSelector);
1460
- return u.reject(elements, isExcluded);
1461
- }
1462
1446
  function isEmpty(element) {
1463
1447
  return !element.children.length > 0 && !element.innerText.trim();
1464
1448
  }
1449
+ function crossOriginSelector(attr) {
1450
+ return `[${attr}*="//"]:not([${attr}*="//${location.host}/"])`;
1451
+ }
1465
1452
  return {
1466
1453
  subtree,
1467
1454
  contains,
@@ -1516,9 +1503,8 @@ up.element = (function () {
1516
1503
  setTemporaryAttr,
1517
1504
  cleanJQuery,
1518
1505
  parseSelector,
1519
- filteredQuery,
1520
1506
  isEmpty,
1521
- disableScript,
1507
+ crossOriginSelector,
1522
1508
  };
1523
1509
  })();
1524
1510
 
@@ -1630,14 +1616,30 @@ up.Record = class Record {
1630
1616
  /* 17 */
1631
1617
  /***/ (() => {
1632
1618
 
1619
+ const u = up.util;
1633
1620
  up.Config = class Config {
1634
1621
  constructor(blueprintFn = (() => ({}))) {
1635
1622
  this._blueprintFn = blueprintFn;
1636
1623
  this.reset();
1624
+ document.addEventListener('up:framework:reset', () => this.reset());
1637
1625
  }
1638
1626
  reset() {
1639
1627
  Object.assign(this, this._blueprintFn());
1640
1628
  }
1629
+ matches(element, prop) {
1630
+ return element.matches(this.selector(prop));
1631
+ }
1632
+ selector(prop) {
1633
+ let includes = this[prop];
1634
+ let excludes = this['no' + u.upperCaseFirst(prop)];
1635
+ let selector = `:is(${includes.join()})`;
1636
+ if (u.isPresent(excludes))
1637
+ selector += `:not(${excludes.join()})`;
1638
+ return selector;
1639
+ }
1640
+ selectorFn(prop) {
1641
+ return () => this.selector(prop);
1642
+ }
1641
1643
  };
1642
1644
 
1643
1645
 
@@ -2220,6 +2222,7 @@ up.Change.OpenLayer = class OpenLayer extends up.Change.Addition {
2220
2222
  _renderOverlayContent() {
2221
2223
  this._handleHistory();
2222
2224
  this.handleLayerChangeRequests();
2225
+ this.responseDoc.commitElement(this._content);
2223
2226
  this.layer.setContent(this._content);
2224
2227
  this.setReloadAttrs({ newElement: this._content, source: this.options.source });
2225
2228
  this.responseDoc.finalizeElement(this._content);
@@ -2618,7 +2621,7 @@ up.Change.UpdateSteps = class UpdateSteps extends up.Change.Addition {
2618
2621
  const keepableClone = keepable.cloneNode(true);
2619
2622
  keepable.insertAdjacentElement('beforebegin', keepableClone);
2620
2623
  keepable.classList.add('up-keeping');
2621
- u.each(e.subtree(keepPlan.newElement, 'script'), e.disableScript);
2624
+ up.script.disableSubtree(keepPlan.newElement);
2622
2625
  let viewports = up.viewport.subtree(keepPlan.oldElement);
2623
2626
  keepPlan.revivers = viewports.map(function (viewport) {
2624
2627
  let cursorProps = up.viewport.copyCursorProps(viewport);
@@ -3884,7 +3887,7 @@ up.FormValidator = class FormValidator {
3884
3887
  options.failOptions = false;
3885
3888
  options.params = up.Params.merge(options.params, ...u.map(dirtyRenderOptionsList, 'params'));
3886
3889
  options.headers = u.merge(...u.map(dirtyRenderOptionsList, 'headers'));
3887
- options.headers[up.protocol.headerize('validate')] = dirtyNames.join(' ') || ':unknown';
3890
+ this._addValidateHeader(options.headers, dirtyNames);
3888
3891
  options.guardEvent = up.event.build('up:form:validate', {
3889
3892
  fields: dirtyFields,
3890
3893
  log: 'Validating form',
@@ -3909,6 +3912,13 @@ up.FormValidator = class FormValidator {
3909
3912
  this._renderDirtySolutions();
3910
3913
  }
3911
3914
  }
3915
+ _addValidateHeader(headers, names) {
3916
+ let key = up.protocol.headerize('validate');
3917
+ let value = names.join(' ');
3918
+ if (!value || value.length > up.protocol.config.maxHeaderSize)
3919
+ value = ':unknown';
3920
+ headers[key] = value;
3921
+ }
3912
3922
  _buildDataMap(solutions) {
3913
3923
  let dataMap = {};
3914
3924
  for (let solution of solutions) {
@@ -4048,7 +4058,7 @@ up.FragmentFinder = class FragmentFinder {
4048
4058
  }
4049
4059
  }
4050
4060
  _findInRegion() {
4051
- if (this._match === 'region' && this._origin?.isConnected) {
4061
+ if (this._match === 'region' && !up.fragment.containsMainPseudo(this._selector) && this._origin?.isConnected) {
4052
4062
  return this._findClosest() || this._findDescendantInRegion();
4053
4063
  }
4054
4064
  }
@@ -5473,25 +5483,19 @@ up.NonceableCallback = class NonceableCallback {
5473
5483
  return new this(match[3], match[2]);
5474
5484
  }
5475
5485
  toFunction(...argNames) {
5476
- if (up.browser.canEval()) {
5477
- return new Function(...argNames, this.script);
5478
- }
5479
- else if (this.nonce) {
5486
+ if (this.nonce) {
5480
5487
  let callbackThis = this;
5481
5488
  return function (...args) {
5482
5489
  return callbackThis._runAsNoncedFunction(this, argNames, args);
5483
5490
  };
5484
5491
  }
5485
5492
  else {
5486
- return this._cannotRun.bind(this);
5493
+ return new Function(...argNames, this.script);
5487
5494
  }
5488
5495
  }
5489
5496
  toString() {
5490
5497
  return `nonce-${this.nonce} ${this.script}`;
5491
5498
  }
5492
- _cannotRun() {
5493
- throw new Error(`Your Content Security Policy disallows inline JavaScript (${this.script}). See https://unpoly.com/csp for solutions.`);
5494
- }
5495
5499
  _runAsNoncedFunction(thisArg, argNames, args) {
5496
5500
  let wrappedScript = `
5497
5501
  try {
@@ -6816,7 +6820,7 @@ up.Response = class Response extends up.Record {
6816
6820
  return this.header('Content-Type');
6817
6821
  }
6818
6822
  get cspNonces() {
6819
- return up.protocol.cspNoncesFromHeader(this.header('Content-Security-Policy'));
6823
+ return up.protocol.cspNoncesFromHeader(this.header('Content-Security-Policy') || this.header('Content-Security-Policy-Report-Only'));
6820
6824
  }
6821
6825
  get lastModified() {
6822
6826
  let header = this.header('Last-Modified');
@@ -6862,9 +6866,6 @@ up.ResponseDoc = (_a = class ResponseDoc {
6862
6866
  else {
6863
6867
  this._parseContent(content || '', target);
6864
6868
  }
6865
- if (!up.fragment.config.runScripts) {
6866
- this._document.querySelectorAll('script').forEach((e) => e.remove());
6867
- }
6868
6869
  this._cspNonces = cspNonces;
6869
6870
  if (origin) {
6870
6871
  let originSelector = up.fragment.tryToTarget(origin);
@@ -6952,12 +6953,7 @@ up.ResponseDoc = (_a = class ResponseDoc {
6952
6953
  });
6953
6954
  }
6954
6955
  commitSteps(steps) {
6955
- return steps.filter((step) => {
6956
- if (this._document.contains(step.newElement)) {
6957
- step.newElement.remove();
6958
- return true;
6959
- }
6960
- });
6956
+ return steps.filter((step) => this.commitElement(step.newElement));
6961
6957
  }
6962
6958
  _trySelectStep(step) {
6963
6959
  if (step.newElement) {
@@ -6984,6 +6980,15 @@ up.ResponseDoc = (_a = class ResponseDoc {
6984
6980
  throw new up.CannotMatch();
6985
6981
  }
6986
6982
  }
6983
+ commitElement(element) {
6984
+ if (this._document.contains(element)) {
6985
+ if (!up.fragment.config.runScripts) {
6986
+ up.script.disableSubtree(element);
6987
+ }
6988
+ element.remove();
6989
+ return true;
6990
+ }
6991
+ }
6987
6992
  finalizeElement(element) {
6988
6993
  up.NonceableCallback.adoptNonces(element, this._cspNonces);
6989
6994
  if (this._isDocumentBroken) {
@@ -7017,8 +7022,8 @@ up.RevealMotion = class RevealMotion {
7017
7022
  this._padding = this._options.padding ?? this._options.revealPadding ?? viewportConfig.revealPadding;
7018
7023
  this._top = this._options.top ?? this._options.revealTop ?? viewportConfig.revealTop;
7019
7024
  this._max = this._options.max ?? this._options.revealMax ?? viewportConfig.revealMax;
7020
- this._topObstructions = viewportConfig.fixedTopSelectors;
7021
- this._bottomObstructions = viewportConfig.fixedBottomSelectors;
7025
+ this._topObstructionSelector = viewportConfig.selector('fixedTopSelectors');
7026
+ this._bottomObstructionSelector = viewportConfig.selector('fixedBottomSelectors');
7022
7027
  }
7023
7028
  start() {
7024
7029
  const viewportRect = this._getViewportRect(this._viewport);
@@ -7070,12 +7075,12 @@ up.RevealMotion = class RevealMotion {
7070
7075
  elementRect.top -= this._padding;
7071
7076
  elementRect.height += 2 * this._padding;
7072
7077
  }
7073
- _selectObstructions(selectors) {
7074
- let elements = up.fragment.all(selectors.join(), { layer: this._obstructionsLayer });
7078
+ _selectObstructions(selector) {
7079
+ let elements = up.fragment.all(selector, { layer: this._obstructionsLayer });
7075
7080
  return u.filter(elements, e.isVisible);
7076
7081
  }
7077
7082
  _substractObstructions(viewportRect) {
7078
- for (let obstruction of this._selectObstructions(this._topObstructions)) {
7083
+ for (let obstruction of this._selectObstructions(this._topObstructionSelector)) {
7079
7084
  let obstructionRect = up.Rect.fromElement(obstruction);
7080
7085
  let diff = obstructionRect.bottom - viewportRect.top;
7081
7086
  if (diff > 0) {
@@ -7083,7 +7088,7 @@ up.RevealMotion = class RevealMotion {
7083
7088
  viewportRect.height -= diff;
7084
7089
  }
7085
7090
  }
7086
- for (let obstruction of this._selectObstructions(this._bottomObstructions)) {
7091
+ for (let obstruction of this._selectObstructions(this._bottomObstructionSelector)) {
7087
7092
  let obstructionRect = up.Rect.fromElement(obstruction);
7088
7093
  let diff = viewportRect.bottom - obstructionRect.top;
7089
7094
  if (diff > 0) {
@@ -7121,10 +7126,12 @@ up.Selector = class Selector {
7121
7126
  }
7122
7127
  let expandedTargets = up.fragment.expandTargets(selector, { ...options, layer: expandTargetLayer });
7123
7128
  this._selectors = expandedTargets.map((target) => {
7124
- target = target.replace(CSS_HAS_SUFFIX_PATTERN, (match, descendantSelector) => {
7125
- this._filters.push(element => element.querySelector(descendantSelector));
7126
- return '';
7127
- });
7129
+ if (!up.browser.canHasSelector()) {
7130
+ target = target.replace(CSS_HAS_SUFFIX_PATTERN, (match, descendantSelector) => {
7131
+ this._filters.push(element => element.querySelector(descendantSelector));
7132
+ return '';
7133
+ });
7134
+ }
7128
7135
  return target || '*';
7129
7136
  });
7130
7137
  this._unionSelector = this._selectors.join() || 'match-none';
@@ -7614,6 +7621,7 @@ up.protocol = (function () {
7614
7621
  csrfToken() { return e.metaContent('csrf-token'); },
7615
7622
  cspNonce() { return e.metaContent('csp-nonce'); },
7616
7623
  csrfHeader: 'X-CSRF-Token',
7624
+ maxHeaderSize: 2048,
7617
7625
  }));
7618
7626
  function csrfHeader() {
7619
7627
  return u.evalOption(config.csrfHeader);
@@ -7647,13 +7655,8 @@ up.protocol = (function () {
7647
7655
  params.add(config.methodParam, method);
7648
7656
  return 'POST';
7649
7657
  }
7650
- function reset() {
7651
- config.reset();
7652
- }
7653
- up.on('up:framework:reset', reset);
7654
7658
  return {
7655
7659
  config,
7656
- reset,
7657
7660
  locationFromXHR,
7658
7661
  titleFromXHR,
7659
7662
  targetFromXHR,
@@ -7684,9 +7687,6 @@ up.protocol = (function () {
7684
7687
  up.log = (function () {
7685
7688
  const u = up.util;
7686
7689
  const config = new up.LogConfig();
7687
- function reset() {
7688
- config.reset();
7689
- }
7690
7690
  function printToStandard(...args) {
7691
7691
  if (config.enabled) {
7692
7692
  printToStream('log', ...args);
@@ -7741,7 +7741,6 @@ up.log = (function () {
7741
7741
  }
7742
7742
  }
7743
7743
  up.on('up:framework:boot', printBanner);
7744
- up.on('up:framework:reset', reset);
7745
7744
  function enable() {
7746
7745
  config.enabled = true;
7747
7746
  }
@@ -7788,6 +7787,12 @@ up.script = (function () {
7788
7787
  'up-on-error',
7789
7788
  'up-on-offline',
7790
7789
  ],
7790
+ scriptSelectors: [
7791
+ 'script'
7792
+ ],
7793
+ noScriptSelectors: [
7794
+ 'script[type="application/ld+json"]'
7795
+ ]
7791
7796
  }));
7792
7797
  const SYSTEM_MACRO_PRIORITIES = {
7793
7798
  '[up-back]': -100,
@@ -7915,7 +7920,7 @@ up.script = (function () {
7915
7920
  };
7916
7921
  }
7917
7922
  function findAssets(head = document.head) {
7918
- return e.filteredQuery(head, config.assetSelectors, config.noAssetSelectors);
7923
+ return head.querySelectorAll(config.selector('assetSelectors'));
7919
7924
  }
7920
7925
  function assertAssetsOK(newAssets, renderOptions) {
7921
7926
  let oldAssets = findAssets();
@@ -7925,10 +7930,16 @@ up.script = (function () {
7925
7930
  up.event.assertEmitted('up:assets:changed', { oldAssets, newAssets, renderOptions });
7926
7931
  }
7927
7932
  }
7933
+ function disableScript(scriptElement) {
7934
+ scriptElement.type = 'up-disabled-script';
7935
+ }
7936
+ function disableScriptsInSubtree(root) {
7937
+ let selector = config.selector('scriptSelectors');
7938
+ u.each(e.subtree(root, selector), disableScript);
7939
+ }
7928
7940
  function reset() {
7929
7941
  registeredCompilers = u.filter(registeredCompilers, 'isDefault');
7930
7942
  registeredMacros = u.filter(registeredMacros, 'isDefault');
7931
- config.reset();
7932
7943
  }
7933
7944
  up.on('up:framework:reset', reset);
7934
7945
  return {
@@ -7941,6 +7952,7 @@ up.script = (function () {
7941
7952
  data: readData,
7942
7953
  findAssets,
7943
7954
  assertAssetsOK,
7955
+ disableSubtree: disableScriptsInSubtree,
7944
7956
  };
7945
7957
  })();
7946
7958
  up.compiler = up.script.compiler;
@@ -7967,6 +7979,7 @@ up.history = (function () {
7967
7979
  'link[rel=canonical]',
7968
7980
  'link[rel=icon]',
7969
7981
  '[up-meta]',
7982
+ 'script[type="application/ld+json"]',
7970
7983
  ],
7971
7984
  noMetaTagSelectors: [
7972
7985
  'meta[http-equiv]',
@@ -7977,7 +7990,6 @@ up.history = (function () {
7977
7990
  let previousLocation;
7978
7991
  let nextPreviousLocation;
7979
7992
  function reset() {
7980
- config.reset();
7981
7993
  previousLocation = undefined;
7982
7994
  nextPreviousLocation = undefined;
7983
7995
  trackCurrentLocation();
@@ -8078,7 +8090,7 @@ up.history = (function () {
8078
8090
  }
8079
8091
  });
8080
8092
  function findMetaTags(head = document.head) {
8081
- return e.filteredQuery(head, config.metaTagSelectors, config.noMetaTagSelectors);
8093
+ return head.querySelectorAll(config.selector('metaTagSelectors'));
8082
8094
  }
8083
8095
  function updateMetaTags(newMetaTags) {
8084
8096
  let oldMetaTags = findMetaTags();
@@ -8172,9 +8184,6 @@ up.fragment = (function () {
8172
8184
  skipResponse: defaultSkipResponse
8173
8185
  }));
8174
8186
  u.delegate(config, ['mainTargets'], () => up.layer.config.any);
8175
- function reset() {
8176
- config.reset();
8177
- }
8178
8187
  function defaultSkipResponse({ response, expiredResponse }) {
8179
8188
  return !response.text || response.text === expiredResponse?.text;
8180
8189
  }
@@ -8435,18 +8444,11 @@ up.fragment = (function () {
8435
8444
  let isGood = (klass) => !u.some(config.badTargetClasses, (badTargetClass) => matchesPattern(badTargetClass, klass));
8436
8445
  return u.filter(element.classList, isGood);
8437
8446
  }
8438
- function modernResolveOrigin(target, { origin } = {}) {
8439
- return target.replace(/:origin\b/, function (match) {
8440
- if (origin) {
8441
- return toTarget(origin);
8442
- }
8443
- else {
8444
- up.fail('Missing { origin } element to resolve "%s" reference (found in %s)', match, target);
8445
- }
8446
- });
8447
- }
8448
- function resolveOrigin(...args) {
8449
- return (up.migrate.resolveOrigin || modernResolveOrigin)(...args);
8447
+ const MAIN_PSEUDO = /:main\b/;
8448
+ const LAYER_PSEUDO = /:layer\b/;
8449
+ const ORIGIN_PSEUDO = /:origin\b/;
8450
+ function containsMainPseudo(target) {
8451
+ return MAIN_PSEUDO.test(target);
8450
8452
  }
8451
8453
  function expandTargets(targets, options = {}) {
8452
8454
  const { layer } = options;
@@ -8456,21 +8458,19 @@ up.fragment = (function () {
8456
8458
  targets = u.copy(u.wrapList(targets));
8457
8459
  const expanded = [];
8458
8460
  while (targets.length) {
8459
- const target = targets.shift();
8460
- if (target === ':main' || target === true) {
8461
- let mode;
8462
- if (layer === 'new') {
8463
- mode = options.mode || up.fail('Must pass a { mode } option together with { layer: "new" }');
8464
- }
8465
- else {
8466
- mode = layer.mode;
8467
- }
8468
- targets.unshift(...up.layer.mainTargets(mode));
8469
- }
8470
- else if (target === ':layer') {
8471
- if (layer !== 'new' && !layer.opening) {
8472
- targets.unshift(layer.getFirstSwappableElement());
8473
- }
8461
+ let target = targets.shift();
8462
+ if (target === true)
8463
+ target = ':main';
8464
+ if (containsMainPseudo(target)) {
8465
+ let mode = resolveMode(options);
8466
+ let replaced = up.layer.mainTargets(mode).map((mainTarget) => target.replace(MAIN_PSEUDO, mainTarget));
8467
+ targets.unshift(...replaced);
8468
+ }
8469
+ else if (LAYER_PSEUDO.test(target)) {
8470
+ if (layer === 'new' || layer.opening)
8471
+ continue;
8472
+ let firstSwappableTarget = toTarget(layer.getFirstSwappableElement(), options);
8473
+ targets.unshift(target.replace(LAYER_PSEUDO, firstSwappableTarget));
8474
8474
  }
8475
8475
  else if (u.isElementish(target)) {
8476
8476
  expanded.push(toTarget(target, options));
@@ -8478,11 +8478,30 @@ up.fragment = (function () {
8478
8478
  else if (u.isString(target)) {
8479
8479
  expanded.push(resolveOrigin(target, options));
8480
8480
  }
8481
- else {
8482
- }
8483
8481
  }
8484
8482
  return u.uniq(expanded);
8485
8483
  }
8484
+ function resolveMode({ layer, mode }) {
8485
+ if (layer === 'new') {
8486
+ return mode || up.fail('Must pass a { mode } option together with { layer: "new" }');
8487
+ }
8488
+ else {
8489
+ return layer.mode;
8490
+ }
8491
+ }
8492
+ function modernResolveOrigin(target, { origin } = {}) {
8493
+ return target.replace(ORIGIN_PSEUDO, function (match) {
8494
+ if (origin) {
8495
+ return toTarget(origin);
8496
+ }
8497
+ else {
8498
+ up.fail('Missing { origin } element to resolve "%s" reference (found in %s)', match, target);
8499
+ }
8500
+ });
8501
+ }
8502
+ function resolveOrigin(...args) {
8503
+ return (up.migrate.resolveOrigin || modernResolveOrigin)(...args);
8504
+ }
8486
8505
  function splitTarget(target) {
8487
8506
  return u.parseTokens(target, { separator: 'comma' });
8488
8507
  }
@@ -8593,7 +8612,6 @@ up.fragment = (function () {
8593
8612
  return up.warn('Cannot push history changes. Next fragment update will load in a new page.');
8594
8613
  }
8595
8614
  });
8596
- up.on('up:framework:reset', reset);
8597
8615
  return {
8598
8616
  config,
8599
8617
  reload,
@@ -8632,6 +8650,7 @@ up.fragment = (function () {
8632
8650
  isNotDestroying,
8633
8651
  targetForSteps,
8634
8652
  compressNestedSteps,
8653
+ containsMainPseudo,
8635
8654
  };
8636
8655
  })();
8637
8656
  up.reload = up.fragment.reload;
@@ -8671,13 +8690,7 @@ up.viewport = (function () {
8671
8690
  revealMax() { return 0.5 * window.innerHeight; },
8672
8691
  }));
8673
8692
  const bodyShifter = new up.BodyShifter();
8674
- function reset() {
8675
- config.reset();
8676
- }
8677
- function fullAnchoredRightSelector() {
8678
- return config.anchoredRightSelectors.join();
8679
- }
8680
- up.compiler(fullAnchoredRightSelector, function (element) {
8693
+ up.compiler(config.selectorFn('anchoredRightSelectors'), function (element) {
8681
8694
  return bodyShifter.onAnchoredElementInserted(element);
8682
8695
  });
8683
8696
  function reveal(element, options) {
@@ -8943,7 +8956,6 @@ up.viewport = (function () {
8943
8956
  });
8944
8957
  });
8945
8958
  up.on(window, 'hashchange', () => revealHash());
8946
- up.on('up:framework:reset', reset);
8947
8959
  return {
8948
8960
  reveal,
8949
8961
  revealHash,
@@ -9008,7 +9020,6 @@ up.motion = (function () {
9008
9020
  motionController.reset();
9009
9021
  namedAnimations = pickDefault(namedAnimations);
9010
9022
  namedTransitions = pickDefault(namedTransitions);
9011
- config.reset();
9012
9023
  }
9013
9024
  function isEnabled() {
9014
9025
  return config.enabled;
@@ -9283,7 +9294,6 @@ up.network = (function () {
9283
9294
  function reset() {
9284
9295
  abortRequests();
9285
9296
  queue.reset();
9286
- config.reset();
9287
9297
  cache.reset();
9288
9298
  progressBar?.destroy();
9289
9299
  progressBar = null;
@@ -9552,7 +9562,6 @@ up.layer = (function () {
9552
9562
  return e.callbackAttr(link, attr, { exposedKeys: ['layer', 'value', 'response'] });
9553
9563
  }
9554
9564
  function reset() {
9555
- config.reset();
9556
9565
  stack.reset();
9557
9566
  handlers = u.filter(handlers, 'isDefault');
9558
9567
  }
@@ -9587,7 +9596,7 @@ up.layer = (function () {
9587
9596
  }
9588
9597
  }
9589
9598
  function isWithinForeignOverlay(element) {
9590
- let selector = config.foreignOverlaySelectors.join();
9599
+ let selector = config.selector('foreignOverlaySelectors');
9591
9600
  return !!(selector && element.closest(selector));
9592
9601
  }
9593
9602
  up.on('up:fragment:destroyed', function () {
@@ -9672,7 +9681,7 @@ up.link = (function () {
9672
9681
  }
9673
9682
  const config = new up.Config(() => ({
9674
9683
  followSelectors: combineFollowableSelectors(LINKS_WITH_REMOTE_HTML, ATTRIBUTES_SUGGESTING_FOLLOW).concat(LINKS_WITH_LOCAL_HTML),
9675
- noFollowSelectors: ['[up-follow=false]', 'a[download]', 'a[target]', 'a[href^="#"]:not([up-content]):not([up-fragment]):not([up-document])', 'a[href^="javascript:"]'],
9684
+ noFollowSelectors: ['[up-follow=false]', 'a[download]', 'a[target]', 'a[href^="#"]:not([up-content]):not([up-fragment]):not([up-document])', 'a[href^="javascript:"]', 'a[href^="mailto:"]', e.crossOriginSelector('href'), e.crossOriginSelector('up-href')],
9676
9685
  instantSelectors: ['[up-instant]'],
9677
9686
  noInstantSelectors: ['[up-instant=false]', '[onclick]'],
9678
9687
  preloadSelectors: combineFollowableSelectors(LINKS_WITH_REMOTE_HTML, ['[up-preload]']),
@@ -9680,26 +9689,8 @@ up.link = (function () {
9680
9689
  clickableSelectors: LINKS_WITH_LOCAL_HTML.concat(['[up-emit]', '[up-accept]', '[up-dismiss]', '[up-clickable]']),
9681
9690
  preloadDelay: 90,
9682
9691
  }));
9683
- function fullFollowSelector() {
9684
- return config.followSelectors.join();
9685
- }
9686
- function fullPreloadSelector() {
9687
- return config.preloadSelectors.join();
9688
- }
9689
- function fullInstantSelector() {
9690
- return config.instantSelectors.join();
9691
- }
9692
- function fullClickableSelector() {
9693
- return config.clickableSelectors.join();
9694
- }
9695
- function isFollowDisabled(link) {
9696
- return link.matches(config.noFollowSelectors.join()) || u.isCrossOrigin(link);
9697
- }
9698
9692
  function isPreloadDisabled(link) {
9699
- return !up.browser.canPushState() ||
9700
- link.matches(config.noPreloadSelectors.join()) ||
9701
- isFollowDisabled(link) ||
9702
- !willCache(link);
9693
+ return !up.browser.canPushState() || !isFollowable(link) || !willCache(link);
9703
9694
  }
9704
9695
  function willCache(link) {
9705
9696
  const options = parseRequestOptions(link);
@@ -9712,12 +9703,8 @@ up.link = (function () {
9712
9703
  return request.willCache();
9713
9704
  }
9714
9705
  }
9715
- function isInstantDisabled(link) {
9716
- return link.matches(config.noInstantSelectors.join()) || isFollowDisabled(link);
9717
- }
9718
9706
  function reset() {
9719
9707
  lastMousedownTarget = null;
9720
- config.reset();
9721
9708
  linkPreloader.reset();
9722
9709
  }
9723
9710
  const follow = up.mockable(function (link, options) {
@@ -9832,7 +9819,7 @@ up.link = (function () {
9832
9819
  }
9833
9820
  function isFollowable(link) {
9834
9821
  link = up.fragment.get(link);
9835
- return link.matches(fullFollowSelector()) && !isFollowDisabled(link);
9822
+ return config.matches(link, 'followSelectors');
9836
9823
  }
9837
9824
  function makeFollowable(link) {
9838
9825
  if (!isFollowable(link)) {
@@ -9854,9 +9841,9 @@ up.link = (function () {
9854
9841
  }
9855
9842
  });
9856
9843
  }
9857
- up.macro(fullClickableSelector, makeClickable);
9844
+ up.macro(config.selectorFn('clickableSelectors'), makeClickable);
9858
9845
  function shouldFollowEvent(event, link) {
9859
- if (event.defaultPrevented || isFollowDisabled(link)) {
9846
+ if (event.defaultPrevented) {
9860
9847
  return false;
9861
9848
  }
9862
9849
  const betterTargetSelector = `a, [up-href], ${up.form.fieldSelector()}`;
@@ -9864,9 +9851,12 @@ up.link = (function () {
9864
9851
  return !betterTarget || (betterTarget === link);
9865
9852
  }
9866
9853
  function isInstant(linkOrDescendant) {
9867
- const element = linkOrDescendant.closest(fullInstantSelector());
9854
+ const element = linkOrDescendant.closest(config.selector('instantSelectors'));
9868
9855
  return element && !isInstantDisabled(element);
9869
9856
  }
9857
+ function isInstantDisabled(link) {
9858
+ return config.matches(link, 'noInstantSelectors') || config.matches(link, 'noFollowSelectors');
9859
+ }
9870
9860
  function convertClicks(layer) {
9871
9861
  layer.on('click', function (event, element) {
9872
9862
  if (!up.event.isUnmodified(event)) {
@@ -9902,7 +9892,7 @@ up.link = (function () {
9902
9892
  const method = followMethod(link);
9903
9893
  return up.network.isSafeMethod(method);
9904
9894
  }
9905
- up.on('up:click', fullFollowSelector, function (event, link) {
9895
+ up.on('up:click', config.selectorFn('followSelectors'), function (event, link) {
9906
9896
  if (shouldFollowEvent(event, link)) {
9907
9897
  up.event.halt(event, { log: true });
9908
9898
  up.focus(link, { preventScroll: true });
@@ -9921,7 +9911,7 @@ up.link = (function () {
9921
9911
  makeFollowable(area);
9922
9912
  }
9923
9913
  });
9924
- up.compiler(fullPreloadSelector, function (link) {
9914
+ up.compiler(config.selectorFn('preloadSelectors'), function (link) {
9925
9915
  if (!isPreloadDisabled(link)) {
9926
9916
  linkPreloader.watchLink(link);
9927
9917
  }
@@ -9940,8 +9930,6 @@ up.link = (function () {
9940
9930
  convertClicks,
9941
9931
  config,
9942
9932
  combineFollowableSelectors,
9943
- preloadSelector: fullPreloadSelector,
9944
- followSelector: fullFollowSelector,
9945
9933
  preloadIssue,
9946
9934
  };
9947
9935
  })();
@@ -9969,18 +9957,12 @@ up.form = (function () {
9969
9957
  groupSelectors: ['[up-form-group]', 'fieldset', 'label', 'form'],
9970
9958
  fieldSelectors: ['select', 'input:not([type=submit]):not([type=image])', 'button[type]:not([type=submit])', 'textarea'],
9971
9959
  submitSelectors: up.link.combineFollowableSelectors(['form'], ATTRIBUTES_SUGGESTING_SUBMIT),
9972
- noSubmitSelectors: ['[up-submit=false]', '[target]'],
9960
+ noSubmitSelectors: ['[up-submit=false]', '[target]', e.crossOriginSelector('action')],
9973
9961
  submitButtonSelectors: ['input[type=submit]', 'input[type=image]', 'button[type=submit]', 'button:not([type])'],
9974
9962
  watchInputEvents: ['input', 'change'],
9975
9963
  watchInputDelay: 0,
9976
9964
  watchChangeEvents: ['change'],
9977
9965
  }));
9978
- function fullSubmitSelector() {
9979
- return config.submitSelectors.join();
9980
- }
9981
- function reset() {
9982
- config.reset();
9983
- }
9984
9966
  function fieldSelector(suffix = '') {
9985
9967
  return config.fieldSelectors.map(field => field + suffix).join();
9986
9968
  }
@@ -10012,7 +9994,7 @@ up.form = (function () {
10012
9994
  return e.get(form, selector);
10013
9995
  }
10014
9996
  function submitButtonSelector() {
10015
- return config.submitButtonSelectors.join();
9997
+ return config.selector('submitButtonSelectors');
10016
9998
  }
10017
9999
  const submit = up.mockable((form, options) => {
10018
10000
  return up.render(submitOptions(form, options));
@@ -10290,15 +10272,11 @@ up.form = (function () {
10290
10272
  }
10291
10273
  function isSubmittable(form) {
10292
10274
  form = up.fragment.get(form);
10293
- return form.matches(fullSubmitSelector()) && !isSubmitDisabled(form);
10275
+ return config.matches(form, 'submitSelectors');
10294
10276
  }
10295
- function isSubmitDisabled(form) {
10296
- return form.matches(config.noSubmitSelectors.join());
10297
- }
10298
- up.on('submit', fullSubmitSelector, function (event, form) {
10299
- if (event.defaultPrevented || isSubmitDisabled(form)) {
10277
+ up.on('submit', config.selectorFn('submitSelectors'), function (event, form) {
10278
+ if (event.defaultPrevented)
10300
10279
  return;
10301
- }
10302
10280
  up.event.halt(event, { log: true });
10303
10281
  up.error.muteUncriticalRejection(submit(form));
10304
10282
  });
@@ -10320,7 +10298,6 @@ up.form = (function () {
10320
10298
  });
10321
10299
  up.compiler('[up-watch]', (formOrField) => watch(formOrField));
10322
10300
  up.compiler('[up-autosubmit]', (formOrField) => autosubmit(formOrField));
10323
- up.on('up:framework:reset', reset);
10324
10301
  return {
10325
10302
  config,
10326
10303
  submit,
@@ -10363,14 +10340,13 @@ up.feedback = (function () {
10363
10340
  navSelectors: ['[up-nav]', 'nav'],
10364
10341
  }));
10365
10342
  function reset() {
10366
- config.reset();
10367
10343
  up.layer.root.feedbackLocation = null;
10368
10344
  }
10369
10345
  const CLASS_ACTIVE = 'up-active';
10370
10346
  const CLASS_LOADING = 'up-loading';
10371
10347
  const SELECTOR_LINK = 'a, [up-href]';
10372
10348
  function navSelector() {
10373
- return config.navSelectors.join();
10349
+ return config.selector('navSelectors');
10374
10350
  }
10375
10351
  function normalizeURL(url) {
10376
10352
  if (url) {
@@ -10478,15 +10454,12 @@ up.radio = (function () {
10478
10454
  hungrySelectors: ['[up-hungry]'],
10479
10455
  pollInterval: 30000,
10480
10456
  }));
10481
- function reset() {
10482
- config.reset();
10483
- }
10484
10457
  function hungrySteps(renderOptions) {
10485
10458
  let { useHungry, origin, layer: renderLayer } = renderOptions;
10486
10459
  let steps = { current: [], other: [] };
10487
10460
  if (!useHungry)
10488
10461
  return steps;
10489
- let hungrySelector = config.hungrySelectors.join();
10462
+ let hungrySelector = config.selector('hungrySelectors');
10490
10463
  const layerPreference = [renderLayer, ...renderLayer.ancestors, ...renderLayer.descendants];
10491
10464
  for (let elementLayer of layerPreference) {
10492
10465
  let hungries = up.fragment.all(elementLayer.element, hungrySelector, { layer: elementLayer });
@@ -10550,7 +10523,6 @@ up.radio = (function () {
10550
10523
  event.preventDefault();
10551
10524
  });
10552
10525
  });
10553
- up.on('up:framework:reset', reset);
10554
10526
  return {
10555
10527
  config,
10556
10528
  hungrySteps,