unpoly-rails 3.5.2 → 3.6.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.
@@ -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,