@hyperfixi/core 3.3.0 → 4.0.1
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/README.md +57 -179
- package/dist/ast-utils/index.cjs +74 -806
- package/dist/ast-utils/index.d.ts +1 -1
- package/dist/ast-utils/index.mjs +74 -805
- package/dist/ast-utils/interchange/engine-positions.d.ts +3 -0
- package/dist/ast-utils/interchange/index.d.ts +1 -2
- package/dist/hyperfixi.js +19 -2
- package/dist/index.d.ts +2 -22
- package/dist/index.mjs +3 -29128
- package/dist/lsp-metadata.cjs +77 -73
- package/dist/lsp-metadata.d.ts +4 -4
- package/dist/lsp-metadata.mjs +77 -73
- package/dist/metadata.cjs +34 -266
- package/dist/metadata.d.ts +31 -26
- package/dist/metadata.mjs +34 -266
- package/dist/multilingual/index.cjs +16 -382
- package/dist/multilingual/index.d.ts +4 -32
- package/dist/multilingual/index.mjs +15 -377
- package/dist/reference/index.cjs +67 -216
- package/dist/reference/index.d.ts +0 -3
- package/dist/reference/index.mjs +68 -216
- package/dist/version.d.ts +1 -1
- package/package.json +13 -179
- package/dist/__test-utils__/context-builders.d.ts +0 -42
- package/dist/__test-utils__/error-testing.d.ts +0 -18
- package/dist/__test-utils__/index.d.ts +0 -6
- package/dist/__test-utils__/mock-types.d.ts +0 -57
- package/dist/__test-utils__/parser-context-mock.d.ts +0 -7
- package/dist/__test-utils__/parser-helpers.d.ts +0 -38
- package/dist/api/hyperscript-api.d.ts +0 -90
- package/dist/api/lokascript-api.d.ts +0 -9
- package/dist/ast/command-slots.d.ts +0 -140
- package/dist/ast/guards.d.ts +0 -15
- package/dist/ast/legacy.d.ts +0 -15
- package/dist/ast/nodes.d.ts +0 -243
- package/dist/ast-utils/interchange/from-core.d.ts +0 -12
- package/dist/ast-utils/interchange/to-core.d.ts +0 -8
- package/dist/behaviors/boosted.d.ts +0 -29
- package/dist/behaviors/history-swap.d.ts +0 -24
- package/dist/behaviors/index.cjs +0 -1155
- package/dist/behaviors/index.d.ts +0 -4
- package/dist/behaviors/index.mjs +0 -1145
- package/dist/bundle-generator/executor-core.d.ts +0 -4
- package/dist/bundle-generator/generator.d.ts +0 -4
- package/dist/bundle-generator/index.cjs +0 -2804
- package/dist/bundle-generator/index.d.ts +0 -6
- package/dist/bundle-generator/index.mjs +0 -2779
- package/dist/bundle-generator/parser-templates.d.ts +0 -6
- package/dist/bundle-generator/template-capabilities.d.ts +0 -12
- package/dist/bundle-generator/templates.d.ts +0 -12
- package/dist/bundle-generator/types.d.ts +0 -34
- package/dist/chunks/bridge-CI9SOl8u.js +0 -2
- package/dist/chunks/browser-modular-7CpI5VF2.js +0 -2
- package/dist/chunks/index-BwXDEK0m.js +0 -2
- package/dist/chunks/index-DQi2o8Lk.js +0 -2
- package/dist/chunks/index-uCOQ8Qn0.js +0 -2
- package/dist/commands/advanced/js.d.ts +0 -40
- package/dist/commands/animation/measure.d.ts +0 -43
- package/dist/commands/animation/settle.d.ts +0 -38
- package/dist/commands/animation/start-view-transition.d.ts +0 -38
- package/dist/commands/animation/take.d.ts +0 -41
- package/dist/commands/animation/transition.d.ts +0 -49
- package/dist/commands/async/fetch.d.ts +0 -61
- package/dist/commands/async/wait.d.ts +0 -51
- package/dist/commands/behaviors/install.d.ts +0 -40
- package/dist/commands/content/append.d.ts +0 -26
- package/dist/commands/content/insertion-base.d.ts +0 -60
- package/dist/commands/content/prepend.d.ts +0 -26
- package/dist/commands/control-flow/break.d.ts +0 -29
- package/dist/commands/control-flow/continue.d.ts +0 -29
- package/dist/commands/control-flow/exit.d.ts +0 -29
- package/dist/commands/control-flow/halt.d.ts +0 -39
- package/dist/commands/control-flow/if.d.ts +0 -58
- package/dist/commands/control-flow/repeat.d.ts +0 -50
- package/dist/commands/control-flow/return.d.ts +0 -33
- package/dist/commands/control-flow/signal-base.d.ts +0 -18
- package/dist/commands/control-flow/throw.d.ts +0 -34
- package/dist/commands/control-flow/unless.d.ts +0 -3
- package/dist/commands/data/clear.d.ts +0 -37
- package/dist/commands/data/decrement.d.ts +0 -3
- package/dist/commands/data/default.d.ts +0 -60
- package/dist/commands/data/get.d.ts +0 -35
- package/dist/commands/data/increment.d.ts +0 -42
- package/dist/commands/data/set.d.ts +0 -76
- package/dist/commands/decorators/index.d.ts +0 -14
- package/dist/commands/dom/add.d.ts +0 -44
- package/dist/commands/dom/close.d.ts +0 -32
- package/dist/commands/dom/dom-modification-base.d.ts +0 -48
- package/dist/commands/dom/empty.d.ts +0 -32
- package/dist/commands/dom/hide.d.ts +0 -28
- package/dist/commands/dom/make.d.ts +0 -34
- package/dist/commands/dom/open.d.ts +0 -34
- package/dist/commands/dom/process-partials.d.ts +0 -51
- package/dist/commands/dom/put.d.ts +0 -42
- package/dist/commands/dom/remove.d.ts +0 -46
- package/dist/commands/dom/reset.d.ts +0 -32
- package/dist/commands/dom/select.d.ts +0 -32
- package/dist/commands/dom/show.d.ts +0 -29
- package/dist/commands/dom/swap.d.ts +0 -65
- package/dist/commands/dom/toggle.d.ts +0 -69
- package/dist/commands/dom/visibility-base.d.ts +0 -22
- package/dist/commands/events/send.d.ts +0 -3
- package/dist/commands/events/trigger.d.ts +0 -49
- package/dist/commands/execution/blur.d.ts +0 -32
- package/dist/commands/execution/call.d.ts +0 -35
- package/dist/commands/execution/focus.d.ts +0 -32
- package/dist/commands/execution/pseudo-command.d.ts +0 -41
- package/dist/commands/helpers/attribute-manipulation.d.ts +0 -11
- package/dist/commands/helpers/attribute-target.d.ts +0 -9
- package/dist/commands/helpers/batch-dom-operations.d.ts +0 -12
- package/dist/commands/helpers/body-ops.d.ts +0 -10
- package/dist/commands/helpers/class-manipulation.d.ts +0 -11
- package/dist/commands/helpers/condition-helpers.d.ts +0 -4
- package/dist/commands/helpers/dom-mutation.d.ts +0 -16
- package/dist/commands/helpers/duration-parsing.d.ts +0 -8
- package/dist/commands/helpers/element-property-access.d.ts +0 -7
- package/dist/commands/helpers/element-resolution.d.ts +0 -16
- package/dist/commands/helpers/error-helpers.d.ts +0 -17
- package/dist/commands/helpers/event-helpers.d.ts +0 -13
- package/dist/commands/helpers/event-waiting.d.ts +0 -37
- package/dist/commands/helpers/index.d.ts +0 -32
- package/dist/commands/helpers/input-validator.d.ts +0 -23
- package/dist/commands/helpers/loop-executor.d.ts +0 -56
- package/dist/commands/helpers/numeric-target-parser.d.ts +0 -21
- package/dist/commands/helpers/property-target.d.ts +0 -20
- package/dist/commands/helpers/selector-type-detection.d.ts +0 -24
- package/dist/commands/helpers/slots.d.ts +0 -5
- package/dist/commands/helpers/smart-element.d.ts +0 -16
- package/dist/commands/helpers/style-manipulation.d.ts +0 -16
- package/dist/commands/helpers/target-elements.d.ts +0 -5
- package/dist/commands/helpers/temporal-modifiers.d.ts +0 -15
- package/dist/commands/helpers/url-argument-parser.d.ts +0 -13
- package/dist/commands/helpers/url-validation.d.ts +0 -7
- package/dist/commands/helpers/variable-access.d.ts +0 -13
- package/dist/commands/helpers/visibility-target-parser.d.ts +0 -15
- package/dist/commands/helpers/write-target.d.ts +0 -42
- package/dist/commands/index.cjs +0 -24168
- package/dist/commands/index.d.ts +0 -171
- package/dist/commands/index.mjs +0 -23981
- package/dist/commands/manifest.d.ts +0 -17
- package/dist/commands/navigation/go.d.ts +0 -58
- package/dist/commands/navigation/push-url.d.ts +0 -48
- package/dist/commands/navigation/replace-url.d.ts +0 -3
- package/dist/commands/navigation/scroll-to.d.ts +0 -43
- package/dist/commands/templates/render.d.ts +0 -47
- package/dist/commands/utility/beep.d.ts +0 -41
- package/dist/commands/utility/breakpoint.d.ts +0 -32
- package/dist/commands/utility/copy.d.ts +0 -41
- package/dist/commands/utility/log.d.ts +0 -36
- package/dist/commands/utility/pick.d.ts +0 -47
- package/dist/commands/utility/tell.d.ts +0 -39
- package/dist/compatibility/browser-bundle-classic.d.ts +0 -17
- package/dist/compatibility/browser-bundle-hybrid-complete.d.ts +0 -22
- package/dist/compatibility/browser-bundle-hybrid-hx.d.ts +0 -43
- package/dist/compatibility/browser-bundle-lite.d.ts +0 -15
- package/dist/compatibility/browser-bundle-modular.d.ts +0 -18
- package/dist/compatibility/browser-bundle-multilingual.d.ts +0 -19
- package/dist/compatibility/browser-bundle-semantic-complete.d.ts +0 -24
- package/dist/compatibility/browser-bundle-textshelf-minimal.d.ts +0 -16
- package/dist/compatibility/browser-bundle-textshelf-profile.d.ts +0 -18
- package/dist/compatibility/browser-modular.d.ts +0 -42
- package/dist/compatibility/browser-tests/helpers/semantic-page.d.ts +0 -3
- package/dist/compatibility/browser-tests/test-utils.d.ts +0 -21
- package/dist/compatibility/bundle-shell.d.ts +0 -13
- package/dist/compatibility/bundle-sources.d.ts +0 -4
- package/dist/compatibility/eval-hyperscript.d.ts +0 -16
- package/dist/compatibility/hyperscript-adapter.d.ts +0 -38
- package/dist/core/ast-property-utils.d.ts +0 -2
- package/dist/core/context.d.ts +0 -19
- package/dist/core/dom.d.ts +0 -15
- package/dist/core/evaluator-types.d.ts +0 -5
- package/dist/core/events.d.ts +0 -48
- package/dist/core/executor.d.ts +0 -34
- package/dist/core/expression-evaluator.d.ts +0 -6
- package/dist/core/expression-registry.d.ts +0 -8
- package/dist/core/scope-hooks.d.ts +0 -24
- package/dist/debug/debug-controller.d.ts +0 -62
- package/dist/debug/index.d.ts +0 -5
- package/dist/dom/attribute-processor.d.ts +0 -75
- package/dist/dom/detect-language.d.ts +0 -3
- package/dist/dom/minimal-attribute-processor.d.ts +0 -20
- package/dist/expressions/base-expression.d.ts +0 -27
- package/dist/expressions/bundles/common-expressions.d.ts +0 -10
- package/dist/expressions/bundles/core-expressions.d.ts +0 -8
- package/dist/expressions/bundles/full-expressions.d.ts +0 -11
- package/dist/expressions/bundles/index.d.ts +0 -7
- package/dist/expressions/collection/index.d.ts +0 -10
- package/dist/expressions/conversion/index.d.ts +0 -31
- package/dist/expressions/expression-tiers.d.ts +0 -13
- package/dist/expressions/index.cjs +0 -4331
- package/dist/expressions/index.d.ts +0 -13
- package/dist/expressions/index.mjs +0 -4312
- package/dist/expressions/logical/index.d.ts +0 -61
- package/dist/expressions/mathematical/index.d.ts +0 -80
- package/dist/expressions/positional/index.d.ts +0 -31
- package/dist/expressions/properties/index.d.ts +0 -27
- package/dist/expressions/property-access-utils.d.ts +0 -23
- package/dist/expressions/references/index.d.ts +0 -39
- package/dist/expressions/shared/comparison-utils.d.ts +0 -10
- package/dist/expressions/shared/index.d.ts +0 -10
- package/dist/expressions/shared/number-utils.d.ts +0 -8
- package/dist/expressions/shared/tracking.d.ts +0 -20
- package/dist/expressions/shared/validation-utils.d.ts +0 -13
- package/dist/expressions/special/index.d.ts +0 -78
- package/dist/expressions/type-helpers.d.ts +0 -11
- package/dist/expressions/type-registry.d.ts +0 -57
- package/dist/expressions/validation-helpers.d.ts +0 -15
- package/dist/htmx/hcon.d.ts +0 -9
- package/dist/htmx/htmx-attribute-processor.d.ts +0 -120
- package/dist/htmx/htmx-translator.d.ts +0 -22
- package/dist/htmx/i18n-hooks.d.ts +0 -18
- package/dist/htmx/i18n-orchestrator.d.ts +0 -16
- package/dist/htmx/index.d.ts +0 -3
- package/dist/htmx/lang-resolver.d.ts +0 -3
- package/dist/htmx/sse.d.ts +0 -60
- package/dist/htmx/ws.d.ts +0 -59
- package/dist/hyperfixi-browser-classic-i18n.js +0 -2
- package/dist/hyperfixi-browser.js +0 -2
- package/dist/hyperfixi-classic-i18n.js +0 -2
- package/dist/hyperfixi-hx-v4.js +0 -1
- package/dist/hyperfixi-hx.js +0 -1
- package/dist/hyperfixi-hybrid-complete.js +0 -1
- package/dist/hyperfixi-hybrid-hx.js +0 -1
- package/dist/hyperfixi-multilingual.js +0 -2
- package/dist/hyperfixi.mjs +0 -2
- package/dist/i18n/error-catalog.d.ts +0 -12
- package/dist/index.cjs +0 -29159
- package/dist/index.min.js +0 -2
- package/dist/lib/dom-globals-shim.d.ts +0 -2
- package/dist/lib/index.d.ts +0 -4
- package/dist/lib/morph-adapter.d.ts +0 -9
- package/dist/lib/swap-executor.d.ts +0 -12
- package/dist/lib/view-transitions.d.ts +0 -7
- package/dist/lokascript-browser-classic-i18n.js +0 -2
- package/dist/lokascript-browser.js +0 -2
- package/dist/lokascript-hybrid-complete.js +0 -1
- package/dist/lokascript-hybrid-hx.js +0 -1
- package/dist/lokascript-multilingual.js +0 -2
- package/dist/lse/index.cjs +0 -84
- package/dist/lse/index.d.ts +0 -15
- package/dist/lse/index.mjs +0 -71
- package/dist/multilingual/bridge.d.ts +0 -38
- package/dist/multilingual/schema-roles.d.ts +0 -3
- package/dist/parser/__types__/test-helpers.d.ts +0 -25
- package/dist/parser/command-grammar.d.ts +0 -14
- package/dist/parser/command-node-builder.d.ts +0 -46
- package/dist/parser/command-parsers/animation-commands.d.ts +0 -6
- package/dist/parser/command-parsers/async-commands.d.ts +0 -5
- package/dist/parser/command-parsers/control-flow-commands.d.ts +0 -7
- package/dist/parser/command-parsers/declared-commands.d.ts +0 -6
- package/dist/parser/command-parsers/dom-commands.d.ts +0 -11
- package/dist/parser/command-parsers/event-commands.d.ts +0 -4
- package/dist/parser/command-parsers/navigation-commands.d.ts +0 -6
- package/dist/parser/command-parsers/utility-commands.d.ts +0 -14
- package/dist/parser/command-parsers/variable-commands.d.ts +0 -12
- package/dist/parser/error-handler.d.ts +0 -34
- package/dist/parser/extensions.d.ts +0 -43
- package/dist/parser/full-parser.cjs +0 -7943
- package/dist/parser/full-parser.d.ts +0 -4
- package/dist/parser/full-parser.mjs +0 -7940
- package/dist/parser/helpers/ast-helpers.d.ts +0 -24
- package/dist/parser/helpers/parsing-helpers.d.ts +0 -19
- package/dist/parser/helpers/token-helpers.d.ts +0 -28
- package/dist/parser/hybrid/aliases.cjs +0 -44
- package/dist/parser/hybrid/aliases.d.ts +0 -7
- package/dist/parser/hybrid/aliases.mjs +0 -37
- package/dist/parser/hybrid/ast-types.cjs +0 -3
- package/dist/parser/hybrid/ast-types.d.ts +0 -97
- package/dist/parser/hybrid/ast-types.mjs +0 -2
- package/dist/parser/hybrid/index.cjs +0 -1185
- package/dist/parser/hybrid/index.d.ts +0 -6
- package/dist/parser/hybrid/index.mjs +0 -1175
- package/dist/parser/hybrid/parser-core.cjs +0 -1171
- package/dist/parser/hybrid/parser-core.d.ts +0 -69
- package/dist/parser/hybrid/parser-core.mjs +0 -1169
- package/dist/parser/hybrid/tokenizer.cjs +0 -255
- package/dist/parser/hybrid/tokenizer.d.ts +0 -9
- package/dist/parser/hybrid/tokenizer.mjs +0 -252
- package/dist/parser/hybrid-parser.cjs +0 -1249
- package/dist/parser/hybrid-parser.d.ts +0 -10
- package/dist/parser/hybrid-parser.mjs +0 -1242
- package/dist/parser/parser-constants.d.ts +0 -100
- package/dist/parser/parser-interface.d.ts +0 -12
- package/dist/parser/parser-types.d.ts +0 -164
- package/dist/parser/parser.d.ts +0 -165
- package/dist/parser/pratt-parser.d.ts +0 -41
- package/dist/parser/regex-parser.cjs +0 -422
- package/dist/parser/regex-parser.d.ts +0 -4
- package/dist/parser/regex-parser.mjs +0 -419
- package/dist/parser/runtime.d.ts +0 -14
- package/dist/parser/semantic-integration.d.ts +0 -17
- package/dist/parser/token-consumer.d.ts +0 -34
- package/dist/parser/token-predicates.d.ts +0 -77
- package/dist/parser/tokenizer.d.ts +0 -28
- package/dist/parser/types.d.ts +0 -105
- package/dist/performance/expression-cache.d.ts +0 -78
- package/dist/performance/integration.d.ts +0 -40
- package/dist/performance/production-monitor.d.ts +0 -67
- package/dist/registry/browser-types.cjs +0 -81
- package/dist/registry/browser-types.d.ts +0 -20
- package/dist/registry/browser-types.mjs +0 -76
- package/dist/registry/environment.cjs +0 -36
- package/dist/registry/environment.d.ts +0 -19
- package/dist/registry/environment.mjs +0 -30
- package/dist/registry/event-source-registry.d.ts +0 -54
- package/dist/registry/examples/server-commands.d.ts +0 -6
- package/dist/registry/examples/server-event-source.d.ts +0 -32
- package/dist/registry/index.cjs +0 -14055
- package/dist/registry/index.d.ts +0 -39
- package/dist/registry/index.mjs +0 -14039
- package/dist/registry/runtime-integration.d.ts +0 -23
- package/dist/registry/universal-types.cjs +0 -91
- package/dist/registry/universal-types.d.ts +0 -35
- package/dist/registry/universal-types.mjs +0 -86
- package/dist/runtime/cleanup-registry.d.ts +0 -47
- package/dist/runtime/command-adapter.d.ts +0 -69
- package/dist/runtime/environment.d.ts +0 -75
- package/dist/runtime/plugin.d.ts +0 -14
- package/dist/runtime/runtime-base.d.ts +0 -100
- package/dist/runtime/runtime-factory.d.ts +0 -29
- package/dist/runtime/runtime.d.ts +0 -20
- package/dist/runtime/temporal-modifiers.d.ts +0 -37
- package/dist/test-setup.d.ts +0 -28
- package/dist/test-utilities.d.ts +0 -39
- package/dist/types/base-types.d.ts +0 -231
- package/dist/types/code-fix.d.ts +0 -39
- package/dist/types/command-metadata.d.ts +0 -57
- package/dist/types/command-types.d.ts +0 -262
- package/dist/types/context-types.d.ts +0 -106
- package/dist/types/core-context.d.ts +0 -22
- package/dist/types/core.d.ts +0 -143
- package/dist/types/error-codes.d.ts +0 -207
- package/dist/types/expression-types.d.ts +0 -155
- package/dist/types/hooks.d.ts +0 -45
- package/dist/types/index.d.ts +0 -32
- package/dist/types/program.d.ts +0 -8
- package/dist/types/result.d.ts +0 -73
- package/dist/types/template-types.d.ts +0 -162
- package/dist/types/type-guards.d.ts +0 -24
- package/dist/types/unified-types.d.ts +0 -91
- package/dist/utils/beep.d.ts +0 -8
- package/dist/utils/debug-events.d.ts +0 -41
- package/dist/utils/debug.d.ts +0 -35
- package/dist/utils/dom-utils.d.ts +0 -16
- package/dist/utils/element-check.d.ts +0 -8
- package/dist/utils/keyboard-shortcuts.d.ts +0 -18
- package/dist/utils/performance.d.ts +0 -40
- package/dist/validation/command-pattern-validator.d.ts +0 -53
- package/dist/validation/common-validators.d.ts +0 -24
- package/dist/validation/lightweight-validators.d.ts +0 -113
- package/dist/validation/partial-validation-types.d.ts +0 -50
- package/dist/validation/partial-validator.d.ts +0 -6
- package/dist/validation/partial-warning-formatter.d.ts +0 -6
- package/dist/validation/validate-cli.d.ts +0 -41
- package/vocab/htmx/ar.js +0 -62
- package/vocab/htmx/bn.js +0 -65
- package/vocab/htmx/de.js +0 -83
- package/vocab/htmx/en.js +0 -24
- package/vocab/htmx/es.js +0 -79
- package/vocab/htmx/fr.js +0 -79
- package/vocab/htmx/he.js +0 -61
- package/vocab/htmx/hi.js +0 -81
- package/vocab/htmx/id.js +0 -76
- package/vocab/htmx/it.js +0 -79
- package/vocab/htmx/ja.js +0 -85
- package/vocab/htmx/ko.js +0 -81
- package/vocab/htmx/ms.js +0 -58
- package/vocab/htmx/pl.js +0 -80
- package/vocab/htmx/pt.js +0 -81
- package/vocab/htmx/qu.js +0 -83
- package/vocab/htmx/ru.js +0 -82
- package/vocab/htmx/sw.js +0 -79
- package/vocab/htmx/th.js +0 -67
- package/vocab/htmx/tl.js +0 -56
- package/vocab/htmx/tr.js +0 -86
- package/vocab/htmx/uk.js +0 -82
- package/vocab/htmx/vi.js +0 -59
- package/vocab/htmx/zh.js +0 -79
package/dist/behaviors/index.mjs
DELETED
|
@@ -1,1145 +0,0 @@
|
|
|
1
|
-
function ensureDomGlobals() {
|
|
2
|
-
if (typeof globalThis.Element === 'undefined') {
|
|
3
|
-
globalThis.Element = class {
|
|
4
|
-
};
|
|
5
|
-
}
|
|
6
|
-
return true;
|
|
7
|
-
}
|
|
8
|
-
ensureDomGlobals();
|
|
9
|
-
|
|
10
|
-
// src/morphlex.ts
|
|
11
|
-
var SUPPORTS_MOVE_BEFORE = "moveBefore" in Element.prototype;
|
|
12
|
-
var ELEMENT_NODE_TYPE = 1;
|
|
13
|
-
var TEXT_NODE_TYPE = 3;
|
|
14
|
-
var IS_PARENT_NODE_TYPE = [
|
|
15
|
-
0,
|
|
16
|
-
1,
|
|
17
|
-
0,
|
|
18
|
-
0,
|
|
19
|
-
0,
|
|
20
|
-
0,
|
|
21
|
-
0,
|
|
22
|
-
0,
|
|
23
|
-
0,
|
|
24
|
-
1,
|
|
25
|
-
0,
|
|
26
|
-
1,
|
|
27
|
-
0
|
|
28
|
-
];
|
|
29
|
-
var Operation = {
|
|
30
|
-
EqualNode: 0,
|
|
31
|
-
SameElement: 1,
|
|
32
|
-
SameNode: 2
|
|
33
|
-
};
|
|
34
|
-
var candidateNodes = new Set;
|
|
35
|
-
var candidateElements = new Set;
|
|
36
|
-
var candidateElementsWithIds = new Set;
|
|
37
|
-
var unmatchedNodes = new Set;
|
|
38
|
-
var unmatchedElements = new Set;
|
|
39
|
-
var whitespaceNodes = new Set;
|
|
40
|
-
function morph(from, to, options = {}) {
|
|
41
|
-
if (typeof to === "string")
|
|
42
|
-
to = parseFragment(to).childNodes;
|
|
43
|
-
if (!options.preserveChanges && isParentNode(from))
|
|
44
|
-
flagDirtyInputs(from);
|
|
45
|
-
new Morph(options).morph(from, to);
|
|
46
|
-
}
|
|
47
|
-
function morphInner(from, to, options = {}) {
|
|
48
|
-
if (typeof to === "string") {
|
|
49
|
-
const fragment = parseFragment(to);
|
|
50
|
-
if (fragment.firstChild && fragment.childNodes.length === 1 && fragment.firstChild.nodeType === ELEMENT_NODE_TYPE) {
|
|
51
|
-
to = fragment.firstChild;
|
|
52
|
-
} else {
|
|
53
|
-
throw new Error("[Morphlex] The string was not a valid HTML element.");
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
if (from.nodeType === ELEMENT_NODE_TYPE && to.nodeType === ELEMENT_NODE_TYPE && from.localName === to.localName) {
|
|
57
|
-
if (isParentNode(from))
|
|
58
|
-
flagDirtyInputs(from);
|
|
59
|
-
new Morph(options).visitChildNodes(from, to);
|
|
60
|
-
} else {
|
|
61
|
-
throw new Error("[Morphlex] You can only do an inner morph with matching elements.");
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function flagDirtyInputs(node) {
|
|
65
|
-
for (const input of node.querySelectorAll("input")) {
|
|
66
|
-
if (input.name && input.value !== input.defaultValue || input.checked !== input.defaultChecked) {
|
|
67
|
-
input.setAttribute("morphlex-dirty", "");
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
for (const element of node.querySelectorAll("option")) {
|
|
71
|
-
if (element.value && element.selected !== element.defaultSelected) {
|
|
72
|
-
element.setAttribute("morphlex-dirty", "");
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
for (const element of node.querySelectorAll("textarea")) {
|
|
76
|
-
if (element.value !== element.defaultValue) {
|
|
77
|
-
element.setAttribute("morphlex-dirty", "");
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function parseFragment(string) {
|
|
82
|
-
const template = document.createElement("template");
|
|
83
|
-
template.innerHTML = string.trim();
|
|
84
|
-
return template.content;
|
|
85
|
-
}
|
|
86
|
-
function moveBefore(parent, node, insertionPoint) {
|
|
87
|
-
if (node === insertionPoint)
|
|
88
|
-
return;
|
|
89
|
-
if (node.parentNode === parent) {
|
|
90
|
-
if (node.nextSibling === insertionPoint)
|
|
91
|
-
return;
|
|
92
|
-
if (SUPPORTS_MOVE_BEFORE) {
|
|
93
|
-
parent.moveBefore(node, insertionPoint);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
parent.insertBefore(node, insertionPoint);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
class Morph {
|
|
101
|
-
#idArrayMap = new WeakMap;
|
|
102
|
-
#idSetMap = new WeakMap;
|
|
103
|
-
#options;
|
|
104
|
-
constructor(options = {}) {
|
|
105
|
-
this.#options = options;
|
|
106
|
-
}
|
|
107
|
-
morph(from, to) {
|
|
108
|
-
if (isParentNode(from)) {
|
|
109
|
-
this.#mapIdSets(from);
|
|
110
|
-
}
|
|
111
|
-
if (to instanceof NodeList) {
|
|
112
|
-
this.#mapIdArraysForEach(to);
|
|
113
|
-
this.#morphOneToMany(from, to);
|
|
114
|
-
} else if (isParentNode(to)) {
|
|
115
|
-
this.#mapIdArrays(to);
|
|
116
|
-
this.#morphOneToOne(from, to);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
#morphOneToMany(from, to) {
|
|
120
|
-
const length = to.length;
|
|
121
|
-
if (length === 0) {
|
|
122
|
-
this.#removeNode(from);
|
|
123
|
-
} else if (length === 1) {
|
|
124
|
-
this.#morphOneToOne(from, to[0]);
|
|
125
|
-
} else if (length > 1) {
|
|
126
|
-
const newNodes = [...to];
|
|
127
|
-
this.#morphOneToOne(from, newNodes.shift());
|
|
128
|
-
const insertionPoint = from.nextSibling;
|
|
129
|
-
const parent = from.parentNode || document;
|
|
130
|
-
for (let i = 0;i < newNodes.length; i++) {
|
|
131
|
-
const newNode = newNodes[i];
|
|
132
|
-
if (this.#options.beforeNodeAdded?.(parent, newNode, insertionPoint) ?? true) {
|
|
133
|
-
parent.insertBefore(newNode, insertionPoint);
|
|
134
|
-
this.#options.afterNodeAdded?.(newNode);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
#morphOneToOne(from, to) {
|
|
140
|
-
if (from === to)
|
|
141
|
-
return;
|
|
142
|
-
if (from.isEqualNode(to))
|
|
143
|
-
return;
|
|
144
|
-
if (from.nodeType === ELEMENT_NODE_TYPE && to.nodeType === ELEMENT_NODE_TYPE) {
|
|
145
|
-
if (from.localName === to.localName) {
|
|
146
|
-
this.#morphMatchingElements(from, to);
|
|
147
|
-
} else {
|
|
148
|
-
this.#morphNonMatchingElements(from, to);
|
|
149
|
-
}
|
|
150
|
-
} else {
|
|
151
|
-
this.#morphOtherNode(from, to);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
#morphMatchingElements(from, to) {
|
|
155
|
-
if (!(this.#options.beforeNodeVisited?.(from, to) ?? true))
|
|
156
|
-
return;
|
|
157
|
-
if (from.hasAttributes() || to.hasAttributes()) {
|
|
158
|
-
this.#visitAttributes(from, to);
|
|
159
|
-
}
|
|
160
|
-
if (from.localName === "textarea" && to.localName === "textarea") {
|
|
161
|
-
this.#visitTextArea(from, to);
|
|
162
|
-
} else if (from.hasChildNodes() || to.hasChildNodes()) {
|
|
163
|
-
this.visitChildNodes(from, to);
|
|
164
|
-
}
|
|
165
|
-
this.#options.afterNodeVisited?.(from, to);
|
|
166
|
-
}
|
|
167
|
-
#morphNonMatchingElements(from, to) {
|
|
168
|
-
if (!(this.#options.beforeNodeVisited?.(from, to) ?? true))
|
|
169
|
-
return;
|
|
170
|
-
this.#replaceNode(from, to);
|
|
171
|
-
this.#options.afterNodeVisited?.(from, to);
|
|
172
|
-
}
|
|
173
|
-
#morphOtherNode(from, to) {
|
|
174
|
-
if (!(this.#options.beforeNodeVisited?.(from, to) ?? true))
|
|
175
|
-
return;
|
|
176
|
-
if (from.nodeType === to.nodeType && from.nodeValue !== null && to.nodeValue !== null) {
|
|
177
|
-
from.nodeValue = to.nodeValue;
|
|
178
|
-
} else {
|
|
179
|
-
this.#replaceNode(from, to);
|
|
180
|
-
}
|
|
181
|
-
this.#options.afterNodeVisited?.(from, to);
|
|
182
|
-
}
|
|
183
|
-
#visitAttributes(from, to) {
|
|
184
|
-
if (from.hasAttribute("morphlex-dirty")) {
|
|
185
|
-
from.removeAttribute("morphlex-dirty");
|
|
186
|
-
}
|
|
187
|
-
for (const { name, value } of to.attributes) {
|
|
188
|
-
if (name === "value") {
|
|
189
|
-
if (isInputElement(from) && from.value !== value) {
|
|
190
|
-
if (!this.#options.preserveChanges || from.value === from.defaultValue) {
|
|
191
|
-
from.value = value;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
if (name === "selected") {
|
|
196
|
-
if (isOptionElement(from) && !from.selected) {
|
|
197
|
-
if (!this.#options.preserveChanges || from.selected === from.defaultSelected) {
|
|
198
|
-
from.selected = true;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
if (name === "checked") {
|
|
203
|
-
if (isInputElement(from) && !from.checked) {
|
|
204
|
-
if (!this.#options.preserveChanges || from.checked === from.defaultChecked) {
|
|
205
|
-
from.checked = true;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
const oldValue = from.getAttribute(name);
|
|
210
|
-
if (oldValue !== value && (this.#options.beforeAttributeUpdated?.(from, name, value) ?? true)) {
|
|
211
|
-
from.setAttribute(name, value);
|
|
212
|
-
this.#options.afterAttributeUpdated?.(from, name, oldValue);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
for (const { name, value } of from.attributes) {
|
|
216
|
-
if (!to.hasAttribute(name)) {
|
|
217
|
-
if (name === "selected") {
|
|
218
|
-
if (isOptionElement(from) && from.selected) {
|
|
219
|
-
if (!this.#options.preserveChanges || from.selected === from.defaultSelected) {
|
|
220
|
-
from.selected = false;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
if (name === "checked") {
|
|
225
|
-
if (isInputElement(from) && from.checked) {
|
|
226
|
-
if (!this.#options.preserveChanges || from.checked === from.defaultChecked) {
|
|
227
|
-
from.checked = false;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
if (this.#options.beforeAttributeUpdated?.(from, name, null) ?? true) {
|
|
232
|
-
from.removeAttribute(name);
|
|
233
|
-
this.#options.afterAttributeUpdated?.(from, name, value);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
#visitTextArea(from, to) {
|
|
239
|
-
const newTextContent = to.textContent || "";
|
|
240
|
-
const isModified = from.value !== from.defaultValue;
|
|
241
|
-
if (from.textContent !== newTextContent) {
|
|
242
|
-
from.textContent = newTextContent;
|
|
243
|
-
}
|
|
244
|
-
if (this.#options.preserveChanges && isModified)
|
|
245
|
-
return;
|
|
246
|
-
from.value = from.defaultValue;
|
|
247
|
-
}
|
|
248
|
-
visitChildNodes(from, to) {
|
|
249
|
-
if (!(this.#options.beforeChildrenVisited?.(from) ?? true))
|
|
250
|
-
return;
|
|
251
|
-
const parent = from;
|
|
252
|
-
const fromChildNodes = [...from.childNodes];
|
|
253
|
-
const toChildNodes = [...to.childNodes];
|
|
254
|
-
candidateNodes.clear();
|
|
255
|
-
candidateElements.clear();
|
|
256
|
-
candidateElementsWithIds.clear();
|
|
257
|
-
unmatchedNodes.clear();
|
|
258
|
-
unmatchedElements.clear();
|
|
259
|
-
whitespaceNodes.clear();
|
|
260
|
-
const matches = [];
|
|
261
|
-
const op = [];
|
|
262
|
-
const nodeTypeMap = [];
|
|
263
|
-
const candidateNodeTypeMap = [];
|
|
264
|
-
const localNameMap = [];
|
|
265
|
-
const candidateLocalNameMap = [];
|
|
266
|
-
for (let i = 0;i < fromChildNodes.length; i++) {
|
|
267
|
-
const candidate = fromChildNodes[i];
|
|
268
|
-
const nodeType = candidate.nodeType;
|
|
269
|
-
candidateNodeTypeMap[i] = nodeType;
|
|
270
|
-
if (nodeType === ELEMENT_NODE_TYPE) {
|
|
271
|
-
candidateLocalNameMap[i] = candidate.localName;
|
|
272
|
-
if (candidate.id !== "") {
|
|
273
|
-
candidateElementsWithIds.add(i);
|
|
274
|
-
} else {
|
|
275
|
-
candidateElements.add(i);
|
|
276
|
-
}
|
|
277
|
-
} else if (nodeType === TEXT_NODE_TYPE && candidate.textContent?.trim() === "") {
|
|
278
|
-
whitespaceNodes.add(i);
|
|
279
|
-
} else {
|
|
280
|
-
candidateNodes.add(i);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
for (let i = 0;i < toChildNodes.length; i++) {
|
|
284
|
-
const node = toChildNodes[i];
|
|
285
|
-
const nodeType = node.nodeType;
|
|
286
|
-
nodeTypeMap[i] = nodeType;
|
|
287
|
-
if (nodeType === ELEMENT_NODE_TYPE) {
|
|
288
|
-
localNameMap[i] = node.localName;
|
|
289
|
-
unmatchedElements.add(i);
|
|
290
|
-
} else if (nodeType === TEXT_NODE_TYPE && node.textContent?.trim() === "") {
|
|
291
|
-
continue;
|
|
292
|
-
} else {
|
|
293
|
-
unmatchedNodes.add(i);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
for (const unmatchedIndex of unmatchedElements) {
|
|
297
|
-
const localName = localNameMap[unmatchedIndex];
|
|
298
|
-
const element = toChildNodes[unmatchedIndex];
|
|
299
|
-
for (const candidateIndex of candidateElements) {
|
|
300
|
-
if (localName !== candidateLocalNameMap[candidateIndex])
|
|
301
|
-
continue;
|
|
302
|
-
const candidate = fromChildNodes[candidateIndex];
|
|
303
|
-
if (candidate.isEqualNode(element)) {
|
|
304
|
-
matches[unmatchedIndex] = candidateIndex;
|
|
305
|
-
op[unmatchedIndex] = Operation.EqualNode;
|
|
306
|
-
candidateElements.delete(candidateIndex);
|
|
307
|
-
unmatchedElements.delete(unmatchedIndex);
|
|
308
|
-
break;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
for (const unmatchedIndex of unmatchedElements) {
|
|
313
|
-
const element = toChildNodes[unmatchedIndex];
|
|
314
|
-
const id = element.id;
|
|
315
|
-
const idArray = this.#idArrayMap.get(element);
|
|
316
|
-
if (id === "" && !idArray)
|
|
317
|
-
continue;
|
|
318
|
-
candidateLoop:
|
|
319
|
-
for (const candidateIndex of candidateElementsWithIds) {
|
|
320
|
-
const candidate = fromChildNodes[candidateIndex];
|
|
321
|
-
if (localNameMap[unmatchedIndex] === candidateLocalNameMap[candidateIndex]) {
|
|
322
|
-
if (id !== "" && id === candidate.id) {
|
|
323
|
-
matches[unmatchedIndex] = candidateIndex;
|
|
324
|
-
op[unmatchedIndex] = Operation.SameElement;
|
|
325
|
-
candidateElementsWithIds.delete(candidateIndex);
|
|
326
|
-
unmatchedElements.delete(unmatchedIndex);
|
|
327
|
-
break candidateLoop;
|
|
328
|
-
}
|
|
329
|
-
if (idArray) {
|
|
330
|
-
const candidateIdSet = this.#idSetMap.get(candidate);
|
|
331
|
-
if (candidateIdSet) {
|
|
332
|
-
for (let i = 0;i < idArray.length; i++) {
|
|
333
|
-
const arrayId = idArray[i];
|
|
334
|
-
if (candidateIdSet.has(arrayId)) {
|
|
335
|
-
matches[unmatchedIndex] = candidateIndex;
|
|
336
|
-
op[unmatchedIndex] = Operation.SameElement;
|
|
337
|
-
candidateElementsWithIds.delete(candidateIndex);
|
|
338
|
-
unmatchedElements.delete(unmatchedIndex);
|
|
339
|
-
break candidateLoop;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
for (const unmatchedIndex of unmatchedElements) {
|
|
348
|
-
const element = toChildNodes[unmatchedIndex];
|
|
349
|
-
const name = element.getAttribute("name");
|
|
350
|
-
const href = element.getAttribute("href");
|
|
351
|
-
const src = element.getAttribute("src");
|
|
352
|
-
for (const candidateIndex of candidateElements) {
|
|
353
|
-
const candidate = fromChildNodes[candidateIndex];
|
|
354
|
-
if (localNameMap[unmatchedIndex] === candidateLocalNameMap[candidateIndex] && (name && name === candidate.getAttribute("name") || href && href === candidate.getAttribute("href") || src && src === candidate.getAttribute("src"))) {
|
|
355
|
-
matches[unmatchedIndex] = candidateIndex;
|
|
356
|
-
op[unmatchedIndex] = Operation.SameElement;
|
|
357
|
-
candidateElements.delete(candidateIndex);
|
|
358
|
-
unmatchedElements.delete(unmatchedIndex);
|
|
359
|
-
break;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
for (const unmatchedIndex of unmatchedElements) {
|
|
364
|
-
const element = toChildNodes[unmatchedIndex];
|
|
365
|
-
const localName = localNameMap[unmatchedIndex];
|
|
366
|
-
for (const candidateIndex of candidateElements) {
|
|
367
|
-
const candidate = fromChildNodes[candidateIndex];
|
|
368
|
-
const candidateLocalName = candidateLocalNameMap[candidateIndex];
|
|
369
|
-
if (localName === candidateLocalName) {
|
|
370
|
-
if (localName === "input" && candidate.type !== element.type) {
|
|
371
|
-
continue;
|
|
372
|
-
}
|
|
373
|
-
matches[unmatchedIndex] = candidateIndex;
|
|
374
|
-
op[unmatchedIndex] = Operation.SameElement;
|
|
375
|
-
candidateElements.delete(candidateIndex);
|
|
376
|
-
unmatchedElements.delete(unmatchedIndex);
|
|
377
|
-
break;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
for (const unmatchedIndex of unmatchedNodes) {
|
|
382
|
-
const node = toChildNodes[unmatchedIndex];
|
|
383
|
-
for (const candidateIndex of candidateNodes) {
|
|
384
|
-
const candidate = fromChildNodes[candidateIndex];
|
|
385
|
-
if (candidate.isEqualNode(node)) {
|
|
386
|
-
matches[unmatchedIndex] = candidateIndex;
|
|
387
|
-
op[unmatchedIndex] = Operation.EqualNode;
|
|
388
|
-
candidateNodes.delete(candidateIndex);
|
|
389
|
-
unmatchedNodes.delete(unmatchedIndex);
|
|
390
|
-
break;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
for (const unmatchedIndex of unmatchedNodes) {
|
|
395
|
-
const nodeType = nodeTypeMap[unmatchedIndex];
|
|
396
|
-
for (const candidateIndex of candidateNodes) {
|
|
397
|
-
if (nodeType === candidateNodeTypeMap[candidateIndex]) {
|
|
398
|
-
matches[unmatchedIndex] = candidateIndex;
|
|
399
|
-
op[unmatchedIndex] = Operation.SameNode;
|
|
400
|
-
candidateNodes.delete(candidateIndex);
|
|
401
|
-
unmatchedNodes.delete(unmatchedIndex);
|
|
402
|
-
break;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
for (const i of candidateNodes)
|
|
407
|
-
this.#removeNode(fromChildNodes[i]);
|
|
408
|
-
for (const i of whitespaceNodes)
|
|
409
|
-
this.#removeNode(fromChildNodes[i]);
|
|
410
|
-
for (const i of candidateElements)
|
|
411
|
-
this.#removeNode(fromChildNodes[i]);
|
|
412
|
-
for (const i of candidateElementsWithIds)
|
|
413
|
-
this.#removeNode(fromChildNodes[i]);
|
|
414
|
-
const lisIndices = longestIncreasingSubsequence(matches);
|
|
415
|
-
const shouldNotMove = new Array(fromChildNodes.length);
|
|
416
|
-
for (let i = 0;i < lisIndices.length; i++) {
|
|
417
|
-
shouldNotMove[matches[lisIndices[i]]] = true;
|
|
418
|
-
}
|
|
419
|
-
let insertionPoint = parent.firstChild;
|
|
420
|
-
for (let i = 0;i < toChildNodes.length; i++) {
|
|
421
|
-
const node = toChildNodes[i];
|
|
422
|
-
const matchInd = matches[i];
|
|
423
|
-
if (matchInd !== undefined) {
|
|
424
|
-
const match = fromChildNodes[matchInd];
|
|
425
|
-
const operation = op[i];
|
|
426
|
-
if (!shouldNotMove[matchInd]) {
|
|
427
|
-
moveBefore(parent, match, insertionPoint);
|
|
428
|
-
}
|
|
429
|
-
if (operation === Operation.EqualNode) ; else if (operation === Operation.SameElement) {
|
|
430
|
-
this.#morphMatchingElements(match, node);
|
|
431
|
-
} else {
|
|
432
|
-
this.#morphOneToOne(match, node);
|
|
433
|
-
}
|
|
434
|
-
insertionPoint = match.nextSibling;
|
|
435
|
-
} else {
|
|
436
|
-
if (this.#options.beforeNodeAdded?.(parent, node, insertionPoint) ?? true) {
|
|
437
|
-
parent.insertBefore(node, insertionPoint);
|
|
438
|
-
this.#options.afterNodeAdded?.(node);
|
|
439
|
-
insertionPoint = node.nextSibling;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
this.#options.afterChildrenVisited?.(from);
|
|
444
|
-
}
|
|
445
|
-
#replaceNode(node, newNode) {
|
|
446
|
-
const parent = node.parentNode || document;
|
|
447
|
-
const insertionPoint = node;
|
|
448
|
-
if ((this.#options.beforeNodeRemoved?.(node) ?? true) && (this.#options.beforeNodeAdded?.(parent, newNode, insertionPoint) ?? true)) {
|
|
449
|
-
parent.insertBefore(newNode, insertionPoint);
|
|
450
|
-
this.#options.afterNodeAdded?.(newNode);
|
|
451
|
-
node.remove();
|
|
452
|
-
this.#options.afterNodeRemoved?.(node);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
#removeNode(node) {
|
|
456
|
-
if (this.#options.beforeNodeRemoved?.(node) ?? true) {
|
|
457
|
-
node.remove();
|
|
458
|
-
this.#options.afterNodeRemoved?.(node);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
#mapIdArraysForEach(nodeList) {
|
|
462
|
-
for (const childNode of nodeList) {
|
|
463
|
-
if (isParentNode(childNode)) {
|
|
464
|
-
this.#mapIdArrays(childNode);
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
#mapIdArrays(node) {
|
|
469
|
-
const idArrayMap = this.#idArrayMap;
|
|
470
|
-
for (const element of node.querySelectorAll("[id]")) {
|
|
471
|
-
const id = element.id;
|
|
472
|
-
if (id === "")
|
|
473
|
-
continue;
|
|
474
|
-
let currentElement = element;
|
|
475
|
-
while (currentElement) {
|
|
476
|
-
const idArray = idArrayMap.get(currentElement);
|
|
477
|
-
if (idArray) {
|
|
478
|
-
idArray.push(id);
|
|
479
|
-
} else {
|
|
480
|
-
idArrayMap.set(currentElement, [id]);
|
|
481
|
-
}
|
|
482
|
-
if (currentElement === node)
|
|
483
|
-
break;
|
|
484
|
-
currentElement = currentElement.parentElement;
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
#mapIdSets(node) {
|
|
489
|
-
const idSetMap = this.#idSetMap;
|
|
490
|
-
for (const element of node.querySelectorAll("[id]")) {
|
|
491
|
-
const id = element.id;
|
|
492
|
-
if (id === "")
|
|
493
|
-
continue;
|
|
494
|
-
let currentElement = element;
|
|
495
|
-
while (currentElement) {
|
|
496
|
-
const idSet = idSetMap.get(currentElement);
|
|
497
|
-
if (idSet) {
|
|
498
|
-
idSet.add(id);
|
|
499
|
-
} else {
|
|
500
|
-
idSetMap.set(currentElement, new Set([id]));
|
|
501
|
-
}
|
|
502
|
-
if (currentElement === node)
|
|
503
|
-
break;
|
|
504
|
-
currentElement = currentElement.parentElement;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
function isInputElement(element) {
|
|
510
|
-
return element.localName === "input";
|
|
511
|
-
}
|
|
512
|
-
function isOptionElement(element) {
|
|
513
|
-
return element.localName === "option";
|
|
514
|
-
}
|
|
515
|
-
function isParentNode(node) {
|
|
516
|
-
return !!IS_PARENT_NODE_TYPE[node.nodeType];
|
|
517
|
-
}
|
|
518
|
-
function longestIncreasingSubsequence(sequence) {
|
|
519
|
-
const n = sequence.length;
|
|
520
|
-
if (n === 0)
|
|
521
|
-
return [];
|
|
522
|
-
const smallestEnding = [];
|
|
523
|
-
const indices = [];
|
|
524
|
-
const prev = new Array(n);
|
|
525
|
-
for (let i = 0;i < n; i++) {
|
|
526
|
-
const val = sequence[i];
|
|
527
|
-
if (val === undefined)
|
|
528
|
-
continue;
|
|
529
|
-
let left = 0;
|
|
530
|
-
let right = smallestEnding.length;
|
|
531
|
-
while (left < right) {
|
|
532
|
-
const mid = Math.floor((left + right) / 2);
|
|
533
|
-
if (smallestEnding[mid] < val)
|
|
534
|
-
left = mid + 1;
|
|
535
|
-
else
|
|
536
|
-
right = mid;
|
|
537
|
-
}
|
|
538
|
-
prev[i] = left > 0 ? indices[left - 1] : -1;
|
|
539
|
-
if (left === smallestEnding.length) {
|
|
540
|
-
smallestEnding.push(val);
|
|
541
|
-
indices.push(i);
|
|
542
|
-
} else {
|
|
543
|
-
smallestEnding[left] = val;
|
|
544
|
-
indices[left] = i;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
const result = [];
|
|
548
|
-
if (indices.length === 0)
|
|
549
|
-
return result;
|
|
550
|
-
let curr = indices[indices.length - 1];
|
|
551
|
-
while (curr !== undefined && curr !== -1) {
|
|
552
|
-
result.unshift(curr);
|
|
553
|
-
curr = prev[curr];
|
|
554
|
-
}
|
|
555
|
-
return result;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
//# debugId=3F4BCB911DEC843864756E2164756E21
|
|
559
|
-
|
|
560
|
-
function toMorphlexOptions(options) {
|
|
561
|
-
return { preserveChanges: (options?.preserveChanges ?? true) };
|
|
562
|
-
}
|
|
563
|
-
const morphAdapter = {
|
|
564
|
-
morph(target, content, options) {
|
|
565
|
-
morph(target, content, toMorphlexOptions(options));
|
|
566
|
-
},
|
|
567
|
-
morphInner(target, content, options) {
|
|
568
|
-
let contentEl;
|
|
569
|
-
if (typeof content === 'string') {
|
|
570
|
-
const wrapper = document.createElement(target.tagName);
|
|
571
|
-
wrapper.innerHTML = content;
|
|
572
|
-
contentEl = wrapper;
|
|
573
|
-
}
|
|
574
|
-
else {
|
|
575
|
-
contentEl = content;
|
|
576
|
-
}
|
|
577
|
-
morphInner(target, contentEl, toMorphlexOptions(options));
|
|
578
|
-
},
|
|
579
|
-
};
|
|
580
|
-
|
|
581
|
-
function getStartViewTransition() {
|
|
582
|
-
if (typeof document === 'undefined')
|
|
583
|
-
return undefined;
|
|
584
|
-
const fn = document
|
|
585
|
-
.startViewTransition;
|
|
586
|
-
return typeof fn === 'function' ? fn.bind(document) : undefined;
|
|
587
|
-
}
|
|
588
|
-
function isViewTransitionsSupported() {
|
|
589
|
-
return typeof getStartViewTransition() === 'function';
|
|
590
|
-
}
|
|
591
|
-
const queue = [];
|
|
592
|
-
let processing = false;
|
|
593
|
-
async function runOne(callback, options) {
|
|
594
|
-
const start = getStartViewTransition();
|
|
595
|
-
if (!start) {
|
|
596
|
-
await callback();
|
|
597
|
-
return;
|
|
598
|
-
}
|
|
599
|
-
const update = async () => {
|
|
600
|
-
await callback();
|
|
601
|
-
};
|
|
602
|
-
let transition;
|
|
603
|
-
if (options?.transitionName) {
|
|
604
|
-
try {
|
|
605
|
-
transition = start({
|
|
606
|
-
update,
|
|
607
|
-
types: [options.transitionName],
|
|
608
|
-
});
|
|
609
|
-
}
|
|
610
|
-
catch {
|
|
611
|
-
transition = start(update);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
else {
|
|
615
|
-
transition = start(update);
|
|
616
|
-
}
|
|
617
|
-
await transition.finished;
|
|
618
|
-
}
|
|
619
|
-
async function drain() {
|
|
620
|
-
if (processing)
|
|
621
|
-
return;
|
|
622
|
-
processing = true;
|
|
623
|
-
try {
|
|
624
|
-
while (queue.length > 0) {
|
|
625
|
-
const item = queue.shift();
|
|
626
|
-
try {
|
|
627
|
-
await runOne(item.callback, item.options);
|
|
628
|
-
item.resolve();
|
|
629
|
-
}
|
|
630
|
-
catch (error) {
|
|
631
|
-
item.reject(error);
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
finally {
|
|
636
|
-
processing = false;
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
function withViewTransition(callback, options) {
|
|
640
|
-
return new Promise((resolve, reject) => {
|
|
641
|
-
queue.push({ callback, options, resolve, reject });
|
|
642
|
-
drain().catch(reject);
|
|
643
|
-
});
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
function isHTMLElement(value) {
|
|
647
|
-
return (value !== null &&
|
|
648
|
-
typeof value === 'object' &&
|
|
649
|
-
'nodeType' in value &&
|
|
650
|
-
value.nodeType === 1 &&
|
|
651
|
-
'tagName' in value &&
|
|
652
|
-
typeof value.tagName === 'string' &&
|
|
653
|
-
'classList' in value);
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
function loneRootWithTag(content, tagName) {
|
|
657
|
-
let root;
|
|
658
|
-
if (typeof content === 'string') {
|
|
659
|
-
const template = document.createElement('template');
|
|
660
|
-
template.innerHTML = content;
|
|
661
|
-
root = template.content.firstElementChild;
|
|
662
|
-
if (!root || root.nextElementSibling)
|
|
663
|
-
return null;
|
|
664
|
-
}
|
|
665
|
-
else {
|
|
666
|
-
root = content.cloneNode(true);
|
|
667
|
-
}
|
|
668
|
-
return root.tagName === tagName && isHTMLElement(root) ? root : null;
|
|
669
|
-
}
|
|
670
|
-
function executeSwap(target, content, strategy, morphOptions) {
|
|
671
|
-
const contentStr = content !== null && !isHTMLElement(content) ? content : '';
|
|
672
|
-
const contentEl = isHTMLElement(content) ? content : null;
|
|
673
|
-
switch (strategy) {
|
|
674
|
-
case 'morphMerge': {
|
|
675
|
-
const root = content !== null ? loneRootWithTag(content, target.tagName) : null;
|
|
676
|
-
executeSwap(target, root ?? content, root ? 'morphOuter' : 'morph', morphOptions);
|
|
677
|
-
break;
|
|
678
|
-
}
|
|
679
|
-
case 'morph':
|
|
680
|
-
if (content !== null) {
|
|
681
|
-
try {
|
|
682
|
-
morphAdapter.morphInner(target, contentEl || contentStr, morphOptions);
|
|
683
|
-
}
|
|
684
|
-
catch (error) {
|
|
685
|
-
console.warn('[HyperFixi] Morph failed, falling back to innerHTML:', error);
|
|
686
|
-
if (contentEl) {
|
|
687
|
-
target.innerHTML = '';
|
|
688
|
-
target.appendChild(contentEl);
|
|
689
|
-
}
|
|
690
|
-
else {
|
|
691
|
-
target.innerHTML = contentStr;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
break;
|
|
696
|
-
case 'morphOuter':
|
|
697
|
-
if (content !== null) {
|
|
698
|
-
try {
|
|
699
|
-
morphAdapter.morph(target, contentEl || contentStr, morphOptions);
|
|
700
|
-
}
|
|
701
|
-
catch (error) {
|
|
702
|
-
console.warn('[HyperFixi] Morph failed, falling back to outerHTML:', error);
|
|
703
|
-
if (contentEl) {
|
|
704
|
-
target.replaceWith(contentEl);
|
|
705
|
-
}
|
|
706
|
-
else {
|
|
707
|
-
target.outerHTML = contentStr;
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
break;
|
|
712
|
-
case 'innerHTML':
|
|
713
|
-
if (contentEl) {
|
|
714
|
-
target.innerHTML = '';
|
|
715
|
-
target.appendChild(contentEl);
|
|
716
|
-
}
|
|
717
|
-
else {
|
|
718
|
-
target.innerHTML = contentStr;
|
|
719
|
-
}
|
|
720
|
-
break;
|
|
721
|
-
case 'outerHTML':
|
|
722
|
-
if (contentEl) {
|
|
723
|
-
target.replaceWith(contentEl);
|
|
724
|
-
}
|
|
725
|
-
else {
|
|
726
|
-
target.outerHTML = contentStr;
|
|
727
|
-
}
|
|
728
|
-
break;
|
|
729
|
-
case 'beforeBegin':
|
|
730
|
-
if (contentEl) {
|
|
731
|
-
target.parentElement?.insertBefore(contentEl, target);
|
|
732
|
-
}
|
|
733
|
-
else {
|
|
734
|
-
target.insertAdjacentHTML('beforebegin', contentStr);
|
|
735
|
-
}
|
|
736
|
-
break;
|
|
737
|
-
case 'afterBegin':
|
|
738
|
-
if (contentEl) {
|
|
739
|
-
target.insertBefore(contentEl, target.firstChild);
|
|
740
|
-
}
|
|
741
|
-
else {
|
|
742
|
-
target.insertAdjacentHTML('afterbegin', contentStr);
|
|
743
|
-
}
|
|
744
|
-
break;
|
|
745
|
-
case 'beforeEnd':
|
|
746
|
-
if (contentEl) {
|
|
747
|
-
target.appendChild(contentEl);
|
|
748
|
-
}
|
|
749
|
-
else {
|
|
750
|
-
target.insertAdjacentHTML('beforeend', contentStr);
|
|
751
|
-
}
|
|
752
|
-
break;
|
|
753
|
-
case 'afterEnd':
|
|
754
|
-
if (contentEl) {
|
|
755
|
-
target.parentElement?.insertBefore(contentEl, target.nextSibling);
|
|
756
|
-
}
|
|
757
|
-
else {
|
|
758
|
-
target.insertAdjacentHTML('afterend', contentStr);
|
|
759
|
-
}
|
|
760
|
-
break;
|
|
761
|
-
case 'delete':
|
|
762
|
-
target.remove();
|
|
763
|
-
break;
|
|
764
|
-
case 'none':
|
|
765
|
-
break;
|
|
766
|
-
default:
|
|
767
|
-
throw new Error(`[HyperFixi] swap: unknown strategy "${strategy}"`);
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
async function executeSwapWithTransition(targets, content, strategy, options = {}) {
|
|
771
|
-
const { morphOptions, useViewTransition = false } = options;
|
|
772
|
-
const performSwap = () => {
|
|
773
|
-
for (const target of targets) {
|
|
774
|
-
executeSwap(target, content, strategy, morphOptions);
|
|
775
|
-
}
|
|
776
|
-
};
|
|
777
|
-
if (useViewTransition && isViewTransitionsSupported()) {
|
|
778
|
-
await withViewTransition(performSwap);
|
|
779
|
-
}
|
|
780
|
-
else {
|
|
781
|
-
performSwap();
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
function createCustomEvent(eventName, detail, options = {}) {
|
|
786
|
-
return new CustomEvent(eventName, {
|
|
787
|
-
detail: detail !== undefined ? detail : {},
|
|
788
|
-
bubbles: options.bubbles !== undefined ? options.bubbles : true,
|
|
789
|
-
cancelable: options.cancelable !== undefined ? options.cancelable : true,
|
|
790
|
-
composed: options.composed !== undefined ? options.composed : false,
|
|
791
|
-
});
|
|
792
|
-
}
|
|
793
|
-
function dispatchCustomEvent(target, eventName, detail = {}, options = {}) {
|
|
794
|
-
const event = createCustomEvent(eventName, detail, options);
|
|
795
|
-
target.dispatchEvent(event);
|
|
796
|
-
return event;
|
|
797
|
-
}
|
|
798
|
-
function dispatchLokaScriptEvent(target, eventName, detail = {}, options = {}) {
|
|
799
|
-
const lokascriptEvent = dispatchCustomEvent(target, `lokascript:${eventName}`, detail, options);
|
|
800
|
-
const hyperfixiEvent = dispatchCustomEvent(target, `hyperfixi:${eventName}`, detail, options);
|
|
801
|
-
return {
|
|
802
|
-
lokascript: lokascriptEvent,
|
|
803
|
-
hyperfixi: hyperfixiEvent,
|
|
804
|
-
};
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
function createHistorySwap(config) {
|
|
808
|
-
const { target, strategy = 'morph', useViewTransition = false, fetchOptions = {}, transformUrl, onBeforeFetch, onAfterSwap, onError, } = config;
|
|
809
|
-
const resolveTarget = () => {
|
|
810
|
-
if (typeof target === 'string') {
|
|
811
|
-
const element = document.querySelector(target);
|
|
812
|
-
return isHTMLElement(element) ? element : null;
|
|
813
|
-
}
|
|
814
|
-
return isHTMLElement(target) ? target : null;
|
|
815
|
-
};
|
|
816
|
-
const handlePopstate = async (_event) => {
|
|
817
|
-
const targetElement = resolveTarget();
|
|
818
|
-
if (!targetElement) {
|
|
819
|
-
console.warn(`HistorySwap: target "${target}" not found`);
|
|
820
|
-
return;
|
|
821
|
-
}
|
|
822
|
-
let url = window.location.href;
|
|
823
|
-
if (transformUrl) {
|
|
824
|
-
url = transformUrl(url);
|
|
825
|
-
}
|
|
826
|
-
try {
|
|
827
|
-
if (onBeforeFetch) {
|
|
828
|
-
await onBeforeFetch(url);
|
|
829
|
-
}
|
|
830
|
-
targetElement.classList.add('hx-swapping');
|
|
831
|
-
const response = await fetch(url, {
|
|
832
|
-
method: 'GET',
|
|
833
|
-
headers: {
|
|
834
|
-
Accept: 'text/html',
|
|
835
|
-
'HX-Request': 'true',
|
|
836
|
-
'HX-History-Restore-Request': 'true',
|
|
837
|
-
},
|
|
838
|
-
...fetchOptions,
|
|
839
|
-
});
|
|
840
|
-
if (!response.ok) {
|
|
841
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
842
|
-
}
|
|
843
|
-
const html = await response.text();
|
|
844
|
-
await executeSwapWithTransition([targetElement], html, strategy, { useViewTransition });
|
|
845
|
-
targetElement.classList.remove('hx-swapping');
|
|
846
|
-
if (onAfterSwap) {
|
|
847
|
-
await onAfterSwap(url, html);
|
|
848
|
-
}
|
|
849
|
-
dispatchLokaScriptEvent(window, 'historyswap', { url, strategy, target });
|
|
850
|
-
}
|
|
851
|
-
catch (error) {
|
|
852
|
-
targetElement.classList.remove('hx-swapping');
|
|
853
|
-
if (onError) {
|
|
854
|
-
onError(error, url);
|
|
855
|
-
}
|
|
856
|
-
else {
|
|
857
|
-
console.error('HistorySwap fetch failed:', error);
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
};
|
|
861
|
-
window.addEventListener('popstate', handlePopstate);
|
|
862
|
-
return {
|
|
863
|
-
destroy: () => {
|
|
864
|
-
window.removeEventListener('popstate', handlePopstate);
|
|
865
|
-
},
|
|
866
|
-
config,
|
|
867
|
-
};
|
|
868
|
-
}
|
|
869
|
-
const HistorySwapBehavior = {
|
|
870
|
-
name: 'HistorySwap',
|
|
871
|
-
init(element, params = {}) {
|
|
872
|
-
const config = {
|
|
873
|
-
target: params.target || element,
|
|
874
|
-
strategy: params.strategy || 'morph',
|
|
875
|
-
useViewTransition: Boolean(params.useViewTransition),
|
|
876
|
-
};
|
|
877
|
-
return createHistorySwap(config);
|
|
878
|
-
},
|
|
879
|
-
destroy(instance) {
|
|
880
|
-
instance.destroy();
|
|
881
|
-
},
|
|
882
|
-
};
|
|
883
|
-
function registerHistorySwap(registry) {
|
|
884
|
-
if (registry instanceof Map) {
|
|
885
|
-
registry.set('HistorySwap', HistorySwapBehavior);
|
|
886
|
-
}
|
|
887
|
-
else if (registry && typeof registry.set === 'function') {
|
|
888
|
-
registry.set('HistorySwap', HistorySwapBehavior);
|
|
889
|
-
}
|
|
890
|
-
else if (registry && typeof registry === 'object') {
|
|
891
|
-
registry['HistorySwap'] = HistorySwapBehavior;
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
const historySwapHyperscript = `
|
|
895
|
-
behavior HistorySwap(target, strategy)
|
|
896
|
-
init
|
|
897
|
-
if no target then set target to me end
|
|
898
|
-
if no strategy then set strategy to 'morph' end
|
|
899
|
-
end
|
|
900
|
-
|
|
901
|
-
on popstate from window
|
|
902
|
-
add .hx-swapping to target
|
|
903
|
-
fetch location.href as html
|
|
904
|
-
if strategy is 'morph' then
|
|
905
|
-
swap target with it
|
|
906
|
-
else if strategy is 'innerHTML' then
|
|
907
|
-
swap innerHTML of target with it
|
|
908
|
-
else
|
|
909
|
-
swap target with it
|
|
910
|
-
end
|
|
911
|
-
remove .hx-swapping from target
|
|
912
|
-
end
|
|
913
|
-
end
|
|
914
|
-
`;
|
|
915
|
-
|
|
916
|
-
function isExternalUrl(url) {
|
|
917
|
-
try {
|
|
918
|
-
const parsed = new URL(url, window.location.origin);
|
|
919
|
-
return parsed.origin !== window.location.origin;
|
|
920
|
-
}
|
|
921
|
-
catch {
|
|
922
|
-
return false;
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
function shouldBoostLink(link) {
|
|
927
|
-
if (isExternalUrl(link.href)) {
|
|
928
|
-
return false;
|
|
929
|
-
}
|
|
930
|
-
if (link.target && link.target !== '_self') {
|
|
931
|
-
return false;
|
|
932
|
-
}
|
|
933
|
-
if (link.hasAttribute('download')) {
|
|
934
|
-
return false;
|
|
935
|
-
}
|
|
936
|
-
if (link.hasAttribute('data-no-boost') || link.hasAttribute('hx-boost-off')) {
|
|
937
|
-
return false;
|
|
938
|
-
}
|
|
939
|
-
if (link.protocol === 'javascript:' || link.protocol === 'mailto:') {
|
|
940
|
-
return false;
|
|
941
|
-
}
|
|
942
|
-
return true;
|
|
943
|
-
}
|
|
944
|
-
function shouldHandleClick(event) {
|
|
945
|
-
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
946
|
-
return false;
|
|
947
|
-
}
|
|
948
|
-
if (event.button !== 0) {
|
|
949
|
-
return false;
|
|
950
|
-
}
|
|
951
|
-
return true;
|
|
952
|
-
}
|
|
953
|
-
function createBoosted(config) {
|
|
954
|
-
const { container, target, linkSelector = 'a[href]', formSelector = 'form', boostForms = false, strategy = 'morph', pushUrl = true, useViewTransition = false, fetchOptions = {}, onBeforeFetch, onAfterSwap, onError, } = config;
|
|
955
|
-
const resolveTarget = () => {
|
|
956
|
-
if (!target) {
|
|
957
|
-
return document.body;
|
|
958
|
-
}
|
|
959
|
-
if (typeof target === 'string') {
|
|
960
|
-
const element = document.querySelector(target);
|
|
961
|
-
return isHTMLElement(element) ? element : null;
|
|
962
|
-
}
|
|
963
|
-
return isHTMLElement(target) ? target : null;
|
|
964
|
-
};
|
|
965
|
-
const boost = async (url, method = 'GET', body = null) => {
|
|
966
|
-
const targetElement = resolveTarget();
|
|
967
|
-
if (!targetElement) {
|
|
968
|
-
console.warn(`Boosted: target "${target}" not found`);
|
|
969
|
-
return;
|
|
970
|
-
}
|
|
971
|
-
try {
|
|
972
|
-
if (onBeforeFetch) {
|
|
973
|
-
const result = await onBeforeFetch(url, method);
|
|
974
|
-
if (result === false) {
|
|
975
|
-
return;
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
targetElement.classList.add('hx-swapping');
|
|
979
|
-
container.classList.add('hx-boosting');
|
|
980
|
-
const requestInit = {
|
|
981
|
-
method,
|
|
982
|
-
headers: {
|
|
983
|
-
Accept: 'text/html',
|
|
984
|
-
'HX-Request': 'true',
|
|
985
|
-
'HX-Boosted': 'true',
|
|
986
|
-
},
|
|
987
|
-
...fetchOptions,
|
|
988
|
-
};
|
|
989
|
-
if (body && method !== 'GET') {
|
|
990
|
-
requestInit.body = body;
|
|
991
|
-
}
|
|
992
|
-
const response = await fetch(url, requestInit);
|
|
993
|
-
if (!response.ok) {
|
|
994
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
995
|
-
}
|
|
996
|
-
const html = await response.text();
|
|
997
|
-
await executeSwapWithTransition([targetElement], html, strategy, { useViewTransition });
|
|
998
|
-
targetElement.classList.remove('hx-swapping');
|
|
999
|
-
container.classList.remove('hx-boosting');
|
|
1000
|
-
if (pushUrl && method === 'GET') {
|
|
1001
|
-
window.history.pushState(null, '', url);
|
|
1002
|
-
}
|
|
1003
|
-
if (onAfterSwap) {
|
|
1004
|
-
await onAfterSwap(url, html);
|
|
1005
|
-
}
|
|
1006
|
-
dispatchLokaScriptEvent(window, 'boosted', { url, method, strategy, target });
|
|
1007
|
-
}
|
|
1008
|
-
catch (error) {
|
|
1009
|
-
targetElement.classList.remove('hx-swapping');
|
|
1010
|
-
container.classList.remove('hx-boosting');
|
|
1011
|
-
if (onError) {
|
|
1012
|
-
onError(error, url);
|
|
1013
|
-
}
|
|
1014
|
-
else {
|
|
1015
|
-
console.error('Boosted fetch failed:', error);
|
|
1016
|
-
window.location.href = url;
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
};
|
|
1020
|
-
const handleClick = async (event) => {
|
|
1021
|
-
const link = event.target.closest(linkSelector);
|
|
1022
|
-
if (!link) {
|
|
1023
|
-
return;
|
|
1024
|
-
}
|
|
1025
|
-
if (!shouldHandleClick(event)) {
|
|
1026
|
-
return;
|
|
1027
|
-
}
|
|
1028
|
-
if (!shouldBoostLink(link)) {
|
|
1029
|
-
return;
|
|
1030
|
-
}
|
|
1031
|
-
event.preventDefault();
|
|
1032
|
-
event.stopPropagation();
|
|
1033
|
-
await boost(link.href);
|
|
1034
|
-
};
|
|
1035
|
-
const handleSubmit = async (event) => {
|
|
1036
|
-
if (!boostForms) {
|
|
1037
|
-
return;
|
|
1038
|
-
}
|
|
1039
|
-
const form = event.target.closest(formSelector);
|
|
1040
|
-
if (!form) {
|
|
1041
|
-
return;
|
|
1042
|
-
}
|
|
1043
|
-
if (form.hasAttribute('data-no-boost') || form.hasAttribute('hx-boost-off')) {
|
|
1044
|
-
return;
|
|
1045
|
-
}
|
|
1046
|
-
if (form.target && form.target !== '_self') {
|
|
1047
|
-
return;
|
|
1048
|
-
}
|
|
1049
|
-
event.preventDefault();
|
|
1050
|
-
event.stopPropagation();
|
|
1051
|
-
const method = (form.method || 'GET').toUpperCase();
|
|
1052
|
-
const formData = new FormData(form);
|
|
1053
|
-
let url;
|
|
1054
|
-
let body = null;
|
|
1055
|
-
if (method === 'GET') {
|
|
1056
|
-
const params = new URLSearchParams();
|
|
1057
|
-
formData.forEach((value, key) => {
|
|
1058
|
-
params.append(key, String(value));
|
|
1059
|
-
});
|
|
1060
|
-
url = `${form.action || window.location.pathname}?${params.toString()}`;
|
|
1061
|
-
}
|
|
1062
|
-
else {
|
|
1063
|
-
url = form.action || window.location.pathname;
|
|
1064
|
-
body = formData;
|
|
1065
|
-
}
|
|
1066
|
-
await boost(url, method, body);
|
|
1067
|
-
};
|
|
1068
|
-
container.addEventListener('click', handleClick);
|
|
1069
|
-
if (boostForms) {
|
|
1070
|
-
container.addEventListener('submit', handleSubmit);
|
|
1071
|
-
}
|
|
1072
|
-
return {
|
|
1073
|
-
destroy: () => {
|
|
1074
|
-
container.removeEventListener('click', handleClick);
|
|
1075
|
-
container.removeEventListener('submit', handleSubmit);
|
|
1076
|
-
},
|
|
1077
|
-
config,
|
|
1078
|
-
boost,
|
|
1079
|
-
};
|
|
1080
|
-
}
|
|
1081
|
-
const BoostedBehavior = {
|
|
1082
|
-
name: 'Boosted',
|
|
1083
|
-
init(element, params = {}) {
|
|
1084
|
-
const config = {
|
|
1085
|
-
container: element,
|
|
1086
|
-
target: params.target,
|
|
1087
|
-
linkSelector: params.linkSelector || 'a[href]',
|
|
1088
|
-
formSelector: params.formSelector || 'form',
|
|
1089
|
-
boostForms: Boolean(params.boostForms),
|
|
1090
|
-
strategy: params.strategy || 'morph',
|
|
1091
|
-
pushUrl: params.pushUrl !== false,
|
|
1092
|
-
useViewTransition: Boolean(params.useViewTransition),
|
|
1093
|
-
};
|
|
1094
|
-
return createBoosted(config);
|
|
1095
|
-
},
|
|
1096
|
-
destroy(instance) {
|
|
1097
|
-
instance.destroy();
|
|
1098
|
-
},
|
|
1099
|
-
};
|
|
1100
|
-
function registerBoosted(registry) {
|
|
1101
|
-
if (registry instanceof Map) {
|
|
1102
|
-
registry.set('Boosted', BoostedBehavior);
|
|
1103
|
-
}
|
|
1104
|
-
else if (registry && typeof registry.set === 'function') {
|
|
1105
|
-
registry.set('Boosted', BoostedBehavior);
|
|
1106
|
-
}
|
|
1107
|
-
else if (registry && typeof registry === 'object') {
|
|
1108
|
-
registry['Boosted'] = BoostedBehavior;
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
const boostedHyperscript = `
|
|
1112
|
-
behavior Boosted(target, pushHistory)
|
|
1113
|
-
init
|
|
1114
|
-
if no target then set target to document.body end
|
|
1115
|
-
if no pushHistory then set pushHistory to true end
|
|
1116
|
-
end
|
|
1117
|
-
|
|
1118
|
-
on click from <a[href]/> in me
|
|
1119
|
-
-- Skip if modifier keys pressed
|
|
1120
|
-
if event.metaKey or event.ctrlKey or event.shiftKey or event.altKey then exit end
|
|
1121
|
-
|
|
1122
|
-
-- Skip external links
|
|
1123
|
-
set href to the @href of the target
|
|
1124
|
-
if href starts with 'http' and not (href starts with location.origin) then exit end
|
|
1125
|
-
|
|
1126
|
-
-- Skip links with target attribute
|
|
1127
|
-
if the target has @target then exit end
|
|
1128
|
-
|
|
1129
|
-
halt the event
|
|
1130
|
-
add .hx-swapping to target
|
|
1131
|
-
fetch href as html
|
|
1132
|
-
swap target with it
|
|
1133
|
-
remove .hx-swapping from target
|
|
1134
|
-
if pushHistory then push url href end
|
|
1135
|
-
end
|
|
1136
|
-
end
|
|
1137
|
-
`;
|
|
1138
|
-
|
|
1139
|
-
function registerAllBehaviors(registry) {
|
|
1140
|
-
registerHistorySwap(registry);
|
|
1141
|
-
registerBoosted(registry);
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
export { BoostedBehavior, HistorySwapBehavior, boostedHyperscript, createBoosted, createHistorySwap, historySwapHyperscript, registerAllBehaviors, registerBoosted, registerHistorySwap };
|
|
1145
|
-
//# sourceMappingURL=index.mjs.map
|