Skip to content

Commit

Permalink
Svelte 5 support
Browse files Browse the repository at this point in the history
  • Loading branch information
skryukov committed Nov 3, 2024
1 parent 7fdfafa commit f7460e2
Show file tree
Hide file tree
Showing 33 changed files with 647 additions and 100 deletions.
45 changes: 37 additions & 8 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,49 @@ on:
pull_request:

jobs:
lint:
runs-on: ubuntu-latest
name: Linter
env:
BUNDLE_JOBS: 4
BUNDLE_RETRY: 3
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3"
bundler: latest
bundler-cache: true
- name: Run StandardRB
run: bundle exec standardrb


build:
runs-on: ubuntu-latest
name: Ruby ${{ matrix.ruby }}
env:
BUNDLE_JOBS: 4
BUNDLE_RETRY: 3
strategy:
matrix:
ruby:
- "3.3"
- "3.2"
- "3.1"
- "3.0"

steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run the default task
run: bundle exec rake
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
bundler: latest
- name: Set Node.js 22.x
uses: actions/setup-node@v3
with:
node-version: 22.x
- name: Run tests
run: bundle exec rspec
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning].

## [Unreleased]

### Added

- [BREAKING] Support Svelte 5. ([@skryukov])
`turbo-mount/svelte` is now the Svelte 5 plugin. The Svelte 4 plugin is now `turbo-mount/svelte4`.

## [0.3.3] - 2024-09-24

### Added
Expand Down
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ gemspec
gem "rake", "~> 13.0"

gem "standard", "~> 1.3"

gem "rspec", "~> 3.0"

gem "generator_spec", "~> 0.10"
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ This will generate the following HTML:

- React: `"turbo-mount/react"`
- Vue: `"turbo-mount/vue"`
- Svelte: `"turbo-mount/svelte"`
- Svelte 4: `"turbo-mount/svelte4"`
- Svelte 5: `"turbo-mount/svelte"`

To add support for other frameworks, create a custom plugin. See included plugins for examples.

Expand Down
6 changes: 5 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# frozen_string_literal: true

require "bundler/gem_tasks"
require "rspec/core/rake_task"

RSpec::Core::RakeTask.new(:spec)

require "standard/rake"

task default: :standard
task default: %i[spec standard]
8 changes: 3 additions & 5 deletions app/assets/javascripts/turbo-mount.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,9 @@ class TurboMount {
this.application.turboMount = this;
this.application.register("turbo-mount", TurboMountController);
document.addEventListener("turbo:before-morph-element", (event) => {
var _a;
const turboMorphEvent = event;
const { target, detail } = turboMorphEvent;
if ((_a = target.getAttribute("data-controller")) === null || _a === void 0 ? void 0 : _a.includes("turbo-mount")) {
if (target.getAttribute("data-controller")?.includes("turbo-mount")) {
target.setAttribute("data-turbo-mount-props-value", detail.newElement.getAttribute("data-turbo-mount-props-value") ||
"{}");
event.preventDefault();
Expand Down Expand Up @@ -112,15 +111,14 @@ const identifierNames = (name) => {
return [`turbo-mount--${controllerName}`, `turbo-mount-${controllerName}`];
};
const registerComponentsBase = ({ plugin, turboMount, components, controllers, }) => {
var _a;
const controllerModules = controllers !== null && controllers !== void 0 ? controllers : [];
const controllerModules = controllers ?? [];
for (const { module, filename } of components) {
const name = filename
.replace(/\.\w*$/, "")
.replace(/^[./]*components\//, "");
const identifiers = identifierNames(name);
const controller = controllerModules.find(({ identifier }) => identifiers.includes(identifier));
const component = (_a = module.default) !== null && _a !== void 0 ? _a : module;
const component = module.default ?? module;
if (controller) {
turboMount.register(plugin, name, component, controller.controllerConstructor);
}
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/turbo-mount.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/assets/javascripts/turbo-mount.min.js.map

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions app/assets/javascripts/turbo-mount/svelte.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { buildRegisterFunction } from 'turbo-mount';
export { TurboMount } from 'turbo-mount';
import { mount, unmount } from 'svelte';

const plugin = {
mountComponent: (mountProps) => {
const { el, Component, props } = mountProps;
const component = new Component({ target: el, props });
const component = mount(Component, { target: el, props });
return () => {
component.$destroy();
unmount(component);
};
},
};
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascripts/turbo-mount/svelte.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/assets/javascripts/turbo-mount/svelte.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions app/assets/javascripts/turbo-mount/svelte4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { buildRegisterFunction } from 'turbo-mount';
export { TurboMount } from 'turbo-mount';

const plugin = {
mountComponent: (mountProps) => {
const { el, Component, props } = mountProps;
const component = new Component({ target: el, props });
return () => {
component.$destroy();
};
},
};
const registerComponent = buildRegisterFunction(plugin);

export { plugin as default, registerComponent };
2 changes: 2 additions & 0 deletions app/assets/javascripts/turbo-mount/svelte4.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions app/assets/javascripts/turbo-mount/svelte4.min.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions lib/generators/turbo_mount/frameworks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
react:
pins: "react react-dom react-dom/client"
npm_packages: "react react-dom"
vite_plugin: "@vitejs/plugin-react"
extension: "jsx"

vue:
pins: "vue"
npm_packages: "vue"
vite_plugin: "@vitejs/plugin-vue"
extension: "vue"

svelte4:
pins: "svelte"
npm_packages: "svelte@4"
vite_plugin: "@sveltejs/vite-plugin-svelte"
extension: "svelte"

svelte:
pins: "svelte"
npm_packages: "svelte@5"
vite_plugin: "@sveltejs/vite-plugin-svelte"
extension: "svelte"
61 changes: 61 additions & 0 deletions lib/generators/turbo_mount/helpers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
module TurboMount
module Generators
module Helpers
### FS Helpers
def js_destination_path
return ViteRuby.config.source_code_dir if defined?(ViteRuby)

if file?("config/vite.json")
source_code_dir = JSON.parse(File.read(file_path("config/vite.json"))).dig("all", "sourceCodeDir")
return source_code_dir || "app/frontend"
end

"app/javascript"
end

def js_destination_root
file_path(js_destination_path)
end

def js_entrypoint
if vite?
js_file_path "entrypoints/application.js"
else
js_file_path "application.js"
end
end

def js_file_path(*relative_path)
File.join(js_destination_root, *relative_path)
end

def file?(*relative_path)
File.file?(file_path(*relative_path))
end

def file_path(*relative_path)
File.join(destination_root, *relative_path)
end

def vite?
file?("config/vite.json") && Dir.glob(file_path("vite.config.*")).any?
end

# Interactivity Helpers
def ask(*)
unless options[:interactive]
say_error "Specify all options when running the generator non-interactively.", :red
exit(1)
end

super
end

def yes?(*)
return false unless options[:interactive]

super
end
end
end
end
2 changes: 1 addition & 1 deletion lib/generators/turbo_mount/install/turbo-mount.js.tt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ const turboMount = new TurboMount();
// If you want to automatically register components use:
// import { registerComponents } from "turbo-mount/registerComponents/<%= framework %>";
// const controllers = import.meta.glob("/controllers/**/*_controller.js", { eager: true });
// const components = import.meta.glob("/components/**/*.jsx", { eager: true });
// const components = import.meta.glob("/components/**/*.<%= extension %>", { eager: true });
// registerComponents({ turboMount, components, controllers });
<%- end -%>
Loading

0 comments on commit f7460e2

Please sign in to comment.