Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/dvinciguerra/middleman-importmap
Importmap extension port for Middleman
https://github.com/dvinciguerra/middleman-importmap
frontend importmaps middleman middleman-extension ruby rubygem
Last synced: 3 months ago
JSON representation
Importmap extension port for Middleman
- Host: GitHub
- URL: https://github.com/dvinciguerra/middleman-importmap
- Owner: dvinciguerra
- License: mit
- Created: 2022-03-04T21:13:45.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-05-10T12:56:15.000Z (8 months ago)
- Last Synced: 2024-10-14T02:42:52.371Z (3 months ago)
- Topics: frontend, importmaps, middleman, middleman-extension, ruby, rubygem
- Language: Ruby
- Homepage: https://rubygems.org/gems/middleman-importmap
- Size: 43.9 KB
- Stars: 4
- Watchers: 1
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# middleman-importmap
[![Maintainability](https://api.codeclimate.com/v1/badges/aab4c3c09d920639f962/maintainability)](https://codeclimate.com/github/dvinciguerra/middleman-importmap/maintainability)
An Importmap extension for Middleman.
## Install
**Add gem to `Gemfile`**
`gem 'middleman-importmap'`
## Usage
#### Activate extension in `config.rb`**
```ruby
activate :importmap
```#### Create the `importmap.yml` file at middleman root path
```shell
$ cd middleman_project && touch importmap.yml
```#### Add importmaps to file (example)
```yaml
imports:
"@hotwired/stimulus": https://unpkg.com/@hotwired/stimulus/dist/stimulus.js
```The importmap.yml file keep the same structure of importmap in HTML
#### Replace default javascript tag by importmap
```ruby
<%= current_page.data.title || "Middleman" %>
<%= stylesheet_link_tag "site" %>
<%= javascript_importmap_tags %>
<%= yield %>
```
#### Customize options if necessary
##### in `config.rb`:
```ruby
activate :importmap do |option|
option.entrypoint = "site" # js entrypoint's filename without extension
option.importmap = "importmap.yml" # importmap's filename with extension (yaml or json)
option.use_shim = true # or false
option.shim_src = "path/to/shim" # defaults to hardcoded js cdn
end
```##### or by specifying arguments in template helpers:
This will override options in config.rb
```ruby
<%= javascript_importmap_tags("main", importmap: "importmap.json", shim: false) %># or customize one by one:
<%= javascript_importmap_shim_tag(shim_src: "another/path") %>
<%= javascript_inline_importmap_tag("importmap.json", shim: true) %>
<%= javascript_inline_module_tag("main", shim: true) %># See source code for methods implementation
```## Examples
- [Creating an app using Stimulus JS](#creating-an-app-using-stimulus-js)
- [Creating an app using React and React Router](#creating-an-app-using-react-and-react-router)### Creating an app using Stimulus JS
#### Add the following code to `/source/javascripts/site.js`
```javascript
import { Application } from "@hotwired/stimulus"import HelloController from "./controllers/hello_controller.js"
window.Stimulus = Application.start()
Stimulus.register("hello", HelloController)
```#### Create `controllers` directory
```shell
$ mkdir -p source/javascripts/controllers
```#### Now add HelloController at `controllers/hello_controller.js`
```javascript
import { Controller } from "@hotwired/stimulus"export default class extends Controller {
connect() {
console.log("Hello, Stimulus!", this.element)
}greet() {
console.log("Clicked Greet Button")
}
}
```#### One last and important thing is add element binding at `index.html.erb`
```ruby
---
title: Welcome to Middleman
---
Middleman is Running
Greet<%= link_to(
"Read Documentation",
"https://middlemanapp.com/basics/templating_language/",
target: "_blank"
) %>
```If all things are OK, than start middleman server using command `bundle exec middleman server` and open your browser devtools to see the messages.
### Creating an app using React and React Router
This example is based on [DHH's Youtube video presenting rails-importmap gem using React and htm](https://www.youtube.com/watch?v=k73LKxim6tw).
#### Change `importmap.yml` file to be like this
```yaml
---
imports:
"htm": "https://ga.jspm.io/npm:[email protected]/dist/htm.module.js"
"react": "https://ga.jspm.io/npm:[email protected]/index.js"
"react-dom": "https://ga.jspm.io/npm:[email protected]/index.js"
"react-router-dom": "https://ga.jspm.io/npm:[email protected]/dist/main.js"
"htm_create_element": "/javascripts/htm_create_element.js"scopes:
"https://ga.jspm.io/":
"@remix-run/router": "https://ga.jspm.io/npm:@remix-run/[email protected]/dist/router.js"
"react-router": "https://ga.jspm.io/npm:[email protected]/dist/main.js"
"scheduler": "https://ga.jspm.io/npm:[email protected]/index.js"
```#### Create `source/javascripts/htm_create_element.js` file
This file is necessary to use htm with React in an environment that doesn't have build process of JSX files.
```javascript
import { createElement } from 'react'
import htm from 'htm'export const h = htm.bind(createElement)
```#### Create `components` and `pages` directories
```shell
mkdir -p source/javascripts/components && mkdir -p source/javascripts/pages
```#### Create `components/Page.js` file
Creating this file to avoid code duplication of components and demonstrate how to use composition in this environment.
```javascript
import { h } from "htm_create_element"const Footer = () => h`
`const Container = ({ children }) => h`
${children}
<${Footer} />
`const Title = ({ children }) => h`
${children}
`const Lead = ({ children }) => h`
${children}
`export default {
Container,
Title,
Lead
}
```#### Create `pages/Home.js` file
Now, let's create the Home page using the components created above and react-router-dom `Link` component.
```javascript
import { h } from "htm_create_element"
import { Link } from "react-router-dom"import Page from "../components/Page.js"
export default () => h`
<${Page.Container}>
<${Page.Title}>Middleman Importmap React/>
<${Page.Lead}>
This is a simple page created using Middleman-importmap and React to demonstrate how it is possible to build
frontends in Middleman using importmap without any build.
/>
<${Link}
to="/getting-started"
class="btn btn-dark btn-lg"
role="button"
>
Getting Started
/>
GitHub
/>
/>
`
```#### Create `pages/About.js` file
Creating just another page to demonstrate how to use react-router-dom `Link` behaviour.
```javascript
import { h } from "htm_create_element"
import { Link } from "react-router-dom"import Page from "../components/Page.js"
export default () => h`
<${Page.Container}>
<${Page.Title}>About/>
<${Page.Lead}>
This is a simple About page
/>
<${Link}
to="/"
class="btn btn-dark btn-lg"
role="button"
>
Back
/>
/>
```#### Create `components/App.js` file
Creating a component to wrap all pages and use react-router-dom `RouterProvider` component.
```javascript
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
import { h } from 'htm_create_element'import Home from "../pages/Home.js"
import About from "../pages/About.js"const router = createBrowserRouter([
{ path: '/', element: h`<${Home} />` },
{ path: '/about', element: h`<${About} />` }
])export default () => h`<${RouterProvider} router=${router} />`
```#### Add the following code to `site.js`
```javascript
import { render } from 'react-dom'
import { h } from 'htm_create_element'import App from "./components/App.js"
const root = document.getElementById('root')
render(h`<${App} />`, root)
```#### Add the following code to `source/index.html.erb`
```ruby
---
title: Welcome to Middleman
---```
If all things are OK, than start middleman server using command `bundle exec middleman server`, open your browser and
access [http://127.0.0.1:4567/](http://127.0.0.1:4567/).## See more
- [Importmap polyfill at guybedford/es-module-shims](https://github.com/guybedford/es-module-shims)
- [Can I Use about Import Maps browser support](https://caniuse.com/import-maps)
- [W3C Import Maps Spec](https://wicg.github.io/import-maps/)
- [The helper tags are inspired by rails/importmap-rails gem](https://github.com/rails/importmap-rails)## License
See `./LICENSE` file for more details.
## Author
Daniel Vinciguerra