Skip to content

Commit 28dbfd2

Browse files
authored
Support more filenames + folders (#10)
1 parent e392d99 commit 28dbfd2

File tree

8 files changed

+83
-5
lines changed

8 files changed

+83
-5
lines changed

Gemfile

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ gem "puma"
1010
gem "debug", ">= 1.0.0"
1111
gem "capybara"
1212
gem "selenium-webdriver"
13+
gem "sqlite3", "~> 1.4"

README.md

+27-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,33 @@ custom_elements/hello_element.js // will register <app-hello> automatically
4949

5050
Your `*_element.js` files have to `export default` custom elements for this to work properly.
5151

52-
> [!WARNING]
53-
> Only single word elements are supported currently. See https://github.com/codergeek121/custom_elements-rails/issues/1
52+
### Naming Convention for Custom Elements
53+
54+
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:
55+
56+
#### Usage
57+
58+
Register all files in the `custom_elements` folder as custom elements using a prefix (e.g., `app`):
59+
60+
```js
61+
eagerDefineCustomElementsFrom("custom_elements", { prefix: "app" });
62+
```
63+
64+
#### Conversion Rules
65+
66+
- Filenames are transformed into kebab-case (lowercase with hyphens).
67+
- Words are separated by underscores (`_`) or hyphens (`-`) in the filename.
68+
- The folder structure is reflected in the name using double hyphens (`--`) to separate folder names from the file name.
69+
- A prefix (e.g., `app`) is added to the beginning of each custom element name.
70+
71+
#### Examples
72+
73+
| Filepath | Generated Custom Element Name |
74+
|-------------------------------------|--------------------------------|
75+
| `custom_elements/demo_element.js` | `<app-demo>` |
76+
| `custom_elements/demo-element.js` | `<app-demo>` |
77+
| `custom_elements/foo_bar_element.js`| `<app-foo-bar>` |
78+
| `custom_elements/folder/foo_bar_element.js` | `<app-folder--foo-bar>` |
5479

5580
## Add a custom element with the built-in generator
5681

app/assets/javascript/custom_elements-rails.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
export function eagerDefineCustomElementsFrom(namespace, options = {}) {
2+
const pathToElementName = (path) => {
3+
const parts = path.split('/').map(p => p.replace(/_/g, '-'));
4+
return `${options.prefix}-${parts.slice(0, -1).join('--')}${parts.length > 1 ? '--' : ''}${parts.at(-1)}`;
5+
}
26
const importmap = document.querySelector('script[type="importmap"]')
37
const { imports } = JSON.parse(importmap.textContent)
4-
const regex = new RegExp(`${namespace}\/(.*?)_element`)
8+
const regex = new RegExp(`${namespace}/(.*?)[-_]element`)
59
Object.entries(imports)
610
.filter(([name, _]) => name.match(regex) )
7-
.map(([name, importPath]) => [name.match(regex)[1], importPath])
11+
.map(([name, importPath]) => { return [pathToElementName(name.match(regex)[1]), importPath] })
812
.forEach(([name, importPath]) => {
913
import(importPath)
1014
.then((module) => {
11-
customElements.define(`${options.prefix}-${name}`, module.default)
15+
customElements.define(name, module.default)
1216
})
1317
.catch((error) => {
1418
console.error(`custom_elements-rails: Could not import custom element <${options.prefix}-${name}>`)

test/custom_elements/integration_test.rb

+18
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,22 @@ class CustomElements::IntegrationTest < ApplicationSystemTestCase
66

77
assert_text "connectedCallback(): hello_element.js"
88
end
9+
10+
test "foo_bar_element.js connects" do
11+
visit elements_path
12+
13+
assert_text "connectedCallback(): foo_bar_element.js"
14+
end
15+
16+
test "some-name-element.js connects" do
17+
visit elements_path
18+
19+
assert_text "connectedCallback(): some-name-element.js"
20+
end
21+
22+
test "namespace/demo_element.js connects" do
23+
visit elements_path
24+
25+
assert_text "connectedCallback(): demo_element.js"
26+
end
927
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default class extends HTMLElement {
2+
constructor() {
3+
super()
4+
}
5+
6+
connectedCallback() {
7+
this.textContent = "connectedCallback(): foo_bar_element.js"
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default class extends HTMLElement {
2+
constructor() {
3+
super()
4+
}
5+
6+
connectedCallback() {
7+
this.textContent = "connectedCallback(): demo_element.js"
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default class extends HTMLElement {
2+
constructor() {
3+
super()
4+
}
5+
6+
connectedCallback() {
7+
this.textContent = "connectedCallback(): some-name-element.js"
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
<h1>Elements#show</h1>
22

33
<app-hello></app-hello>
4+
<app-foo-bar></app-foo-bar>
5+
<app-some-name></app-some-name>
6+
<app-namespace--demo></app-namespace--demo>

0 commit comments

Comments
 (0)