From db1cbad9231b6353217995535942b6156395d540 Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Thu, 10 Nov 2022 16:48:25 +0100 Subject: [PATCH 1/7] Update README and dependencies --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- package.json | 8 +++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ae2a5d1..e2b5e5b 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,20 @@ ## Getting Started -`turbo-morph` is a [morphdom](https://github.com/patrick-steele-idem/morphdom) integration for [Turbo Streams](https://turbo.hotwired.dev/reference/streams). It provides a new Turbo Stream `morph` action. +`turbo-morph` is a Morph integration for [Turbo Streams](https://turbo.hotwired.dev/reference/streams). It provides a new Turbo Stream `morph` action and a few others action. + + +Supported morph plugins: +* [`morphdom`(default)](https://github.com/patrick-steele-idem/morphdom) +* [`@alpinejs/morph`](http://alpinejs.dev/plugins/morph) +* [`nanomorph`](https://github.com/choojs/nanomorph) +* [`micromorph`](https://github.com/natemoo-re/micromorph) +* [`idiomorph`](https://github.com/bigskysoftware/idiomorph) +* [`diffhtml`](https://github.com/tbranyen/diffhtml) +* [`diff-dom`](https://github.com/fiduswriter/diffDOM) + + +## Installation **Note:** Requires Turbo **7.2+** @@ -35,11 +48,43 @@ yarn add turbo-morph // application.js import * as Turbo from '@hotwired/turbo' +// using morphdom as default +import TurboMorph from 'turbo-morph' +TurboMorph.initialize(Turbo.StreamActions) ``` -## Example +Using a non-default morph plugin: + +```diff +// application.js +import * as Turbo from '@hotwired/turbo' + ++import TurboMorph from 'turbo-morph/nanomorph' ++TurboMorph.initialize(Turbo.StreamActions) +``` + +Using multiple morph plugins: + +```diff +// application.js +import * as Turbo from '@hotwired/turbo' + +// using nanomorph as default ++import { morph as morphdom } from 'turbo-morph' ++import { morph as nanomorph } from 'turbo-morph/nanomorph' ++import { morph as micromorph } from 'turbo-morph/micromorph' + + // Set the one you want as default ++Turbo.StreamActions.morph = morphdom + +// And register the other ones as their own action ++Turbo.StreamActions.morphdom = morphdom ++Turbo.StreamActions.nanomorph = nanomorph ++Turbo.StreamActions.micromorph = micromorph +``` + + +## Example using the default ```html diff --git a/package.json b/package.json index d61750e..5dbf8f9 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,13 @@ "vitest": "^0.18.1" }, "peerDependencies": { + "@alpinejs/morph": "^3.10.5", "@hotwired/turbo": ">= 7.2", - "morphdom": ">= 2.6" + "diff-dom": "^4.2.8", + "diffhtml": "^1.0.0-beta.29", + "idiomorph": "^0.0.7", + "micromorph": "^0.3.1", + "morphdom": ">= 2.6", + "nanomorph": "^5.4.3" } } From 0f86fc2387ef8105a15c9d83e1dda442b1b3e223 Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Thu, 10 Nov 2022 16:49:31 +0100 Subject: [PATCH 2/7] update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2b5e5b..2e310e8 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ ## Getting Started -`turbo-morph` is a Morph integration for [Turbo Streams](https://turbo.hotwired.dev/reference/streams). It provides a new Turbo Stream `morph` action and a few others action. +`turbo-morph` is a Morph integration for [Turbo Streams](https://turbo.hotwired.dev/reference/streams). It provides a new Turbo Stream `morph` action which uses `morphdom` under the hood by default. Supported morph plugins: From 78c2a1a486665be73eb5835188a15ead1517455a Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Thu, 10 Nov 2022 16:50:13 +0100 Subject: [PATCH 3/7] move comment --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e310e8..b8ba106 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Using a non-default morph plugin: // application.js import * as Turbo from '@hotwired/turbo' +// using nanomorph as default +import TurboMorph from 'turbo-morph/nanomorph' +TurboMorph.initialize(Turbo.StreamActions) ``` @@ -69,7 +70,6 @@ Using multiple morph plugins: // application.js import * as Turbo from '@hotwired/turbo' -// using nanomorph as default +import { morph as morphdom } from 'turbo-morph' +import { morph as nanomorph } from 'turbo-morph/nanomorph' +import { morph as micromorph } from 'turbo-morph/micromorph' From 6dd1e2da30fc64a62e88a7ad239c11b291d81583 Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Thu, 10 Nov 2022 17:25:07 +0100 Subject: [PATCH 4/7] Add Alpine plugin --- package.json | 12 ++++++++ rollup.config.js | 66 ++++++++++++++++++++++++++++--------------- src/index.ts | 23 ++++----------- src/plugins/alpine.ts | 54 +++++++++++++++++++++++++++++++++++ yarn.lock | 19 +++++++++++++ 5 files changed, 134 insertions(+), 40 deletions(-) create mode 100644 src/plugins/alpine.ts diff --git a/package.json b/package.json index 5dbf8f9..9a78a47 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,16 @@ "license": "MIT", "repository": "https://github.com/marcoroth/turbo-morph", "sideEffects": false, + "exports": { + ".": "./dist/index.js", + "./morphdom": "./dist/index.js", + "./alpine": "./dist/alpine.js", + "./diff-dom": "./dist/diff-dom.js", + "./diffhtml": "./dist/diffhtml.js", + "./idiomorph": "./dist/idiomorph.js", + "./micromorph": "./dist/micromorph.js", + "./nanomorph": "./dist/nanomorph.js" + }, "scripts": { "start": "cd playground && yarn start", "prebuild": "yarn clean", @@ -23,6 +33,7 @@ "@hotwired/turbo": "^7.2.0", "@rollup/plugin-node-resolve": "^13.0.5", "@rollup/plugin-typescript": "^8.2.5", + "@types/alpinejs": "^3.7.1", "concurrently": "^7.3.0", "morphdom": "^2.6.1", "rimraf": "^3.0.2", @@ -37,6 +48,7 @@ "peerDependencies": { "@alpinejs/morph": "^3.10.5", "@hotwired/turbo": ">= 7.2", + "alpinejs": "^3.10.5", "diff-dom": "^4.2.8", "diffhtml": "^1.0.0-beta.29", "idiomorph": "^0.0.7", diff --git a/rollup.config.js b/rollup.config.js index 57c9493..ae811e9 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -14,36 +14,58 @@ const minify = () => { }) } +const plugins = [ + resolve(), + typescript(), + filesize(), + // minify() +] + +const esConfig = { + format: 'es' +} + +const umdConfig = { + name: 'TurboMorph', + format: 'umd', + banner, + globals: { + '@hotwired/turbo': 'Turbo', + 'morphdom': 'morphdom' + } +} + + export default [ { input: 'src/index.ts', external: [ - '@hotwired/turbo' + '@hotwired/turbo', + 'morphdom' ], output: [ - { - name: 'TurboMorph', - file: 'dist/index.umd.js', - format: 'umd', - banner, - globals: { - '@hotwired/turbo': 'Turbo' - } - }, - { - file: 'dist/index.js', - format: 'es', - banner - } + { ...umdConfig, file: 'dist/index.umd.js' }, + { ...esConfig, file: 'dist/index.js' } ], - plugins: [ - resolve(), - typescript(), - filesize(), - minify() + plugins, + watch: { + include: 'src/index.ts' + } + }, + { + input: 'src/plugins/alpine.ts', + external: [ + '@hotwired/turbo', + 'alpinejs', + '@alpinejs/morph', ], + output: [ + { ...umdConfig, file: 'dist/alpine.umd.js', globals: { ...umdConfig.globals, 'alpinejs': 'Alpine' } }, + { ...esConfig, file: 'dist/alpine.js' } + ], + plugins, watch: { - include: 'src/**' + include: 'src/plugins/alpine.ts' } - } + }, ] diff --git a/src/index.ts b/src/index.ts index c11e6e3..dc7a300 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,26 +1,13 @@ -import morphdom from "morphdom" -import { TurboStreamActions, StreamElement } from "@hotwired/turbo" - -function morph(this: StreamElement) { - const options = { - childrenOnly: this.hasAttribute("children-only") - } - - this.targetElements.forEach(element => { - morphdom(element, options.childrenOnly ? this.templateContent : this.templateElement.innerHTML, options) - }) -} - -const initialize = (streamActions: TurboStreamActions) => { - streamActions.morph = morph -} +import { morph as morphdom, initialize } from "./plugins/morphdom" export default { initialize, - morph + morph: morphdom, + morphdom } export { initialize, - morph + morphdom as morph, + morphdom } diff --git a/src/plugins/alpine.ts b/src/plugins/alpine.ts new file mode 100644 index 0000000..53d79b6 --- /dev/null +++ b/src/plugins/alpine.ts @@ -0,0 +1,54 @@ +import Alpine from "alpinejs" +// @ts-ignore +import alpinemorph from "@alpinejs/morph" +import { StreamElement, TurboStreamActions } from "@hotwired/turbo" + +declare global { + interface Window { + Alpine: typeof Alpine + } +} + +if (!window.Alpine) { + window.Alpine = Alpine +} + +// @ts-ignore +if (!window.Alpine.morph) { + window.Alpine.plugin(alpinemorph) +} + +export function morph(this: StreamElement) { + const childrenOnly = this.hasAttribute("children-only") + + this.targetElements.forEach(element => { + const options = { + updating (_element: Element, _toElement: Element, childrenOnlyFn: Function, _skip: Boolean) { + if (childrenOnly) { + childrenOnlyFn() + } + + // shouldMorph(operation) + }, + + updated (_element: Element, _toElement: Element) { + // didMorph(operation) + }, + + removing (_element: Element, _skip: Boolean) {}, + removed (_element: Element) {}, + + adding (_element: Element, _skip: Boolean) {}, + added (_element: Element) {} + } + + const newHtml = childrenOnly ? this.templateContent : this.templateElement.innerHTML + + // @ts-ignore + window.Alpine.morph(element, newHtml, options) + }) +} + +export function initialize(streamActions: TurboStreamActions) { + streamActions.morph = morph +} diff --git a/yarn.lock b/yarn.lock index 98d6d80..fb9a690 100644 --- a/yarn.lock +++ b/yarn.lock @@ -139,6 +139,13 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== +"@types/alpinejs@^3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@types/alpinejs/-/alpinejs-3.7.1.tgz#4726758a0579ef0afd3a9e80ff64840d5943a08b" + integrity sha512-gzwyuHXH/meGQQhurMGWlZgMQxe18lMOoSPd7X6CvGoDelHte9EsU7SpTIoRu8yYir0tbHDeaSMdX9LeQz/QtA== + dependencies: + "@vue/reactivity" "^3.2.26" + "@types/chai-subset@^1.3.3": version "1.3.3" resolved "https://registry.yarnpkg.com/@types/chai-subset/-/chai-subset-1.3.3.tgz#97893814e92abd2c534de422cb377e0e0bdaac94" @@ -168,6 +175,18 @@ dependencies: "@types/node" "*" +"@vue/reactivity@^3.2.26": + version "3.2.44" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.44.tgz#f017f9d1557c5fac18feaa3207f247c8a763cf18" + integrity sha512-Fe0s52fTsPl+RSdvoqUZ3HRKlaVsKhIh1mea5EWOedFvZCjnymzlj3YC1wZMxi89qXRFSdEASVA/BWUGypk0Ig== + dependencies: + "@vue/shared" "3.2.44" + +"@vue/shared@3.2.44": + version "3.2.44" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.44.tgz#d180eae83de86a48a3a0b6aaded546683443ca57" + integrity sha512-mGZ44bnn0zpZ36nXtxbrBPno43yr96wjQE1dBEKS1Sieugt27HS4OGZVBRIgsdGzosB7vqZAvu0ttu1FDVdolA== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" From 811c644ac42a1667ca59761f08e9ecca7ce07af3 Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Thu, 10 Nov 2022 17:25:21 +0100 Subject: [PATCH 5/7] Add files for remaining plugins --- src/plugins/diff-dom.ts | 14 ++++++++++++++ src/plugins/diffhtml.ts | 14 ++++++++++++++ src/plugins/idiomorph.ts | 14 ++++++++++++++ src/plugins/micromorph.ts | 14 ++++++++++++++ src/plugins/morphdom.ts | 16 ++++++++++++++++ src/plugins/nanomorph.ts | 14 ++++++++++++++ 6 files changed, 86 insertions(+) create mode 100644 src/plugins/diff-dom.ts create mode 100644 src/plugins/diffhtml.ts create mode 100644 src/plugins/idiomorph.ts create mode 100644 src/plugins/micromorph.ts create mode 100644 src/plugins/morphdom.ts create mode 100644 src/plugins/nanomorph.ts diff --git a/src/plugins/diff-dom.ts b/src/plugins/diff-dom.ts new file mode 100644 index 0000000..7f712a8 --- /dev/null +++ b/src/plugins/diff-dom.ts @@ -0,0 +1,14 @@ +import { DiffDOM } from "diff-dom" +import { StreamElement, TurboStreamActions } from "@hotwired/turbo" + +export function morph(this: StreamElement) { + const _childrenOnly = this.hasAttribute("children-only") + + this.targetElements.forEach((_element: Element) => { + // TODO + }) +} + +export function initialize(streamActions: TurboStreamActions) { + streamActions.morph = morph +} diff --git a/src/plugins/diffhtml.ts b/src/plugins/diffhtml.ts new file mode 100644 index 0000000..3aa589d --- /dev/null +++ b/src/plugins/diffhtml.ts @@ -0,0 +1,14 @@ +import diffhtml from "diffhtml" +import { StreamElement, TurboStreamActions } from "@hotwired/turbo" + +export function morph(this: StreamElement) { + const _childrenOnly = this.hasAttribute("children-only") + + this.targetElements.forEach((_element: Element) => { + // TODO + }) +} + +export function initialize(streamActions: TurboStreamActions) { + streamActions.morph = morph +} diff --git a/src/plugins/idiomorph.ts b/src/plugins/idiomorph.ts new file mode 100644 index 0000000..71c4cd4 --- /dev/null +++ b/src/plugins/idiomorph.ts @@ -0,0 +1,14 @@ +import TODO from "idiomorph" +import { StreamElement, TurboStreamActions } from "@hotwired/turbo" + +export function morph(this: StreamElement) { + const _childrenOnly = this.hasAttribute("children-only") + + this.targetElements.forEach((_element: Element) => { + // TODO + }) +} + +export function initialize(streamActions: TurboStreamActions) { + streamActions.morph = morph +} diff --git a/src/plugins/micromorph.ts b/src/plugins/micromorph.ts new file mode 100644 index 0000000..73569d2 --- /dev/null +++ b/src/plugins/micromorph.ts @@ -0,0 +1,14 @@ +import TODO from "micromorph" +import { StreamElement, TurboStreamActions } from "@hotwired/turbo" + +export function morph(this: StreamElement) { + const _childrenOnly = this.hasAttribute("children-only") + + this.targetElements.forEach((_element: Element) => { + // TODO + }) +} + +export function initialize(streamActions: TurboStreamActions) { + streamActions.morph = morph +} diff --git a/src/plugins/morphdom.ts b/src/plugins/morphdom.ts new file mode 100644 index 0000000..5dcc987 --- /dev/null +++ b/src/plugins/morphdom.ts @@ -0,0 +1,16 @@ +import morphdom from "morphdom" +import { StreamElement, TurboStreamActions } from "@hotwired/turbo" + +export function morph(this: StreamElement) { + const options = { + childrenOnly: this.hasAttribute("children-only") + } + + this.targetElements.forEach(element => { + morphdom(element, options.childrenOnly ? this.templateContent : this.templateElement.innerHTML, options) + }) +} + +export function initialize(streamActions: TurboStreamActions) { + streamActions.morph = morph +} diff --git a/src/plugins/nanomorph.ts b/src/plugins/nanomorph.ts new file mode 100644 index 0000000..fa7d8b0 --- /dev/null +++ b/src/plugins/nanomorph.ts @@ -0,0 +1,14 @@ +import TODO from "nanomorph" +import { StreamElement, TurboStreamActions } from "@hotwired/turbo" + +export function morph(this: StreamElement) { + const _childrenOnly = this.hasAttribute("children-only") + + this.targetElements.forEach((_element: Element) => { + // TODO + }) +} + +export function initialize(streamActions: TurboStreamActions) { + streamActions.morph = morph +} From f1a73514c0d2c926c4e9250887e73f3ca531d08a Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Thu, 10 Nov 2022 17:31:00 +0100 Subject: [PATCH 6/7] update imports for remaining plugins --- package.json | 1 + src/plugins/diff-dom.ts | 5 +++-- src/plugins/diffhtml.ts | 7 ++++--- src/plugins/idiomorph.ts | 7 ++++--- src/plugins/micromorph.ts | 5 +++-- src/plugins/nanomorph.ts | 9 ++++++--- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 9a78a47..35c5439 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "idiomorph": "^0.0.7", "micromorph": "^0.3.1", "morphdom": ">= 2.6", + "nanohtml": "^1.10.0", "nanomorph": "^5.4.3" } } diff --git a/src/plugins/diff-dom.ts b/src/plugins/diff-dom.ts index 7f712a8..332500b 100644 --- a/src/plugins/diff-dom.ts +++ b/src/plugins/diff-dom.ts @@ -1,11 +1,12 @@ +// @ts-ignore import { DiffDOM } from "diff-dom" import { StreamElement, TurboStreamActions } from "@hotwired/turbo" export function morph(this: StreamElement) { - const _childrenOnly = this.hasAttribute("children-only") + // const _childrenOnly = this.hasAttribute("children-only") this.targetElements.forEach((_element: Element) => { - // TODO + DiffDOM() }) } diff --git a/src/plugins/diffhtml.ts b/src/plugins/diffhtml.ts index 3aa589d..a00f8f7 100644 --- a/src/plugins/diffhtml.ts +++ b/src/plugins/diffhtml.ts @@ -1,11 +1,12 @@ -import diffhtml from "diffhtml" +// @ts-ignore +import { innerHTML } from 'diffhtml' import { StreamElement, TurboStreamActions } from "@hotwired/turbo" export function morph(this: StreamElement) { - const _childrenOnly = this.hasAttribute("children-only") + // const _childrenOnly = this.hasAttribute("children-only") this.targetElements.forEach((_element: Element) => { - // TODO + innerHTML() }) } diff --git a/src/plugins/idiomorph.ts b/src/plugins/idiomorph.ts index 71c4cd4..098c8a6 100644 --- a/src/plugins/idiomorph.ts +++ b/src/plugins/idiomorph.ts @@ -1,11 +1,12 @@ -import TODO from "idiomorph" +// @ts-ignore +import Idiomorph from "idiomorph" import { StreamElement, TurboStreamActions } from "@hotwired/turbo" export function morph(this: StreamElement) { - const _childrenOnly = this.hasAttribute("children-only") + // const _childrenOnly = this.hasAttribute("children-only") this.targetElements.forEach((_element: Element) => { - // TODO + Idiomorph.morph() }) } diff --git a/src/plugins/micromorph.ts b/src/plugins/micromorph.ts index 73569d2..12eda39 100644 --- a/src/plugins/micromorph.ts +++ b/src/plugins/micromorph.ts @@ -1,8 +1,9 @@ -import TODO from "micromorph" +// @ts-ignore +import micromorph from "micromorph" import { StreamElement, TurboStreamActions } from "@hotwired/turbo" export function morph(this: StreamElement) { - const _childrenOnly = this.hasAttribute("children-only") + // const _childrenOnly = this.hasAttribute("children-only") this.targetElements.forEach((_element: Element) => { // TODO diff --git a/src/plugins/nanomorph.ts b/src/plugins/nanomorph.ts index fa7d8b0..7d10aba 100644 --- a/src/plugins/nanomorph.ts +++ b/src/plugins/nanomorph.ts @@ -1,11 +1,14 @@ -import TODO from "nanomorph" +// @ts-ignore +import nanomorph from "nanomorph" +// import nanohtml from "nanohtml" + import { StreamElement, TurboStreamActions } from "@hotwired/turbo" export function morph(this: StreamElement) { - const _childrenOnly = this.hasAttribute("children-only") + // const _childrenOnly = this.hasAttribute("children-only") this.targetElements.forEach((_element: Element) => { - // TODO + nanomorph() }) } From fcdb6e0c4224c00dc9539c469d6e86bd10b34715 Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Fri, 11 Nov 2022 03:14:18 +0100 Subject: [PATCH 7/7] Implement MVP for all plugins, not all cases work as expected yet though --- package.json | 20 +-- playground/index.js | 8 +- playground/package.json | 8 + playground/yarn.lock | 336 ++++++++++++++++++++++++++++++++++++++ rollup.config.js | 76 +++++---- src/index.ts | 10 +- src/plugins/alpine.ts | 1 + src/plugins/diff-dom.ts | 17 +- src/plugins/diffhtml.ts | 10 +- src/plugins/idiomorph.ts | 15 +- src/plugins/micromorph.ts | 14 +- src/plugins/morphdom.ts | 9 +- src/plugins/nanomorph.ts | 19 ++- 13 files changed, 476 insertions(+), 67 deletions(-) diff --git a/package.json b/package.json index 35c5439..6cd7302 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,8 @@ "name": "turbo-morph", "version": "0.1.0", "description": "Morphdom integration for Turbo Streams", - "main": "dist/index.js", - "module": "dist/index.js", + "main": "dist/index.mjs", + "module": "dist/index.mjs", "unpkg": "dist/index.umd.js", "types": "dist/types/index.d.ts", "author": "Marco Roth", @@ -11,14 +11,14 @@ "repository": "https://github.com/marcoroth/turbo-morph", "sideEffects": false, "exports": { - ".": "./dist/index.js", - "./morphdom": "./dist/index.js", - "./alpine": "./dist/alpine.js", - "./diff-dom": "./dist/diff-dom.js", - "./diffhtml": "./dist/diffhtml.js", - "./idiomorph": "./dist/idiomorph.js", - "./micromorph": "./dist/micromorph.js", - "./nanomorph": "./dist/nanomorph.js" + ".": "./dist/index.mjs", + "./morphdom": "./dist/plugins/morphdom.mjs", + "./alpine": "./dist/plugins/alpine.mjs", + "./diff-dom": "./dist/plugins/diff-dom.mjs", + "./diffhtml": "./dist/plugins/diffhtml.mjs", + "./idiomorph": "./dist/plugins/idiomorph.mjs", + "./micromorph": "./dist/plugins/micromorph.mjs", + "./nanomorph": "./dist/plugins/nanomorph.mjs" }, "scripts": { "start": "cd playground && yarn start", diff --git a/playground/index.js b/playground/index.js index 146bbf4..c8f6176 100644 --- a/playground/index.js +++ b/playground/index.js @@ -1,4 +1,8 @@ import * as Turbo from "@hotwired/turbo" +// import * as TurboMorph from 'turbo-morph/morphdom' +// TurboMorph.initialize(Turbo.StreamActions) -import { registerMorph } from "turbo-morph" -registerMorph() +import "diffhtml" + +import * as TurboMorph from 'turbo-morph/diffhtml' +TurboMorph.initialize(Turbo.StreamActions) diff --git a/playground/package.json b/playground/package.json index 5c6d6c9..b05de15 100644 --- a/playground/package.json +++ b/playground/package.json @@ -6,7 +6,15 @@ "license": "MIT", "repository": "https://github.com/marcoroth/turbo-morph", "dependencies": { + "@alpinejs/morph": "^3.10.5", "@hotwired/turbo": "^7.2.0", + "alpinejs": "^3.10.5", + "diff-dom": "^4.2.8", + "diffhtml": "^1.0.0-beta.29", + "idiomorph": "^0.0.7", + "micromorph": "^0.3.1", + "nanohtml": "^1.10.0", + "nanomorph": "^5.4.3", "turbo-morph": "link:../" }, "scripts": { diff --git a/playground/yarn.lock b/playground/yarn.lock index 7fdc161..b7402b7 100644 --- a/playground/yarn.lock +++ b/playground/yarn.lock @@ -2,11 +2,113 @@ # yarn lockfile v1 +"@alpinejs/morph@^3.10.5": + version "3.10.5" + resolved "https://registry.yarnpkg.com/@alpinejs/morph/-/morph-3.10.5.tgz#855bf3352250148f73158780a8f27bbd5ee95d05" + integrity sha512-NQmC1vFwvNbVke1Io6rp6A0Hxgy3iz1xsyqjBZmMJVM5eYaYUwJJXR9N0hFzUTAt4KfzPZpeabwaiduKaEuxBQ== + "@hotwired/turbo@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-7.2.0.tgz#4ff90d80fda17e69b04a12bbf0a42f09953504f6" integrity sha512-CYr6N9NfqsjhmZx1xVQ8zYcDo4hTm7sTUpJydbNgMRyG+YfF/9ADIQQ2TtcBdkl2zi/12a3OTWX0UMzNZnAK9w== +"@vue/reactivity@~3.1.1": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.1.5.tgz#dbec4d9557f7c8f25c2635db1e23a78a729eb991" + integrity sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg== + dependencies: + "@vue/shared" "3.1.5" + +"@vue/shared@3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.1.5.tgz#74ee3aad995d0a3996a6bb9533d4d280514ede03" + integrity sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA== + +acorn-node@^1.3.0, acorn-node@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" + integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== + dependencies: + acorn "^7.0.0" + acorn-walk "^7.0.0" + xtend "^4.0.2" + +acorn-walk@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^7.0.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +alpinejs@^3.10.5: + version "3.10.5" + resolved "https://registry.yarnpkg.com/alpinejs/-/alpinejs-3.10.5.tgz#59ca09ad42293cc8e0bbbdf4c7696fc22c6df700" + integrity sha512-qlvnal44Gof2XVfm/lef8fYpXKxR9fjdSki7aFB/9THyFvbsRKZ6lM5SjxXpIs7B0faJt7bgpK2K25gzrraXJw== + dependencies: + "@vue/reactivity" "~3.1.1" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + +browser-process-hrtime@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" + integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== + +camel-case@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" + integrity sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w== + dependencies: + no-case "^2.2.0" + upper-case "^1.1.1" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +convert-source-map@^1.5.1: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +dash-ast@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dash-ast/-/dash-ast-1.0.0.tgz#12029ba5fb2f8aa6f0a861795b23c1b4b6c27d37" + integrity sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA== + +diff-dom@^4.2.8: + version "4.2.8" + resolved "https://registry.yarnpkg.com/diff-dom/-/diff-dom-4.2.8.tgz#4280b28c4dc1da951c40ee6969d895f782b8edbc" + integrity sha512-OIL+sf1bFBQ/Z1gjo3xlHyDViVaRiDVMOM5jTM30aFATu3tLlNloeixKCg7p7nFyTjI1eQmdlVu1admV/BwVJw== + +diffhtml@^1.0.0-beta.29: + version "1.0.0-beta.29" + resolved "https://registry.yarnpkg.com/diffhtml/-/diffhtml-1.0.0-beta.29.tgz#ded1549d6cce161223ed333abef4b731bccf618d" + integrity sha512-X3ZBa5FOBIBBgMo/MHqQFZTQhOgbJmET6JS5CRrJBKVkmdWF7AemldX2lzF2+c6arFykQ6SOI1SDlY6r2+2z5g== + esbuild-android-64@0.14.49: version "0.14.49" resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.49.tgz#9e4682c36dcf6e7b71b73d2a3723a96e0fdc5054" @@ -133,6 +235,16 @@ esbuild@^0.14.47: esbuild-windows-64 "0.14.49" esbuild-windows-arm64 "0.14.49" +escape-string-regexp@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +estree-is-member-expression@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/estree-is-member-expression/-/estree-is-member-expression-1.0.0.tgz#e724721e0a14949d363915fd71448eaa6312f590" + integrity sha512-Ec+X44CapIGExvSZN+pGkmr5p7HwUVQoPQSd458Lqwvaf4/61k/invHSh4BYK8OXnCkfEhWuIoG5hayKLQStIg== + fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -143,6 +255,13 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" @@ -150,6 +269,38 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hyperscript-attribute-to-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/hyperscript-attribute-to-property/-/hyperscript-attribute-to-property-1.0.2.tgz#66ad4164f88beefacf46ec884bd3d1173c1c382a" + integrity sha512-oerMul16jZCmrbNsUw8QgrtDzF8lKgFri1bKQjReLw1IhiiNkI59CWuzZjJDGT79UQ1YiWqXhJMv/tRMVqgtkA== + +hyperx@^2.5.0: + version "2.5.4" + resolved "https://registry.yarnpkg.com/hyperx/-/hyperx-2.5.4.tgz#72b4c3ed4111f64838221a9d0409e6bfc3f78d9e" + integrity sha512-iOkSh7Yse7lsN/B9y7OsevLWjeXPqGuHQ5SbwaiJM5xAhWFqhoN6erpK1dQsS12OFU36lyai1pnx1mmzWLQqcA== + dependencies: + hyperscript-attribute-to-property "^1.0.0" + +idiomorph@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/idiomorph/-/idiomorph-0.0.7.tgz#8fb8d3886b094e360ca3c688529dde732912573e" + integrity sha512-CqxKuexWBj9UcnsLKABDYXQmlJCNjcBD5PbgmMW9PQPil98AfMxbalQAu4ywjTHlxEegszdhsmtYsCpQ4Pd4YQ== + +inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-boolean-attribute@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/is-boolean-attribute/-/is-boolean-attribute-0.0.1.tgz#24ab59b7dcb9da3612c773e60c656565e5a0980c" + integrity sha512-0kXT52Scokg2Miscvsn5UVqg6y1691vcLJcagie1YHJB4zOEuAhMERLX992jtvaStGy2xQTqOtJhvmG/MK1T5w== + +is-buffer@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + is-core-module@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" @@ -157,11 +308,98 @@ is-core-module@^2.9.0: dependencies: has "^1.0.3" +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +lower-case@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + integrity sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA== + +magic-string@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.23.2.tgz#204d7c3ea36c7d940209fcc54c39b9f243f13369" + integrity sha512-oIUZaAxbcxYIp4AyLafV6OVKoB3YouZs0UTCJ8mOKBHNyJgGDaMJ4TgA+VylJh6fx7EQCC52XkbURxxG9IoJXA== + dependencies: + sourcemap-codec "^1.4.1" + +merge-source-map@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" + integrity sha512-PGSmS0kfnTnMJCzJ16BLLCEe6oeYCamKFFdQKshi4BmM6FUwipjVOcBFGxqtQtirtAG4iZvHlqST9CpZKqlRjA== + dependencies: + source-map "^0.5.6" + +micromorph@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/micromorph/-/micromorph-0.3.1.tgz#8295ad9e6bdab008373daca26b1f19c32e7c846a" + integrity sha512-dbX4sz405e/QQtbHFMJj0SaVP+xuBBpSpR44AQYTjsrPek8oKyeRXkbtYN1XyFVdV7WjHp5DZMwxJOJiBfH1Jw== + +mutexify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/mutexify/-/mutexify-1.4.0.tgz#b7f4ac0273c81824b840887c6a6e0bfab14bbe94" + integrity sha512-pbYSsOrSB/AKN5h/WzzLRMFgZhClWccf2XIB4RSMC8JbquiB0e0/SH5AIfdQMdyHmYtv4seU7yV/TvAwPLJ1Yg== + dependencies: + queue-tick "^1.0.0" + +nanoassert@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/nanoassert/-/nanoassert-1.1.0.tgz#4f3152e09540fde28c76f44b19bbcd1d5a42478d" + integrity sha512-C40jQ3NzfkP53NsO8kEOFd79p4b9kDXQMwgiY1z8ZwrDZgUyom0AHwGegF4Dm99L+YoYhuaB0ceerUcXmqr1rQ== + +nanobench@^2.1.0, nanobench@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nanobench/-/nanobench-2.1.1.tgz#c2f23fcce116d50b4998b1954ba114674c137269" + integrity sha512-z+Vv7zElcjN+OpzAxAquUayFLGK3JI/ubCl0Oh64YQqsTGG09CGqieJVQw4ui8huDnnAgrvTv93qi5UaOoNj8A== + dependencies: + browser-process-hrtime "^0.1.2" + chalk "^1.1.3" + mutexify "^1.1.0" + pretty-hrtime "^1.0.2" + +nanohtml@^1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/nanohtml/-/nanohtml-1.10.0.tgz#3aa8dd06710c773327cdc22817bdb7b8c476e1bd" + integrity sha512-r/3AQl+jxAxUIJRiKExUjBtFcE1cm4yTOsTIdVqqlxPNtBxJh522ANrcQYzdNHhPzbPgb7j6qujq6eGehBX0kg== + dependencies: + acorn-node "^1.8.2" + camel-case "^3.0.0" + convert-source-map "^1.5.1" + estree-is-member-expression "^1.0.0" + hyperx "^2.5.0" + is-boolean-attribute "0.0.1" + nanoassert "^1.1.0" + nanobench "^2.1.0" + normalize-html-whitespace "^0.2.0" + through2 "^2.0.3" + transform-ast "^2.4.0" + nanoid@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +nanomorph@^5.4.3: + version "5.4.3" + resolved "https://registry.yarnpkg.com/nanomorph/-/nanomorph-5.4.3.tgz#ac518e9dc69a3dd69ceab4994388cc03bf867763" + integrity sha512-uPP5y0x21KISffZCKHh1A0QW0RHZFQS0BR7LetlHBlay6UWAbjwhjiJTxOO6JeMHko5Cigl617zFoGrYFJ8ZLg== + dependencies: + nanoassert "^1.1.0" + +no-case@^2.2.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== + dependencies: + lower-case "^1.1.1" + +normalize-html-whitespace@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/normalize-html-whitespace/-/normalize-html-whitespace-0.2.0.tgz#101722f6423551c75cdb8f9d104ff850daf1e10e" + integrity sha512-5CZAEQ4bQi8Msqw0GAT6rrkrjNN4ZKqAG3+jJMwms4O6XoMvh6ekwOueG4mRS1LbPUR1r9EdnhxxfpzMTOdzKw== + path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" @@ -181,6 +419,34 @@ postcss@^8.4.14: picocolors "^1.0.0" source-map-js "^1.0.2" +pretty-hrtime@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +queue-tick@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/queue-tick/-/queue-tick-1.0.1.tgz#f6f07ac82c1fd60f82e098b417a80e52f1f4c142" + integrity sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag== + +readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + resolve@^1.22.1: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" @@ -197,20 +463,85 @@ rollup@^2.75.6: optionalDependencies: fsevents "~2.3.2" +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +sourcemap-codec@^1.4.1: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +transform-ast@^2.4.0: + version "2.4.4" + resolved "https://registry.yarnpkg.com/transform-ast/-/transform-ast-2.4.4.tgz#bebf494e2e73f024746f76348bc86a5992851d00" + integrity sha512-AxjeZAcIOUO2lev2GDe3/xZ1Q0cVGjIMk5IsriTy8zbWlsEnjeB025AhkhBJHoy997mXpLd4R+kRbvnnQVuQHQ== + dependencies: + acorn-node "^1.3.0" + convert-source-map "^1.5.1" + dash-ast "^1.0.0" + is-buffer "^2.0.0" + magic-string "^0.23.2" + merge-source-map "1.0.4" + nanobench "^2.1.1" + "turbo-morph@link:..": version "0.0.0" uid "" +upper-case@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + integrity sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA== + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + vite@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/vite/-/vite-3.0.2.tgz#2a7b4642c53ae066cf724e7e581d6c1fd24e2c32" @@ -222,3 +553,8 @@ vite@^3.0.2: rollup "^2.75.6" optionalDependencies: fsevents "~2.3.2" + +xtend@^4.0.2, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== diff --git a/rollup.config.js b/rollup.config.js index ae811e9..e9d8f18 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -31,41 +31,57 @@ const umdConfig = { banner, globals: { '@hotwired/turbo': 'Turbo', - 'morphdom': 'morphdom' + 'morphdom': 'morphdom', + 'alpinejs': 'Alpine', + '@alpinejs/morph': 'Alpine.morph', + 'diff-dom': 'DiffDOM', + 'diffhtml': 'diffhtml', + 'idiomorph': 'Idiomorph', + 'nanomorph': 'nanomorph', + 'nanohtml': 'nanohtml', } } +const external = [ + '@hotwired/turbo', + 'alpinejs', + '@alpinejs/morph', + 'nanohtml' +] -export default [ - { - input: 'src/index.ts', - external: [ - '@hotwired/turbo', - 'morphdom' - ], - output: [ - { ...umdConfig, file: 'dist/index.umd.js' }, - { ...esConfig, file: 'dist/index.js' } - ], - plugins, - watch: { - include: 'src/index.ts' - } - }, - { - input: 'src/plugins/alpine.ts', - external: [ - '@hotwired/turbo', - 'alpinejs', - '@alpinejs/morph', - ], +const defaultPlugin = { + input: 'src/index.ts', + output: [ + { ...umdConfig, file: 'dist/index.umd.js' }, + { ...esConfig, file: 'dist/index.mjs' }, + ], + plugins, + external, + watch: { include: 'src/index.ts' } +} + +const exportConfigFor = (plugin) => { + external.push(plugin) + return { + input: `src/plugins/${plugin}.ts`, output: [ - { ...umdConfig, file: 'dist/alpine.umd.js', globals: { ...umdConfig.globals, 'alpinejs': 'Alpine' } }, - { ...esConfig, file: 'dist/alpine.js' } + { ...umdConfig, file: `dist/plugins/${plugin}.umd.js` }, + { ...esConfig, file: `dist/plugins/${plugin}.mjs` } ], + external, plugins, - watch: { - include: 'src/plugins/alpine.ts' - } - }, + watch: { include: `src/plugins/${plugin}.ts` } + } +} + + +export default [ + defaultPlugin, + exportConfigFor('morphdom'), + exportConfigFor('alpine'), + exportConfigFor('nanomorph'), + exportConfigFor('idiomorph'), + exportConfigFor('micromorph'), + exportConfigFor('diff-dom'), + exportConfigFor('diffhtml'), ] diff --git a/src/index.ts b/src/index.ts index dc7a300..1d53e24 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,13 +1,13 @@ -import { morph as morphdom, initialize } from "./plugins/morphdom" +import { morph, initialize } from "./plugins/morphdom" + +console.log("morphdom via default") export default { initialize, - morph: morphdom, - morphdom + morph } export { initialize, - morphdom as morph, - morphdom + morph, } diff --git a/src/plugins/alpine.ts b/src/plugins/alpine.ts index 53d79b6..b64577f 100644 --- a/src/plugins/alpine.ts +++ b/src/plugins/alpine.ts @@ -19,6 +19,7 @@ if (!window.Alpine.morph) { } export function morph(this: StreamElement) { + console.log("alpine") const childrenOnly = this.hasAttribute("children-only") this.targetElements.forEach(element => { diff --git a/src/plugins/diff-dom.ts b/src/plugins/diff-dom.ts index 332500b..1816094 100644 --- a/src/plugins/diff-dom.ts +++ b/src/plugins/diff-dom.ts @@ -1,12 +1,23 @@ // @ts-ignore -import { DiffDOM } from "diff-dom" +import { DiffDOM, nodeToObj, stringToObj } from "diff-dom" import { StreamElement, TurboStreamActions } from "@hotwired/turbo" +const dd = new DiffDOM() + export function morph(this: StreamElement) { + console.log("diff-dom") + // const _childrenOnly = this.hasAttribute("children-only") - this.targetElements.forEach((_element: Element) => { - DiffDOM() + this.targetElements.forEach((element: Element) => { + // newHtml should replace the `children-only` attribute + const newHtml = this.templateElement.innerHTML + const diff = dd.diff(element, newHtml.trim()) + const result = dd.apply(element, diff) + + if (!result) { + console.log("diff from DiffDOM could not be applied") + } }) } diff --git a/src/plugins/diffhtml.ts b/src/plugins/diffhtml.ts index a00f8f7..a3dd89b 100644 --- a/src/plugins/diffhtml.ts +++ b/src/plugins/diffhtml.ts @@ -3,10 +3,14 @@ import { innerHTML } from 'diffhtml' import { StreamElement, TurboStreamActions } from "@hotwired/turbo" export function morph(this: StreamElement) { - // const _childrenOnly = this.hasAttribute("children-only") + console.log("diffhtml") - this.targetElements.forEach((_element: Element) => { - innerHTML() + // TODO childrenOnly case works as expected, but morphing the root element doesn't + const childrenOnly = this.hasAttribute("children-only") + const newHtml = childrenOnly ? this.templateContent : this.templateElement.innerHTML + + this.targetElements.forEach((element: Element) => { + innerHTML(element, newHtml) }) } diff --git a/src/plugins/idiomorph.ts b/src/plugins/idiomorph.ts index 098c8a6..9176638 100644 --- a/src/plugins/idiomorph.ts +++ b/src/plugins/idiomorph.ts @@ -3,10 +3,19 @@ import Idiomorph from "idiomorph" import { StreamElement, TurboStreamActions } from "@hotwired/turbo" export function morph(this: StreamElement) { - // const _childrenOnly = this.hasAttribute("children-only") + console.log("idiomorph") - this.targetElements.forEach((_element: Element) => { - Idiomorph.morph() + const childrenOnly = this.hasAttribute("children-only") + const newHtml = childrenOnly ? this.templateContent : this.templateElement.innerHTML + + const options: {morphStyle?: String} = {} + + if (childrenOnly) { + options.morphStyle = 'innerHTML' + } + + this.targetElements.forEach((element: Element) => { + Idiomorph.morph(element, newHtml, options); }) } diff --git a/src/plugins/micromorph.ts b/src/plugins/micromorph.ts index 12eda39..265e581 100644 --- a/src/plugins/micromorph.ts +++ b/src/plugins/micromorph.ts @@ -2,11 +2,19 @@ import micromorph from "micromorph" import { StreamElement, TurboStreamActions } from "@hotwired/turbo" +const parser = new DOMParser() + export function morph(this: StreamElement) { - // const _childrenOnly = this.hasAttribute("children-only") + console.log("micromorph") + const childrenOnly = this.hasAttribute("children-only") + + // TODO: check children-only attribute, it currently replaces the whole parent element with the new content + const newHtml = childrenOnly + ? this.templateContent + : parser.parseFromString(this.templateElement.innerHTML, 'text/html').body.children[0] - this.targetElements.forEach((_element: Element) => { - // TODO + this.targetElements.forEach((element: Element) => { + micromorph(element, newHtml); }) } diff --git a/src/plugins/morphdom.ts b/src/plugins/morphdom.ts index 5dcc987..a0b43f2 100644 --- a/src/plugins/morphdom.ts +++ b/src/plugins/morphdom.ts @@ -2,12 +2,13 @@ import morphdom from "morphdom" import { StreamElement, TurboStreamActions } from "@hotwired/turbo" export function morph(this: StreamElement) { - const options = { - childrenOnly: this.hasAttribute("children-only") - } + console.log("morphdom") + + const childrenOnly = this.hasAttribute("children-only") + const newHtml = childrenOnly ? this.templateContent : this.templateElement.innerHTML this.targetElements.forEach(element => { - morphdom(element, options.childrenOnly ? this.templateContent : this.templateElement.innerHTML, options) + morphdom(element, newHtml, { childrenOnly }) }) } diff --git a/src/plugins/nanomorph.ts b/src/plugins/nanomorph.ts index 7d10aba..93acf7c 100644 --- a/src/plugins/nanomorph.ts +++ b/src/plugins/nanomorph.ts @@ -1,14 +1,25 @@ // @ts-ignore import nanomorph from "nanomorph" -// import nanohtml from "nanohtml" + +// @ts-ignore +import nanohtml from "nanohtml" import { StreamElement, TurboStreamActions } from "@hotwired/turbo" export function morph(this: StreamElement) { - // const _childrenOnly = this.hasAttribute("children-only") + console.log("nanomorph") + + // childrenOnly attribute doesn't work yet + // const childrenOnly = this.hasAttribute("children-only") + // const newHtml = childrenOnly ? this.templateContent.children[0] : nanohtml`${this.templateElement.innerHTML}` + + // let html = nanohtml`${this.templateElement.innerHTML.trim()}` + // let html = childrenOnly ? nanohtml`${this.templateContent.children[0].innerHTML}` : nanohtml`${this.templateElement.innerHTML.trim()}` + + const html = nanohtml`${this.templateContent.children[0]}` - this.targetElements.forEach((_element: Element) => { - nanomorph() + this.targetElements.forEach((element: Element) => { + nanomorph(element, html) }) }