diff --git a/Gemfile b/Gemfile index b58f7c7..a973ea1 100644 --- a/Gemfile +++ b/Gemfile @@ -10,3 +10,4 @@ gem "puma" gem "debug", ">= 1.0.0" gem "capybara" gem "selenium-webdriver" +gem "sqlite3", "~> 1.4" diff --git a/README.md b/README.md index f50aec9..444040c 100644 --- a/README.md +++ b/README.md @@ -49,8 +49,33 @@ custom_elements/hello_element.js // will register automatically Your `*_element.js` files have to `export default` custom elements for this to work properly. -> [!WARNING] -> Only single word elements are supported currently. See https://github.com/codergeek121/custom_elements-rails/issues/1 +### Naming Convention for Custom Elements + +When defining custom elements from files, their filenames are used to generate the element names automatically. The following rules and examples clarify how file paths are converted to custom element names: + +#### Usage + +Register all files in the `custom_elements` folder as custom elements using a prefix (e.g., `app`): + +```js +eagerDefineCustomElementsFrom("custom_elements", { prefix: "app" }); +``` + +#### Conversion Rules + +- Filenames are transformed into kebab-case (lowercase with hyphens). +- Words are separated by underscores (`_`) or hyphens (`-`) in the filename. +- The folder structure is reflected in the name using double hyphens (`--`) to separate folder names from the file name. +- A prefix (e.g., `app`) is added to the beginning of each custom element name. + +#### Examples + +| Filepath | Generated Custom Element Name | +|-------------------------------------|--------------------------------| +| `custom_elements/demo_element.js` | `` | +| `custom_elements/demo-element.js` | `` | +| `custom_elements/foo_bar_element.js`| `` | +| `custom_elements/folder/foo_bar_element.js` | `` | ## Add a custom element with the built-in generator diff --git a/app/assets/javascript/custom_elements-rails.js b/app/assets/javascript/custom_elements-rails.js index 8dc8a60..73dc1c7 100644 --- a/app/assets/javascript/custom_elements-rails.js +++ b/app/assets/javascript/custom_elements-rails.js @@ -1,14 +1,18 @@ export function eagerDefineCustomElementsFrom(namespace, options = {}) { + const pathToElementName = (path) => { + const parts = path.split('/').map(p => p.replace(/_/g, '-')); + return `${options.prefix}-${parts.slice(0, -1).join('--')}${parts.length > 1 ? '--' : ''}${parts.at(-1)}`; + } const importmap = document.querySelector('script[type="importmap"]') const { imports } = JSON.parse(importmap.textContent) - const regex = new RegExp(`${namespace}\/(.*?)_element`) + const regex = new RegExp(`${namespace}/(.*?)[-_]element`) Object.entries(imports) .filter(([name, _]) => name.match(regex) ) - .map(([name, importPath]) => [name.match(regex)[1], importPath]) + .map(([name, importPath]) => { return [pathToElementName(name.match(regex)[1]), importPath] }) .forEach(([name, importPath]) => { import(importPath) .then((module) => { - customElements.define(`${options.prefix}-${name}`, module.default) + customElements.define(name, module.default) }) .catch((error) => { console.error(`custom_elements-rails: Could not import custom element <${options.prefix}-${name}>`) diff --git a/test/custom_elements/integration_test.rb b/test/custom_elements/integration_test.rb index afadad4..49c8a5c 100644 --- a/test/custom_elements/integration_test.rb +++ b/test/custom_elements/integration_test.rb @@ -6,4 +6,22 @@ class CustomElements::IntegrationTest < ApplicationSystemTestCase assert_text "connectedCallback(): hello_element.js" end + + test "foo_bar_element.js connects" do + visit elements_path + + assert_text "connectedCallback(): foo_bar_element.js" + end + + test "some-name-element.js connects" do + visit elements_path + + assert_text "connectedCallback(): some-name-element.js" + end + + test "namespace/demo_element.js connects" do + visit elements_path + + assert_text "connectedCallback(): demo_element.js" + end end diff --git a/test/dummy/app/javascript/custom_elements/foo_bar_element.js b/test/dummy/app/javascript/custom_elements/foo_bar_element.js new file mode 100644 index 0000000..08e42f7 --- /dev/null +++ b/test/dummy/app/javascript/custom_elements/foo_bar_element.js @@ -0,0 +1,9 @@ +export default class extends HTMLElement { + constructor() { + super() + } + + connectedCallback() { + this.textContent = "connectedCallback(): foo_bar_element.js" + } +} diff --git a/test/dummy/app/javascript/custom_elements/namespace/demo_element.js b/test/dummy/app/javascript/custom_elements/namespace/demo_element.js new file mode 100644 index 0000000..3cbdafd --- /dev/null +++ b/test/dummy/app/javascript/custom_elements/namespace/demo_element.js @@ -0,0 +1,9 @@ +export default class extends HTMLElement { + constructor() { + super() + } + + connectedCallback() { + this.textContent = "connectedCallback(): demo_element.js" + } +} diff --git a/test/dummy/app/javascript/custom_elements/some-name-element.js b/test/dummy/app/javascript/custom_elements/some-name-element.js new file mode 100644 index 0000000..6470b9a --- /dev/null +++ b/test/dummy/app/javascript/custom_elements/some-name-element.js @@ -0,0 +1,9 @@ +export default class extends HTMLElement { + constructor() { + super() + } + + connectedCallback() { + this.textContent = "connectedCallback(): some-name-element.js" + } +} diff --git a/test/dummy/app/views/elements/show.html.erb b/test/dummy/app/views/elements/show.html.erb index 9347b36..d386720 100644 --- a/test/dummy/app/views/elements/show.html.erb +++ b/test/dummy/app/views/elements/show.html.erb @@ -1,3 +1,6 @@

Elements#show

+ + +