├── .eleventy.js ├── .github └── workflows │ └── cla.yml ├── .gitignore ├── elements.mjs ├── elements ├── my-footer.mjs └── my-header.mjs ├── index.html ├── index.json ├── package.json ├── plugin.js ├── readme.md ├── rollup.config.js ├── utils.js └── vendor ├── enhance-ssr.js └── readme.md /.eleventy.js: -------------------------------------------------------------------------------- 1 | let plugin = require('./plugin.js') 2 | 3 | module.exports = function (eleventyConfig) { 4 | let extension = 'html' 5 | eleventyConfig.addTemplateFormats(extension) 6 | eleventyConfig.addExtension(extension, plugin) 7 | eleventyConfig.addWatchTarget("./elements/**/*.mjs") 8 | } 9 | -------------------------------------------------------------------------------- /.github/workflows/cla.yml: -------------------------------------------------------------------------------- 1 | name: "CLA Assistant" 2 | on: 3 | issue_comment: 4 | types: [created] 5 | pull_request_target: 6 | types: [opened,closed,synchronize] 7 | 8 | permissions: 9 | actions: write 10 | contents: write 11 | pull-requests: write 12 | statuses: write 13 | 14 | jobs: 15 | CLAAssistant: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: "CLA Assistant" 19 | if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target' 20 | uses: contributor-assistant/github-action@v2.4.0 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }} 24 | with: 25 | path-to-signatures: 'signatures/v1/cla.json' 26 | path-to-document: 'https://github.com/enhance-dev/.github/blob/main/CLA.md' 27 | branch: 'main' 28 | allowlist: brianleroux,colepeters,kristoferjoseph,macdonst,ryanbethel,ryanblock,tbeseda 29 | remote-organization-name: enhance-dev 30 | remote-repository-name: .github 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | _site 3 | -------------------------------------------------------------------------------- /elements.mjs: -------------------------------------------------------------------------------- 1 | import { importWithoutCache } from './utils.js' 2 | 3 | const header = await importWithoutCache('./elements/my-header.mjs') 4 | const footer = await importWithoutCache('./elements/my-footer.mjs') 5 | 6 | export default { 7 | 'my-header': header.default, 8 | 'my-footer': footer.default 9 | } 10 | -------------------------------------------------------------------------------- /elements/my-footer.mjs: -------------------------------------------------------------------------------- 1 | export default function Footer ({ html, state }) { 2 | return html`` 3 | } 4 | -------------------------------------------------------------------------------- /elements/my-header.mjs: -------------------------------------------------------------------------------- 1 | export default function Header ({ html }) { 2 | return html`

header

home
` 3 | } 4 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | hi from cloud eh 3 | 4 | -------------------------------------------------------------------------------- /index.json: -------------------------------------------------------------------------------- 1 | { 2 | "initialState": { 3 | "whatever": true, 4 | "you": 1, 5 | "want": "yay" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@enhance/eleventy-plugin", 3 | "version": "1.0.2", 4 | "main": "plugin.js", 5 | "scripts": { 6 | "build": "rollup -c", 7 | "start": "eleventy --serve" 8 | }, 9 | "devDependencies": { 10 | "@11ty/eleventy": "^1.0.1", 11 | "@enhance/ssr": "^3.0.0", 12 | "@rollup/plugin-commonjs": "^22.0.1", 13 | "@rollup/plugin-json": "^4.1.0", 14 | "@rollup/plugin-node-resolve": "^13.3.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /plugin.js: -------------------------------------------------------------------------------- 1 | let enhance = require('./vendor/enhance-ssr.js') 2 | let { join } = require('path') 3 | let { existsSync: exists, readdirSync: ls } = require('fs') 4 | let { importWithoutCache } = require('./utils') 5 | 6 | module.exports = { 7 | async compile (inputContent) { 8 | return async function compiler ({ initialState={} }) { 9 | let elements = await read() 10 | let html = enhance({ elements, initialState }) 11 | return html`${ inputContent }` 12 | } 13 | } 14 | } 15 | 16 | async function read () { 17 | 18 | let pathToModule = join(process.cwd(), 'elements.mjs') 19 | let pathToDirectory = join(process.cwd(), 'elements') 20 | 21 | if (exists(pathToModule)) { 22 | // read explicit elements manifest 23 | let els = await importWithoutCache(pathToModule) 24 | return els.default || els 25 | } 26 | else if (exists(pathToDirectory)) { 27 | // generate based on elements/ directory 28 | let els = {} 29 | let raw = ls(pathToDirectory) 30 | for (let e of raw) { 31 | let tag = e.replace('.mjs', '') 32 | let mod = await importWithoutCache(join(pathToDirectory, e)) 33 | els[tag] = mod.default 34 | } 35 | return els 36 | } 37 | else { 38 | // generate based on page.html or page.mjs requested 39 | throw Error('cannot find `elements.mjs` or an `elements/` folder') 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # `@enhance/eleventy-plugin` 2 | 3 | Build static websites with custom elements. 4 | 5 | ## Quickstart 6 | 7 | Create a project. 8 | 9 | ``` bash 10 | mkdir -p myproject && cd myproject 11 | npm init -y 12 | npm install @11ty/eleventy @enhance/eleventy-plugin 13 | ``` 14 | 15 | Add some handy shortcuts to `scripts` in `package.json`. 16 | 17 | ```json 18 | { 19 | "scripts": { 20 | "start": "npx @11ty/eleventy --serve" 21 | } 22 | } 23 | ``` 24 | 25 | Add the `@enhance/plugin-eleventy` to `.eleventy.js` config file. 26 | 27 | ```javascript 28 | let plugin = require('@enhance/eleventy-plugin') 29 | 30 | module.exports = function (eleventyConfig) { 31 | let extension = 'html' 32 | eleventyConfig.addTemplateFormats(extension) 33 | eleventyConfig.addExtension(extension, plugin) 34 | eleventyConfig.addWatchTarget("./elements/**/*.mjs") 35 | } 36 | ``` 37 | 38 | Write some HTML. 39 | 40 | ```html 41 | 42 | 43 | powerful html here 44 | 45 | ``` 46 | 47 | Define custom element templates in a folder named `elements`. 48 | 49 | ```javascript 50 | /** elements/my-header.mjs */ 51 | export default function header ({ html }) { 52 | return html`
my cool header
` 53 | } 54 | ``` 55 | 56 | ```javascript 57 | /** elements/my-footer.mjs */ 58 | export default function footer ({ html, state }) { 59 | return html` 60 | 64 | ` 65 | } 66 | ``` 67 | 68 | Run `npm start`, and preview at `http://localhost:8080`. 69 | 70 | ## Add data 71 | 72 | Add `index.json` with some default data, and preview result in the footer. 73 | 74 | ```json 75 | { 76 | "initialState": { "custom": "data", "is": "here" } 77 | } 78 | ``` 79 | 80 | ## Rename elements 81 | 82 | If you want to configure your own element tag names create `./elements.mjs` to explicitly define tags: 83 | 84 | ```javascript 85 | import header from './elements/my-header.mjs' 86 | import footer from './elements/my-footer.mjs' 87 | 88 | export default { 89 | 'my-header': header, 90 | 'my-footer': footer 91 | } 92 | ``` 93 | 94 | > Don't forget to update your corresponding `index.html`! 95 | 96 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import commonjs from '@rollup/plugin-commonjs' 2 | import json from '@rollup/plugin-json' 3 | import { nodeResolve } from '@rollup/plugin-node-resolve'; 4 | 5 | export default { 6 | input: 'node_modules/@enhance/ssr/index.mjs', 7 | output: { 8 | file: `vendor/enhance-ssr.js`, 9 | format: 'cjs' 10 | }, 11 | plugins: [ 12 | nodeResolve(), 13 | commonjs({ignore: ['fs', 'path']}), 14 | json() 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | const importWithoutCache = async (path) => { 2 | return await import(`${path}?cacheBust=${Date.now()}`) 3 | } 4 | 5 | exports.importWithoutCache = importWithoutCache; -------------------------------------------------------------------------------- /vendor/readme.md: -------------------------------------------------------------------------------- 1 | we have to do this because enhance-ssr is a node-native esmodule (which can't be loaded by a node-native commonjs module because reasons) 2 | --------------------------------------------------------------------------------