diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 082e5fc..0000000 --- a/.eslintrc +++ /dev/null @@ -1,2 +0,0 @@ -root: true -extends: fnd-jsx diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5dd4d4b..d9f40fa 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,13 +1,16 @@ version: 2 updates: - # Maintain dependencies for GitHub Actions - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" - # Maintain dependencies for npm - package-ecosystem: "npm" directory: "/" schedule: interval: "daily" + + - package-ecosystem: "bundler" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 257f083..b2131aa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,18 +1,19 @@ name: tests on: -- push + - push jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - node-version: - - 18.x - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 - with: - node-version: ${{ matrix.node-version }} - - run: npm install-test - env: - CI: true + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '22.x' + cache: 'npm' + - run: npm ci + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + bundler-cache: true + - run: bundle exec bridgetown frontend:build + - run: bundle exec bridgetown build diff --git a/.gitignore b/.gitignore index 3526419..a563d04 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ /node_modules -/.eslintcache - -/dist +/.gems +/.bridgetown-cache +/compact_index +/output +/tmp +/.envrc diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..29deb70 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source "https://rubygems.org" + +gem "bridgetown", "~> 2.0.0.beta2" +gem "puma" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..b958c88 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,170 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (7.2.2.1) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + amazing_print (1.7.2) + base64 (0.2.0) + benchmark (0.4.0) + bigdecimal (3.1.9) + bridgetown (2.0.0.beta4) + bridgetown-builder (= 2.0.0.beta4) + bridgetown-core (= 2.0.0.beta4) + bridgetown-foundation (= 2.0.0.beta4) + bridgetown-paginate (= 2.0.0.beta4) + bridgetown-builder (2.0.0.beta4) + bridgetown-core (= 2.0.0.beta4) + bridgetown-core (2.0.0.beta4) + activesupport (>= 6.0, < 8.0) + addressable (~> 2.4) + amazing_print (~> 1.2) + bridgetown-foundation (= 2.0.0.beta4) + csv (~> 3.2) + dry-inflector (>= 1.0) + erubi (~> 1.9) + faraday (~> 2.0) + faraday-follow_redirects (~> 0.3) + i18n (~> 1.0) + irb (>= 1.14) + kramdown (~> 2.1) + kramdown-parser-gfm (~> 1.0) + liquid (>= 5.0, < 5.5) + listen (~> 3.0) + rack (>= 3.0) + rackup (~> 2.0) + rake (>= 13.0) + roda (~> 3.46) + rouge (>= 3.0, < 5.0) + serbea (~> 2.1) + signalize (~> 1.3) + streamlined (>= 0.6.0) + thor (~> 1.1) + tilt (~> 2.0) + zeitwerk (~> 2.5) + bridgetown-foundation (2.0.0.beta4) + hash_with_dot_access (~> 2.0) + inclusive (~> 1.0) + zeitwerk (~> 2.5) + bridgetown-paginate (2.0.0.beta4) + bridgetown-core (= 2.0.0.beta4) + concurrent-ruby (1.3.5) + connection_pool (2.5.0) + csv (3.3.2) + date (3.4.1) + drb (2.2.1) + dry-inflector (1.2.0) + erubi (1.13.1) + faraday (2.12.2) + faraday-net_http (>= 2.0, < 3.5) + json + logger + faraday-follow_redirects (0.3.0) + faraday (>= 1, < 3) + faraday-net_http (3.4.0) + net-http (>= 0.5.0) + ffi (1.17.1) + ffi (1.17.1-aarch64-linux-gnu) + ffi (1.17.1-aarch64-linux-musl) + ffi (1.17.1-arm-linux-gnu) + ffi (1.17.1-arm-linux-musl) + ffi (1.17.1-arm64-darwin) + ffi (1.17.1-x86-linux-gnu) + ffi (1.17.1-x86-linux-musl) + ffi (1.17.1-x86_64-darwin) + ffi (1.17.1-x86_64-linux-gnu) + ffi (1.17.1-x86_64-linux-musl) + hash_with_dot_access (2.1.1) + i18n (1.14.7) + concurrent-ruby (~> 1.0) + inclusive (1.0.0) + io-console (0.8.0) + irb (1.15.1) + pp (>= 0.6.0) + rdoc (>= 4.0.0) + reline (>= 0.4.2) + json (2.9.1) + kramdown (2.5.1) + rexml (>= 3.3.9) + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (5.4.0) + listen (3.9.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + logger (1.6.5) + minitest (5.25.4) + net-http (0.6.0) + uri + nio4r (2.7.4) + pp (0.6.2) + prettyprint + prettyprint (0.2.0) + psych (5.2.3) + date + stringio + public_suffix (6.0.1) + puma (6.5.0) + nio4r (~> 2.0) + rack (3.1.8) + rackup (2.2.1) + rack (>= 3) + rake (13.2.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) + rdoc (6.11.0) + psych (>= 4.0.0) + reline (0.6.0) + io-console (~> 0.5) + rexml (3.4.0) + roda (3.88.0) + rack + rouge (4.5.1) + securerandom (0.4.1) + serbea (2.2.0) + erubi (>= 1.10) + tilt (~> 2.0) + signalize (1.3.0) + concurrent-ruby (~> 1.2) + streamlined (0.6.0) + serbea (>= 2.1) + zeitwerk (~> 2.5) + stringio (3.1.2) + thor (1.3.2) + tilt (2.6.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uri (1.0.2) + zeitwerk (2.7.1) + +PLATFORMS + aarch64-linux-gnu + aarch64-linux-musl + arm-linux-gnu + arm-linux-musl + arm64-darwin + ruby + x86-linux-gnu + x86-linux-musl + x86_64-darwin + x86_64-linux-gnu + x86_64-linux-musl + +DEPENDENCIES + bridgetown (~> 2.0.0.beta2) + puma + +BUNDLED WITH + 2.5.11 diff --git a/README.md b/README.md index be80e57..a4ff8e5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,3 @@ -[![Netlify -Status](https://api.netlify.com/api/v1/badges/79fe58f2-05cd-4e71-9563-703a16605716/deploy-status)](https://app.netlify.com/sites/faucet-pipeline/deploys) - # faucet-pipeline Documentation This repository contains the documentation for the faucet-pipeline project. @@ -8,13 +5,21 @@ The documentation can be found at: [www.faucet-pipeline.org](https://www.faucet-pipeline.org) -It is deployed automatically via Netlify. - ## Contributing -* ensure [Node](http://nodejs.org) is installed -* `npm install` downloads dependencies -* `npm run compile` generates the site at `dist/site` -* `npm start` automatically recompiles while monitoring code changes - the site - is available at http://localhost:8000 -* `npm test` checks code for stylistic consistency +You need Ruby & Node, then run: + +* `bundle` +* `npm i` +* `bundle exec bridgetown start` (or `just start`) +* and you are good to go! + +## Deploy + +If you have `just` installed, run `just deploy`. +If not, run it manually: + +* `bundle exec bridgetown clean` +* `bundle exec bridgetown frontend:build` +* `bundle exec bridgetown build` +* `rsync -uvcr --delete output/ $TARGET` diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..f44eb35 --- /dev/null +++ b/Rakefile @@ -0,0 +1,35 @@ +require "bridgetown" + +Bridgetown.load_tasks + +# Run rake without specifying any command to execute a deploy build by default. +task default: :deploy + +desc "Build the Bridgetown site for deployment" +task :deploy => [:clean, "frontend:build"] do + Bridgetown::Commands::Build.start +end + +desc "Build the site in a test environment" +task :test do + ENV["BRIDGETOWN_ENV"] = "test" + Bridgetown::Commands::Build.start +end + +desc "Runs the clean command" +task :clean do + Bridgetown::Commands::Clean.start +end + +namespace :frontend do + desc "Build the frontend with esbuild for deployment" + task :build do + sh "npm run esbuild" + end + + desc "Watch the frontend with esbuild during development" + task :dev do + sh "npm run esbuild-dev" + rescue Interrupt + end +end diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..80ee349 --- /dev/null +++ b/config.ru @@ -0,0 +1,7 @@ +# This file is used by Rack-based servers during the Bridgetown boot process. + +require "bridgetown-core/rack/boot" + +Bridgetown::Rack.boot + +run RodaApp.freeze.app # see server/roda_app.rb diff --git a/config/esbuild.defaults.js b/config/esbuild.defaults.js new file mode 100644 index 0000000..e65a158 --- /dev/null +++ b/config/esbuild.defaults.js @@ -0,0 +1,360 @@ +// This file is created and managed by Bridgetown. +// Instead of editing this file, add your overrides to `esbuild.config.js` +// +// To update this file to the latest version provided by Bridgetown, +// run `bridgetown esbuild update`. Any changes to this file will be overwritten +// when an update is applied hence we strongly recommend adding overrides to +// `esbuild.config.js` instead of editing this file. +// +// Shipped with Bridgetown v2.0.0.beta2 + +// DO NOT MANUALLY EDIT THIS CONFIGURATION: +const autogeneratedBridgetownConfig = { + "source": "src", + "destination": "output", + "componentsDir": "_components", + "islandsDir": "_islands" +} + +const path = require("path") +const fsLib = require("fs") +const fs = fsLib.promises +const { pathToFileURL, fileURLToPath } = require("url") +const glob = require("glob") +const postcss = require("postcss") +const postCssImport = require("postcss-import") +const readCache = require("read-cache") + +// Detect if an NPM package is available +const moduleAvailable = name => { + try { + require.resolve(name) + return true + } catch (e) { } + return false +} + +// Generate a Source Map URL (used by the Sass plugin) +const generateSourceMappingURL = sourceMap => { + const data = Buffer.from(JSON.stringify(sourceMap), "utf-8").toString("base64") + return `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${data} */` +} + +// Import Sass if available +let sass +if (moduleAvailable("sass")) { + sass = require("sass") +} + +// Glob plugin derived from: +// https://github.com/thomaschaaf/esbuild-plugin-import-glob +// https://github.com/xiaohui-zhangxh/jsbundling-rails/commit/b15025dcc20f664b2b0eb238915991afdbc7cb58 +const importGlobPlugin = (options, bridgetownConfig) => ({ + name: "import-glob", + setup: (build) => { + build.onResolve({ filter: /\*/ }, async (args) => { + if (args.resolveDir === "") { + return; // Ignore unresolvable paths + } + + const adjustedPath = args.path + .replace(/^\$components\/\*\*/, `../../${bridgetownConfig.source}/${bridgetownConfig.componentsDir}/**`) + .replace(/^bridgetownComponents\//, `../../${bridgetownConfig.source}/${bridgetownConfig.componentsDir}/`) // legacy + + return { + path: adjustedPath, + namespace: "import-glob", + pluginData: { + path: adjustedPath, + resolveDir: args.resolveDir, + }, + } + }) + + build.onLoad({ filter: /.*/, namespace: "import-glob" }, async (args) => { + const files = glob.sync(args.pluginData.path, { + cwd: args.pluginData.resolveDir, + }) + .filter(module => options.excludeFilter ? !options.excludeFilter.test(module) : true) + .sort() + .map(module => module.replace(`../../${bridgetownConfig.source}/${bridgetownConfig.componentsDir}/`, "$components/")) + .map(module => module.match(/^[a-zA-Z0-9]/) ? `./${module}` : module) + + const importerCode = ` + ${files + .map((module, index) => `import * as module${index} from '${module}'`) + .join(';')} + const modules = {${files + .map((module, index) => ` + "${module.replace("$components/", "")}": module${index},`) + .join("")} + }; + export default modules; + ` + + return { contents: importerCode, resolveDir: args.pluginData.resolveDir } + }) + }, +}) + +// Plugin for PostCSS +const importPostCssPlugin = (options, configuration) => ({ + name: "postcss", + async setup(build) { + // Process .css files with PostCSS + build.onLoad({ filter: (configuration.filter || /\.css$/) }, async (args) => { + if (args.path.endsWith(".lit.css")) return; + + const additionalFilePaths = [] + const css = await fs.readFile(args.path, "utf8") + + // Configure import plugin so PostCSS can properly resolve `@import`ed CSS files + const importPlugin = postCssImport({ + filter: itemPath => !itemPath.startsWith("/"), // ensure it doesn't try to import source-relative paths + load: async filename => { + let contents = await readCache(filename, "utf-8") + const filedir = path.dirname(filename) + // We'll want to track any imports later when in watch mode: + additionalFilePaths.push(filename) + + // We need to transform `url(...)` in imported CSS so the filepaths are properly + // relative to the entrypoint. Seems icky to have to hack this! C'est la vie... + contents = contents.replace(/url\(['"]?\.\/(.*?)['"]?\)/g, (_match, p1) => { + const relpath = path.relative(args.path, path.resolve(filedir, p1)).replace(/^\.\.\//, "") + return `url("${relpath}")` + }) + return contents + } + }) + + // Process the file through PostCSS + let outputCSS = "" + try { + const result = await postcss([importPlugin, ...options.plugins]).process(css, { + map: true, + ...options.options, + from: args.path, + }) + outputCSS = result.css + } catch(err) { + console.error(`\nerror: "${err.reason}" while processing CSS file:\n${err.file}:${err.line}:${err.column}\n`) + } + return { + contents: outputCSS, + loader: "css", + watchFiles: [args.path, ...additionalFilePaths], + } + }) + }, +}) + +// Plugin for Sass +const sassPlugin = (options) => ({ + name: "sass", + async setup(build) { + // Process .scss and .sass files with Sass + build.onLoad({ filter: /\.(sass|scss)$/ }, async (args) => { + if (!sass) { + console.error("error: Sass is not installed. Try running `npm i sass -D` and then building again.") + return + } + + const modulesFolder = pathToFileURL("node_modules/") + + const localOptions = { + importers: [{ + // An importer that redirects relative URLs starting with "~" to + // `node_modules`. + findFileUrl(url) { + if (!url.startsWith('~')) return null + return new URL(url.substring(1), modulesFolder) + } + }], + sourceMap: true, + ...options + } + const result = sass.compile(args.path, localOptions) + + const watchPaths = result.loadedUrls + .filter((x) => x.protocol === "file:" && !x.pathname.startsWith(modulesFolder.pathname)) + .map((x) => x.pathname) + + let cssOutput = result.css.toString() + + if (result.sourceMap) { + const basedir = process.cwd() + const sourceMap = result.sourceMap + + const promises = sourceMap.sources.map(async source => { + const sourceFile = await fs.readFile(fileURLToPath(source), "utf8") + return sourceFile + }) + sourceMap.sourcesContent = await Promise.all(promises) + + sourceMap.sources = sourceMap.sources.map(source => { + return path.relative(basedir, fileURLToPath(source)) + }) + + cssOutput += '\n' + generateSourceMappingURL(sourceMap) + } + + return { + contents: cssOutput, + loader: "css", + watchFiles: [args.path, ...watchPaths], + } + }) + }, +}) + +// Set up defaults and generate frontend bundling manifest file +const bridgetownPreset = (bridgetownConfig) => ({ + name: "bridgetownPreset", + async setup(build) { + // Ensure any imports anywhere starting with `/` are left verbatim + // so they can be used in-browser for actual `src` repo files + build.onResolve({ filter: /^\// }, args => { + return { path: args.path, external: true } + }) + + build.onStart(() => { + console.log("esbuild: frontend bundling started...") + }) + + // Generate the final output manifest + build.onEnd(async (result) => { + if (!result.metafile) { + console.warn("esbuild: build process error, cannot write manifest") + return + } + + const manifest = {} + const entrypoints = [] + + // Clean up entrypoint naming + const stripPrefix = (str) => str + .replace(/^frontend\//, "") + .replace(RegExp(String.raw`^${bridgetownConfig.source}\/${bridgetownConfig.islandsDir}\/`), "islands/") + + // For calculating the file size of bundle output + const fileSize = (path) => { + const { size } = fsLib.statSync(path) + const i = Math.floor(Math.log(size) / Math.log(1024)) + return (size / Math.pow(1024, i)).toFixed(2) * 1 + ['B', 'KB', 'MB', 'GB', 'TB'][i] + } + + const pathShortener = new RegExp(String.raw`^${bridgetownConfig.destination}\/_bridgetown\/static\/`, "g") + + // Let's loop through all the various outputs + for (const key in result.metafile.outputs) { + const value = result.metafile.outputs[key] + const inputs = Object.keys(value.inputs) + const outputPath = key.replace(pathShortener, "") + + if (value.entryPoint) { + // We have an entrypoint! + manifest[stripPrefix(value.entryPoint)] = outputPath + entrypoints.push([outputPath, fileSize(key)]) + } else if (key.match(/index(\.js)?\.[^-.]*\.css/) && inputs.find(item => item.match(/frontend.*\.(s?css|sass)$/))) { + // Special treatment for index.css + const input = inputs.find(item => item.match(/frontend.*\.(s?css|sass)$/)) + manifest[stripPrefix(input)] = outputPath + entrypoints.push([outputPath, fileSize(key)]) + } else if (inputs.length > 0) { + // Naive implementation, we'll just grab the first input and hope it's accurate + manifest[stripPrefix(inputs[0])] = outputPath + } + } + + const manifestFolder = path.join(process.cwd(), ".bridgetown-cache", "frontend-bundling") + await fs.mkdir(manifestFolder, { recursive: true }) + await fs.writeFile(path.join(manifestFolder, "manifest.json"), JSON.stringify(manifest)) + + console.log("esbuild: frontend bundling complete!") + console.log("esbuild: entrypoints processed:") + entrypoints.forEach(entrypoint => { + const [entrypointName, entrypointSize] = entrypoint + console.log(` - ${entrypointName}: ${entrypointSize}`) + }) + }) + } +}) + +const bridgetownConfigured = (bridgetownConfig, outputFolder) => { + bridgetownConfig = {...autogeneratedBridgetownConfig, ...bridgetownConfig} + if (outputFolder) bridgetownConfig.destination = outputFolder + + return bridgetownConfig +} + +// Load the PostCSS config from postcss.config.js or whatever else is a supported location/format +const postcssrc = require("postcss-load-config") + +module.exports = async (esbuildOptions, ...args) => { + let outputFolder; + if (typeof esbuildOptions === "string") { // legacy syntax where first argument is output folder + outputFolder = esbuildOptions + esbuildOptions = args[0] + } + const bridgetownConfig = bridgetownConfigured(esbuildOptions.bridgetownConfig, outputFolder) + + esbuildOptions.plugins = esbuildOptions.plugins || [] + // Add the PostCSS & glob plugins to the top of the plugin stack + const postCssConfig = await postcssrc() + esbuildOptions.plugins.unshift(importPostCssPlugin(postCssConfig, esbuildOptions.postCssPluginConfig || {})) + if (esbuildOptions.postCssPluginConfig) delete esbuildOptions.postCssPluginConfig + // Add the Glob plugin + esbuildOptions.plugins.unshift(importGlobPlugin(esbuildOptions.globOptions || {}, bridgetownConfig)) + if (esbuildOptions.globOptions) delete esbuildOptions.globOptions + // Add the Sass plugin + esbuildOptions.plugins.push(sassPlugin(esbuildOptions.sassOptions || {})) + if (esbuildOptions.sassOptions) delete esbuildOptions.sassOptions + // Add the Bridgetown preset + esbuildOptions.plugins.push(bridgetownPreset(bridgetownConfig)) + if (esbuildOptions.bridgetownConfig) delete esbuildOptions.bridgetownConfig + + const esbuild = require("esbuild") + const entryPoints = esbuildOptions.entryPoints || ["./frontend/javascript/index.js"] + if (esbuildOptions.entryPoints) delete esbuildOptions.entryPoints + + const islands = glob.sync(`./${bridgetownConfig.source}/${bridgetownConfig.islandsDir}/*.{js,js.rb}`).map(item => `./${item}`) + + esbuild.context({ + bundle: true, + loader: { + ".jpg": "file", + ".jpeg": "file", + ".png": "file", + ".gif": "file", + ".svg": "file", + ".avif": "file", + ".jxl": "file", + ".webp": "file", + ".woff": "file", + ".woff2": "file", + ".ttf": "file", + ".eot": "file", + }, + resolveExtensions: [".tsx", ".ts", ".jsx", ".js", ".css", ".scss", ".sass", ".json", ".js.rb"], + minify: process.argv.includes("--minify"), + sourcemap: true, + target: "es2020", + entryPoints: [...entryPoints, ...islands], + entryNames: "[dir]/[name].[hash]", + outdir: path.join(process.cwd(), `${bridgetownConfig.destination}/_bridgetown/static`), + publicPath: "/_bridgetown/static", + metafile: true, + ...esbuildOptions, + }).then(context => { + if (process.argv.includes("--watch")) { + // Enable watch mode + context.watch() + } else { + // Build once and exit if not in watch mode + context.rebuild().then(result => { + context.dispose() + }) + } + process.on('SIGINT', () => process.exit()) + }).catch(() => process.exit(1)) +} diff --git a/config/initializers.rb b/config/initializers.rb new file mode 100644 index 0000000..e346eab --- /dev/null +++ b/config/initializers.rb @@ -0,0 +1,101 @@ +# Welcome to Bridgetown! +# +# This configuration file is for settings which affect your whole site. +# +# For more documentation on using this initializers file, visit: +# https://www.bridgetownrb.com/docs/configuration/initializers/ +# +# A list of all available configuration options can be found here: +# https://www.bridgetownrb.com/docs/configuration/options +# +# For technical reasons, this file is *NOT* reloaded automatically when you use +# `bin/bridgetown start`. If you change this file, please restart the server process. +# +# For reloadable site metadata like title, SEO description, social media +# handles, etc., take a look at `src/_data/site_metadata.yml` + +Bridgetown.configure do |config| + # The base hostname & protocol for your site, e.g. https://example.com + url "" + + # Available options are `erb` (default), `serbea`, or `liquid` + template_engine "erb" + + # Other options you might want to investigate: + + # See list of timezone values here: + # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + # + # timezone "America/Los_Angeles" + + # Add collection pagination features to your site. Documentation here: + # https://www.bridgetownrb.com/docs/content/pagination + # + # pagination do + # enabled true + # end + + # Configure the permalink style for pages and posts. Custom collections can be + # configured separately under the `collections` key. Documentation here: + # https://www.bridgetownrb.com/docs/content/permalinks + # + # permalink "simple" + + # Optionally host your site off a path, e.g. /blog. If you set this option, + # ensure you use the `relative_url` helper for all links and assets in your HTML. + # If you're using esbuild for frontend assets, edit `esbuild.config.js` to + # update `publicPath`. + # + # base_path "/" + + # You can also modify options on this configuration object directly, like so: + # + # config.autoload_paths << "models" + + # If you find you're having trouble using the new Fast Refresh feature in development, + # you can disable it to force full rebuilds instead: + # + # fast_refresh false + + # You can use `init` to initialize various Bridgetown features or plugin gems. + # For example, you can use the Dotenv gem to load environment variables from + # `.env`. Just `bundle add dotenv` and then uncomment this: + # + # init :dotenv + # + + # Uncomment to use Bridgetown SSR (aka dynamic rendering of content via Roda): + # + # init :ssr + # + + # Uncomment to use file-based dynamic template routing via Roda (make sure you + # uncomment the gem dependency in your `Gemfile` as well): + # + # init :"bridgetown-routes" + # + + # We also recommend that if you're using Roda routes you include this plugin + # so you can get a generated routes list in `.routes.json`. You can then run + # `bin/bridgetown roda:routes` to print the routes. (This will require you to + # comment your route blocks. See example in `server/routes/hello.rb.sample`.) + # + # only :server do + # init :parse_routes + # end + # + + # You can configure the inflector used by Zeitwerk and models. A few acronyms are provided + # by default like HTML, CSS, and JS, so a file like `html_processor.rb` could be defined by + # `HTMLProcessor`. You can add more like so: + # + # config.inflector.configure do |inflections| + # inflections.acronym "W3C" + # end + # + # Bridgetown's inflector is based on Dry::Inflector so you can read up on how to add inflection + # rules here: https://dry-rb.org/gems/dry-inflector/1.0/#custom-inflection-rules + + # For more documentation on how to configure your site using this initializers file, + # visit: https://edge.bridgetownrb.com/docs/configuration/initializers/ +end diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 0000000..e93a86b --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,33 @@ +# Puma is a fast, concurrent web server for Ruby & Rack +# +# Learn more at: https://puma.io +# Bridgetown configuration documentation: +# https://edge.bridgetownrb.com/docs/configuration/puma + +# This port number can be overriden by a bind configuration option +# +port ENV.fetch("BRIDGETOWN_PORT") { 4000 } + +# You can adjust the number of workers (separate processes) and threads +# (per process) based on your production system +# +if ENV["BRIDGETOWN_ENV"] == "production" + workers ENV.fetch("BRIDGETOWN_CONCURRENCY") { 4 } +end + +max_threads_count = ENV.fetch("BRIDGETOWN_MAX_THREADS") { 5 } +min_threads_count = ENV.fetch("BRIDGETOWN_MIN_THREADS") { max_threads_count } +threads min_threads_count, max_threads_count + +pidfile ENV["PIDFILE"] || "tmp/pids/server.pid" + +# Preload the application for maximum performance +# +preload_app! + +# Use the Bridgetown logger format +# +require "bridgetown-core/rack/logger" +log_formatter do |msg| + Bridgetown::Rack::Logger.message_with_prefix msg +end diff --git a/content/defaults.js b/content/defaults.js deleted file mode 100644 index 5660a6e..0000000 --- a/content/defaults.js +++ /dev/null @@ -1,7 +0,0 @@ -export let fullName = "faucet-pipeline"; -export let shortName = "faucet"; -export let tagline = "The no-nonsense asset pipeline for humans"; -export let claims = { - default: `${fullName} – ${tagline.replace(/ /g, " ").toLowerCase()}`, - alt: `painless pre-processing of JavaScript, CSS and more` -}; diff --git a/esbuild.config.js b/esbuild.config.js new file mode 100644 index 0000000..842c855 --- /dev/null +++ b/esbuild.config.js @@ -0,0 +1,43 @@ +const build = require("./config/esbuild.defaults.js") + +// You can customize this as you wish, perhaps to add new esbuild plugins. +// +// ``` +// const path = require("path") +// const esbuildCopy = require('esbuild-plugin-copy').default +// const esbuildOptions = { +// plugins: [ +// esbuildCopy({ +// assets: { +// from: [path.resolve(__dirname, 'node_modules/somepackage/files/*')], +// to: [path.resolve(__dirname, 'output/_bridgetown/somepackage/files')], +// }, +// verbose: false +// }), +// ] +// } +// ``` +// +// You can also support custom base_path deployments via changing `publicPath`. +// +// ``` +// const esbuildOptions = { +// publicPath: "/my_subfolder/_bridgetown/static", +// ... +// } +// ``` + +/** + * @typedef { import("esbuild").BuildOptions } BuildOptions + * @type {BuildOptions} + */ +const esbuildOptions = { + plugins: [ + // add new plugins here... + ], + globOptions: { + excludeFilter: /\.(dsd|lit)\.css$/ + } +} + +build(esbuildOptions) diff --git a/faucet.config.js b/faucet.config.js deleted file mode 100644 index 46791d3..0000000 --- a/faucet.config.js +++ /dev/null @@ -1,44 +0,0 @@ -"use strict"; - -let site = "./dist/site"; -let titillium = "./node_modules/@openfonts/titillium-web_latin/files"; - -module.exports = { - watchDirs: ["./lib", "./views"], - manifest: { - target: "./dist/manifest.json", - key: "short", - webRoot: site, - baseURI: "./" - }, - sass: [{ - source: "./lib/styles/index.scss", - target: `${site}/bundle.css` - }], - js: [{ - source: "./views/index.jsx", - target: "./dist/views.js", - fingerprint: false, - format: "CommonJS", - jsx: { pragma: "createElement" } - }], - static: [{ - source: "./lib/images", - target: `${site}/img` - }, { - source: `${titillium}/titillium-web-latin-400.woff2`, - target: `${site}/fonts/titillium-web-regular.woff2` - }, { - source: `${titillium}/titillium-web-latin-700.woff2`, - target: `${site}/fonts/titillium-web-bold.woff2` - }, { - source: `${titillium}/titillium-web-latin-400-italic.woff2`, - target: `${site}/fonts/titillium-web-italic.woff2` - }, { - source: "./lib/app.js", - target: `${site}/app.js` - }, { - source: "prismjs/prism.js", - target: `${site}/prism.js` - }] -}; diff --git a/frontend/fonts/titillium-web-bold.woff2 b/frontend/fonts/titillium-web-bold.woff2 new file mode 100644 index 0000000..c34f134 Binary files /dev/null and b/frontend/fonts/titillium-web-bold.woff2 differ diff --git a/frontend/fonts/titillium-web-italic.woff2 b/frontend/fonts/titillium-web-italic.woff2 new file mode 100644 index 0000000..d2b9851 Binary files /dev/null and b/frontend/fonts/titillium-web-italic.woff2 differ diff --git a/frontend/fonts/titillium-web-regular.woff2 b/frontend/fonts/titillium-web-regular.woff2 new file mode 100644 index 0000000..82b27bc Binary files /dev/null and b/frontend/fonts/titillium-web-regular.woff2 differ diff --git a/frontend/javascript/index.js b/frontend/javascript/index.js new file mode 100644 index 0000000..0340e71 --- /dev/null +++ b/frontend/javascript/index.js @@ -0,0 +1,9 @@ +import "$styles/index.css" +import "$styles/syntax-highlighting.css" +import components from "$components/**/*.{js,jsx,js.rb,css}" + +// animated logo +let video = document.querySelector("video"); +if(video) { + video.addEventListener("click", video.play.bind(video)); +} diff --git a/frontend/styles/index.css b/frontend/styles/index.css new file mode 100644 index 0000000..498352f --- /dev/null +++ b/frontend/styles/index.css @@ -0,0 +1,147 @@ +:root { + --base-font-size: 100%; /* ~16px */ + --base-line-height: 1.75; + --tight-line-height: 1.2; + + --spacer-xxs: 0.25rem; + --spacer-xs: 0.5rem; + --spacer-s: 0.75rem; + --spacer-m: 1rem; + --spacer-l: 1.25rem; + --spacer-xl: 1.5rem; + + --base-border-radius: 5px; + + --base-block-margin: 0 0 var(--spacer-xs); + --base-heading-margin: var(--spacer-xl) 0 var(--spacer-xxs); + + --main-color: #37375F; + --link-color: #B7455F; + --link-color-hover: #37375F; + --text-color: #1f1f1f; + --text-color-bright: #444; + --text-color-brighter: #666; + --background-color: #FFF; + --highlight-background: #B7455FCC; + --highlight-border: 4px solid #37375FCC; + + --site-nav-order: 1; + --main-base-width: 320px; /* TODO: Figure out a good value here */ + --tagline-font-size: 1.2rem; + --wrapper-max-width: 100%; + --wrapper-margin: var(--spacer-xs); + + @media screen and (min-width: 64em) { + --base-font-size: 112.5%; /* ~18px (from a default of 16px) */ + } + + @media screen and (min-width: 760px) { + --tagline-font-size: 2rem; + --site-nav-order: -1; + } + + @media screen and (min-width: 820px) { + --wrapper-max-width: 90%; + --wrapper-margin: auto; + } + + @media screen and (min-width: 900px) { + --tagline-font-size: 3rem; + } +} + +@font-face { + font-family: "Titillium Web"; + font-weight: 400; + src: url("../fonts/titillium-web-regular.woff2") format("woff2"); + font-display: swap; +} + +@font-face { + font-family: "Titillium Web"; + font-weight: 400; + font-style: italic; + src: url("../fonts/titillium-web-italic.woff2") format("woff2"); + font-display: swap; +} + +@font-face { + font-family: "Titillium Web"; + font-weight: 700; + src: url("../fonts/titillium-web-bold.woff2") format("woff2"); + font-display: swap; +} + +html { + font-size: var(--base-font-size); + line-height: var(--base-line-height); +} + +body { + font-family: "Titillium Web", sans-serif; + color: var(--text-color); + margin: 0; +} + +h1, +h2 { + margin: var(--base-heading-margin); + line-height: var(--base-line-height); +} + +p, +blockquote, +ul { + margin: var(--base-block-margin); +} + +li { + margin-bottom: var(--spacer-xs); +} + +blockquote { + border-left: var(--highlight-border); + padding-left: 1rem; +} + +a { + color: var(--link-color); + transition: color ease-in-out 0.2s; +} + +a:hover, +a:focus { + color: var(--link-color-hover); +} + +video, +img { + max-width: 100%; + height: auto; +} + +header { + margin-bottom: var(--spacer-xl); +} + +.layout { + display: flex; + flex-wrap: wrap; + justify-content: center; + max-width: var(--wrapper-max-width); + margin: 0 var(--wrapper-margin) var(--spacer-xl); +} + +.layout > * { + max-width: var(--wrapper-max-width); +} + +.layout > nav { + flex: 0 1 content; + order: var(--site-nav-order); + padding-right: var(--spacer-m); +} + +.layout > main { + flex: 1 1 var(--main-base-width); +} diff --git a/frontend/styles/syntax-highlighting.css b/frontend/styles/syntax-highlighting.css new file mode 100644 index 0000000..085f7e9 --- /dev/null +++ b/frontend/styles/syntax-highlighting.css @@ -0,0 +1,79 @@ +/* + Syntax Highlighting for Code Snippets + https://www.bridgetownrb.com/docs/liquid/tags#stylesheets-for-syntax-highlighting + + Based on Twilight: + https://gist.github.com/dansimpson/803005 +*/ + +pre.highlight { + color: white; + background: hsl(0, 0%, 8%); + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + font-size: 1.3em; + text-align: left; + text-shadow: 0 -.1em .2em black; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + tab-size: 4; + hyphens: none; + + border-radius: var(--base-border-radius); + margin: var(--base-block-margin); + overflow: auto; + padding: 1em; +} + +pre.highlight .hll { background-color: #ffffcc } +pre.highlight .c { color: #5F5A60; font-style: italic } /* Comment */ +pre.highlight .err { border:#B22518; } /* Error */ +pre.highlight .k { color: #CDA869 } /* Keyword */ +pre.highlight .cm { color: #5F5A60; font-style: italic } /* Comment.Multiline */ +pre.highlight .cp { color: #5F5A60 } /* Comment.Preproc */ +pre.highlight .c1 { color: #5F5A60; font-style: italic } /* Comment.Single */ +pre.highlight .cs { color: #5F5A60; font-style: italic } /* Comment.Special */ +pre.highlight .gd { background: #420E09 } /* Generic.Deleted */ +pre.highlight .ge { font-style: italic } /* Generic.Emph */ +pre.highlight .gr { background: #B22518 } /* Generic.Error */ +pre.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +pre.highlight .gi { background: #253B22 } /* Generic.Inserted */ +pre.highlight .gp { font-weight: bold } /* Generic.Prompt */ +pre.highlight .gs { font-weight: bold } /* Generic.Strong */ +pre.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +pre.highlight .kd { color: #e9df8f; } /* Keyword.Declaration */ +pre.highlight .kp { color: #9B703F } /* Keyword.Pseudo */ +pre.highlight .na { color: #F9EE98 } /* Name.Attribute */ +pre.highlight .nb { color: #CDA869 } /* Name.Builtin */ +pre.highlight .nc { color: #9B859D; font-weight: bold } /* Name.Class */ +pre.highlight .no { color: #9B859D } /* Name.Constant */ +pre.highlight .nd { color: #7587A6 } /* Name.Decorator */ +pre.highlight .ni { color: #CF6A4C; font-weight: bold } /* Name.Entity */ +pre.highlight .nf { color: #9B703F; font-weight: bold } /* Name.Function */ +pre.highlight .nn { color: #9B859D; font-weight: bold } /* Name.Namespace */ +pre.highlight .nt { color: #CDA869; font-weight: bold } /* Name.Tag */ +pre.highlight .nv { color: #7587A6 } /* Name.Variable */ +pre.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +pre.highlight .w { color: #141414 } /* Text.Whitespace */ +pre.highlight .mf { color: #CF6A4C } /* Literal.Number.Float */ +pre.highlight .mh { color: #CF6A4C } /* Literal.Number.Hex */ +pre.highlight .mi { color: #CF6A4C } /* Literal.Number.Integer */ +pre.highlight .mo { color: #CF6A4C } /* Literal.Number.Oct */ +pre.highlight .sb { color: #8F9D6A } /* Literal.String.Backtick */ +pre.highlight .sc { color: #8F9D6A } /* Literal.String.Char */ +pre.highlight .sd { color: #8F9D6A; font-style: italic; } /* Literal.String.Doc */ +pre.highlight .s2 { color: #8F9D6A } /* Literal.String.Double */ +pre.highlight .se { color: #F9EE98; font-weight: bold; } /* Literal.String.Escape */ +pre.highlight .sh { color: #8F9D6A } /* Literal.String.Heredoc */ +pre.highlight .si { color: #DAEFA3; font-weight: bold; } /* Literal.String.Interpol */ +pre.highlight .sx { color: #8F9D6A } /* Literal.String.Other */ +pre.highlight .sr { color: #E9C062 } /* Literal.String.Regex */ +pre.highlight .s1 { color: #8F9D6A } /* Literal.String.Single */ +pre.highlight .ss { color: #CF6A4C } /* Literal.String.Symbol */ +pre.highlight .bp { color: #00aaaa } /* Name.Builtin.Pseudo */ +pre.highlight .vc { color: #7587A6 } /* Name.Variable.Class */ +pre.highlight .vg { color: #7587A6 } /* Name.Variable.Global */ +pre.highlight .vi { color: #7587A6 } /* Name.Variable.Instance */ +pre.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */ diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..b95c7c1 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "$styles/*": ["./frontend/styles/*"], + "$javascript/*": ["./frontend/javascript/*"], + "$components/*": ["./src/_components/*"] + } + }, +} diff --git a/justfile b/justfile new file mode 100644 index 0000000..eaa9bd1 --- /dev/null +++ b/justfile @@ -0,0 +1,12 @@ +start: + bundle exec bridgetown start + +deploy: build + rsync -uvcr --delete output/ $TARGET + +build: clean + bundle exec bridgetown frontend:build + bundle exec bridgetown build + +clean: + bundle exec bridgetown clean diff --git a/lib/app.js b/lib/app.js deleted file mode 100644 index effc93c..0000000 --- a/lib/app.js +++ /dev/null @@ -1,16 +0,0 @@ -(function() { -// code highlighting, adding Prism-specific class -// (necessary because Markdown only supports this for code blocks) -let nodes = document.querySelectorAll("p > code"); -Array.prototype.forEach.call(nodes, function(node) { - if(!node.hasAttributes()) { - node.className = "language-generic"; - } -}); - -// animated logo -let video = document.querySelector("video"); -if(video) { - video.addEventListener("click", video.play.bind(video)); -} -}()); diff --git a/lib/components/bar/_index.scss b/lib/components/bar/_index.scss deleted file mode 100644 index 56762d1..0000000 --- a/lib/components/bar/_index.scss +++ /dev/null @@ -1,13 +0,0 @@ -.bar { - display: flex; - align-items: center; - justify-content: space-between; - gap: var(--spacer-m); - padding: var(--spacer-m) var(--spacer-xl); - background-color: var(--main-color); -} - -.bar > :first-child, -.bar > :last-child { - flex-grow: 1; -} diff --git a/lib/components/bar/index.jsx b/lib/components/bar/index.jsx deleted file mode 100644 index aa8c723..0000000 --- a/lib/components/bar/index.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import { assetURI } from "../../../views/util"; -import { shortName } from "../../../content/defaults"; -import { Iconlist, Iconlink } from "../iconlist"; -import { createElement } from "complate-stream"; - -let logo = assetURI("faucet-logotype-monochrome.svg"); - -export function Bar({ TagName }) { - return - - - - - privacy - imprint - - - - - - - - - ; -} diff --git a/lib/components/code/_index.scss b/lib/components/code/_index.scss deleted file mode 100644 index a2d91ea..0000000 --- a/lib/components/code/_index.scss +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Based on the prism.js Twilight theme - * which is based (more or less) on the Twilight theme originally of Textmate fame. - * @author Remy Bach - */ -code[class*="language-"], -pre[class*="language-"] { - color: white; - background: none; - font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; - font-size: 1em; - text-align: left; - text-shadow: 0 -.1em .2em black; - white-space: pre; - word-spacing: normal; - word-break: normal; - word-wrap: normal; - line-height: 1.5; - tab-size: 4; - hyphens: none; -} - -pre[class*="language-"], -:not(pre) > code[class*="language-"] { - background: hsl(0, 0%, 8%); -} - -/* Code blocks */ -// removed border & box-shadow -pre[class*="language-"] { - border-radius: var(--base-border-radius); // adjusted for consistency - margin: var(--base-block-margin); // adjusted for consistency - overflow: auto; - padding: 1em; -} - -pre[class*="language-"]::-moz-selection { - /* Firefox */ - background: hsl(200, 4%, 16%); -} - -pre[class*="language-"]::selection { - /* Safari */ - background: hsl(200, 4%, 16%); -} - -/* Text Selection colour */ -pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, -code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { - text-shadow: none; - background: hsla(0, 0%, 93%, 0.15); -} - -pre[class*="language-"]::selection, pre[class*="language-"] ::selection, -code[class*="language-"]::selection, code[class*="language-"] ::selection { - text-shadow: none; - background: hsla(0, 0%, 93%, 0.15); -} - -/* Inline code */ -:not(pre) > code[class*="language-"] { - border-radius: .3em; - border: .13em solid hsl(0, 0%, 33%); - box-shadow: 1px 1px .3em -.1em black inset; - padding: .15em .2em .05em; - white-space: normal; -} - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: hsl(0deg 0% 65%); // adjusted for better contrast -} - -.token.punctuation { - opacity: .7; -} - -.token.namespace { - opacity: .7; -} - -.token.tag, -.token.boolean, -.token.number, -.token.deleted { - color: hsl(14, 58%, 55%); -} - -.token.keyword, -.token.property, -.token.selector, -.token.constant, -.token.symbol, -.token.builtin { - color: hsl(53, 89%, 79%); -} - -.token.attr-name, -.token.attr-value, -.token.string, -.token.char, -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string, -.token.variable, -.token.inserted { - color: hsl(76, 21%, 52%); -} - -.token.atrule { - color: hsl(218, 22%, 55%); -} - -.token.regex, -.token.important { - color: hsl(42, 75%, 65%); -} - -.token.important, -.token.bold { - font-weight: bold; -} -.token.italic { - font-style: italic; -} - -.token.entity { - cursor: help; -} - -pre[data-line] { - padding: 1em 0 1em 3em; - position: relative; -} - -/* Markup */ -.language-markup .token.tag, -.language-markup .token.attr-name, -.language-markup .token.punctuation { - color: hsl(33, 33%, 52%); -} - -/* Make the tokens sit above the line highlight so the colours don't look faded. */ -.token { - position: relative; - z-index: 1; -} diff --git a/lib/components/iconlist/_index.scss b/lib/components/iconlist/_index.scss deleted file mode 100644 index 56f5e72..0000000 --- a/lib/components/iconlist/_index.scss +++ /dev/null @@ -1,8 +0,0 @@ -.iconlist { - display: flex; - justify-content: flex-end; - - a { - margin-left: var(--spacer-xl); - } -} diff --git a/lib/components/iconlist/index.jsx b/lib/components/iconlist/index.jsx deleted file mode 100644 index 57b2243..0000000 --- a/lib/components/iconlist/index.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import { assetURI } from "../../../views/util"; -import { createElement } from "complate-stream"; - -export function Iconlist(props, ...icons) { - return ; -} - -export function Iconlink({ href, src, alt, width, height }) { - return - {alt} - ; -} diff --git a/lib/components/layout/_index.scss b/lib/components/layout/_index.scss deleted file mode 100644 index 0c93d4f..0000000 --- a/lib/components/layout/_index.scss +++ /dev/null @@ -1,25 +0,0 @@ -header { - margin-bottom: var(--spacer-xl); -} - -.layout { - display: flex; - flex-wrap: wrap; - justify-content: center; - max-width: var(--wrapper-max-width); - margin: 0 var(--wrapper-margin) var(--spacer-xl); - - & > * { - max-width: var(--wrapper-max-width); - } - - & > nav { - flex: 0 1 content; - order: var(--site-nav-order); - padding-right: var(--spacer-m); - } - - & > main { - flex: 1 1 var(--main-base-width); - } -} diff --git a/lib/components/layout/index.jsx b/lib/components/layout/index.jsx deleted file mode 100644 index 08ac40f..0000000 --- a/lib/components/layout/index.jsx +++ /dev/null @@ -1,87 +0,0 @@ -import { Teaser } from "../teaser"; -import { Navigation } from "../navigation"; -import { Bar } from "../bar"; -import { SkipLink } from "../skip"; -import { assetURI, repr } from "../../../views/util"; -import { createElement } from "complate-stream"; - -let layouts = new Set(["baroque", "tiny"]); - -let stylesheets = [ - assetURI("bundle.css") -]; -let scripts = [ - assetURI("prism.js"), - assetURI("app.js") -]; - -export default function DefaultLayout({ docTitle, claim, layout, slug }, ...children) { - if(!docTitle) { - throw new Error("missing document title"); - } - if(!layout) { - layout = "tiny"; - } - if(!layouts.has(layout)) { - throw new Error(`invalid page layout: ${repr(layout)}`); - } - - return - - - {docTitle} - - - - - - - - - {renderStyleSheets(stylesheets)} - - {renderScripts(scripts)} - - - - - - { layout === "tiny" ? : } - -
-
- {children} -
- - -
- - { layout === "baroque" ? : null } - - ; -} - -function renderScripts(items) { - return items.map(uri => { - return + + + <%= render Skip.new(href: "#main") %> + <% if resource_title == "About" %> + <%= render Teaser.new(tagline: site.metadata.tagline) %> + <% else %> + <%= render Bar.new() %> + <% end %> + +
+
<%= yield %>
+ <%= render Navigation.new(resource: resource) %> +
+ + <% if resource_title == "About" %> + <%= render Bar.new(tag: "footer") %> + <% end %> + + diff --git a/content/build-integration.md b/src/build-integration.md similarity index 98% rename from content/build-integration.md rename to src/build-integration.md index c0e2080..8f7647a 100644 --- a/content/build-integration.md +++ b/src/build-integration.md @@ -1,4 +1,7 @@ +--- +layout: default title: Build an Integration +--- This guide will help you if you want to use faucet-pipeline with your favorite Web framework or programming language and there is no integration written yet. diff --git a/content/build-pipeline.md b/src/build-pipeline.md similarity index 99% rename from content/build-pipeline.md rename to src/build-pipeline.md index 8c1eca0..e766a2b 100644 --- a/content/build-pipeline.md +++ b/src/build-pipeline.md @@ -1,4 +1,7 @@ +--- +layout: default title: Build a Pipeline +--- If you want to support other JS dialects or CSS preprocessors, you can contribute an additional pipeline to the project. We recommend that you read the diff --git a/content/cli.md b/src/cli.md similarity index 97% rename from content/cli.md rename to src/cli.md index a89e827..35d08b0 100644 --- a/content/cli.md +++ b/src/cli.md @@ -1,4 +1,7 @@ +--- +layout: default title: CLI +--- If you call the `faucet` command without any arguments, it will default to building your project according to the configuration in the file diff --git a/content/contributing.md b/src/contributing.md similarity index 98% rename from content/contributing.md rename to src/contributing.md index 42141e4..9baf5ea 100644 --- a/content/contributing.md +++ b/src/contributing.md @@ -1,4 +1,7 @@ +--- +layout: default title: Contributing in General +--- **Please note that this project that all contributions to this project must adhere to the [Contributor diff --git a/content/css.md b/src/css.md similarity index 76% rename from content/css.md rename to src/css.md index cb4d6ed..8462750 100644 --- a/content/css.md +++ b/src/css.md @@ -1,4 +1,7 @@ +--- +layout: default title: faucet-pipeline-css +--- faucet-pipeline-css offers bundling for files written in CSS. @@ -7,13 +10,10 @@ faucet-pipeline-css offers bundling for files written in CSS. To enable this **beta module** you need to add the following lines to your faucet.config.js: -``` -module.exports = { - // ... - plugins: [ - require("faucet-pipeline-css") - ] -} +```js +export const plugins = [ + require("faucet-pipeline-css") +]; ``` The configuration is an array of bundles you want to create. Each entry of the @@ -22,15 +22,13 @@ compiled, and `target` is the file that should be created (the path is, of course, modified a little when you use fingerprinting): ```js -module.exports = { - css: [{ - source: "./example.css", - target: "./output/example.css" - }, { - source: "./example2.css", - target: "./output/subfolder/example2.css" - }] -}; +export const css = [{ + source: "./example.css", + target: "./output/example.css" +}, { + source: "./example2.css", + target: "./output/subfolder/example2.css" +}]; ``` To support fingerprinting of images and fonts, use `faucet-pipeline-static` to @@ -58,13 +56,11 @@ If you don't want to prefix your CSS even though you have a Browserslist configuration, you can deactivate it per bundle: ```js -module.exports = { - css: [{ - source: "./example.scss", - target: "./output/example.css", - browserslist: false - }] -}; +export const css = [{ + source: "./example.scss", + target: "./output/example.css", + browserslist: false +}]; ``` If you use groups in your Browserslist, faucet-pipeline uses the `default` group @@ -72,13 +68,11 @@ by default. If you want to choose a different one, you can, for example, set it "legacy" like this: ```js -module.exports = { - css: [{ - source: "./example.scss", - target: "./output/example.css", - browserslist: "legacy" - }] -}; +export const css = [{ + source: "./example.scss", + target: "./output/example.css", + browserslist: "legacy" +}]; ``` ## Compacting diff --git a/content/faq.md b/src/faq.md similarity index 80% rename from content/faq.md rename to src/faq.md index 50772bb..fb34510 100644 --- a/content/faq.md +++ b/src/faq.md @@ -1,4 +1,7 @@ +--- +layout: default title: Troubleshooting / FAQ +--- Here we want to address some common questions. @@ -8,16 +11,14 @@ This typically happens when importing a module that has already been bundled or otherwise provides a distribution. The solution is to skip transpilation there: ```javascript -module.exports = { - js: [{ - source: "./index.js", - target: "./dist/bundle.js", - esnext: { - // ... - exclude: ["jquery"] - } - }] -} +export const js = [{ + source: "./index.js", + target: "./dist/bundle.js", + esnext: { + // ... + exclude: ["jquery"] + } +}]; ``` (This is necessary because faucet assumes we're consuming ES6 modules by diff --git a/content/images.md b/src/images.md similarity index 67% rename from content/images.md rename to src/images.md index 6f8c822..ecf6773 100644 --- a/content/images.md +++ b/src/images.md @@ -1,4 +1,7 @@ +--- +layout: default title: faucet-pipeline-images +--- faucet-pipeline-images offers image optimization and transformation. It supports JPG, PNG, SVG, WebP and AVIF. @@ -10,12 +13,10 @@ folder, and `target` is the target folder. The resulting configuration might look something like this: ```js -module.exports = { - images: [{ - source: "./images", - target: "./public/images" - }] -}; +export const images = [{ + source: "./images", + target: "./public/images" +}]; ``` This will copy the images in the supported formats by default. The files will @@ -33,13 +34,11 @@ i.e. those for which the function returns `true` – will be copied. In this example, we only optimize `.svg` files: ```js -module.exports = { - images: [{ - source: "./images", - target: "./public/images", - filter: file => file.endsWith(".svg") - }] -} +export const images = [{ + source: "./images", + target: "./public/images", + filter: file => file.endsWith(".svg") +}]; ``` ## Configuring the quality @@ -47,13 +46,11 @@ module.exports = { You can also provide a quality as a value between 1 and 100. ```js -module.exports = { - images: [{ - source: "./images", - target: "./public/images", - quality: 60 - }] -}; +export const images = [{ + source: "./images", + target: "./public/images", + quality: 60 +}]; ``` This will configure the quality of all lossy formats (all formats except PNG and @@ -64,13 +61,11 @@ SVG). The quality is set to a 50 (AVIF/WebP) or 80 (PNG/JPG) by default. You can output the image in one of the supported formats. ```js -module.exports = { - images: [{ - source: "./images", - target: "./public/images", - format: "webp" - }] -}; +export const images = [{ + source: "./images", + target: "./public/images", + format: "webp" +}]; ``` Note that SVGs can be converted to all other formats. But converting a vector @@ -81,13 +76,11 @@ image format to SVG will result in an error. You can add a suffix to the output name: ```js -module.exports = { - images: [{ - source: "./images", - target: "./public/images", - suffix: "-optimized" - }] -}; +export const images = [{ + source: "./images", + target: "./public/images", + suffix: "-optimized" +}]; ``` This will output a file named `foo.png` as `foo-optimized.png`. This is @@ -100,14 +93,12 @@ To scale the images, you can provide a scaling factor. To create a version half the size, with the suffix `-small` you can use the following configuration: ```js -module.exports = { - images: [{ - source: "./images", - target: "./public/images", - scale: 0.5, - suffix: "-small" - }] -}; +export const images = [{ + source: "./images", + target: "./public/images", + scale: 0.5, + suffix: "-small" +}]; ``` You can also provide a target width and/or height. By default, the pipeline @@ -117,15 +108,13 @@ create files with the suffix `-thumbnail` with a maximum width of 300 and a maximum height of 300, keeping the ratio. ```js -module.exports = { - images: [{ - source: "./images", - target: "./public/images", - width: 300, - height: 300, - suffix: "-thumbnail" - }] -}; +export const images = [{ + source: "./images", + target: "./public/images", + width: 300, + height: 300, + suffix: "-thumbnail" +}]; ``` You can also resize without keeping the ratio -- the resulting image will have @@ -133,16 +122,14 @@ the exact dimension you specify. The image will be cropped vertically or horizontally so that no empty space remains. ```js -module.exports = { - images: [{ - source: "./images", - target: "./public/images", - width: 300, - height: 300, - crop: true, - suffix: "-square" - }] -}; +export const images = [{ + source: "./images", + target: "./public/images", + width: 300, + height: 300, + crop: true, + suffix: "-square" +}]; ``` ## Autorotate @@ -151,11 +138,9 @@ You can configure the pipeline to rotate images automatically according to their EXIF data: ```js -module.exports = { - images: [{ - source: "./images", - target: "./public/images", - autorotate: true - }] -}; +export const images = [{ + source: "./images", + target: "./public/images", + autorotate: true +}]; ``` diff --git a/lib/images/faucet-logotype-monochrome.svg b/src/images/faucet-logotype-monochrome.svg similarity index 100% rename from lib/images/faucet-logotype-monochrome.svg rename to src/images/faucet-logotype-monochrome.svg diff --git a/lib/images/favicon.svg b/src/images/favicon.svg similarity index 100% rename from lib/images/favicon.svg rename to src/images/favicon.svg diff --git a/lib/images/github.svg b/src/images/github.svg similarity index 100% rename from lib/images/github.svg rename to src/images/github.svg diff --git a/lib/images/logo.png b/src/images/logo.png similarity index 100% rename from lib/images/logo.png rename to src/images/logo.png diff --git a/lib/images/logo.webm b/src/images/logo.webm similarity index 100% rename from lib/images/logo.webm rename to src/images/logo.webm diff --git a/lib/images/npm.svg b/src/images/npm.svg similarity index 100% rename from lib/images/npm.svg rename to src/images/npm.svg diff --git a/src/impressum.md b/src/impressum.md new file mode 100644 index 0000000..187de32 --- /dev/null +++ b/src/impressum.md @@ -0,0 +1,109 @@ +--- +layout: default +title: "Impressum" +--- + +~~~ +Lucas Dohmen +c/o COCENTER +Koppoldstr. 1 +86551 Aichach +~~~ + +## Kontakt + +E-Mail: lucas@dohmen.io + +## Haftungsausschluss + +### Haftung für Inhalte + +Die Inhalte unserer Seiten wurden mit größter Sorgfalt erstellt. +Für die Richtigkeit, Vollständigkeit und Aktualität der Inhalte +können wir jedoch keine Gewähr übernehmen. Als Diensteanbieter sind +wir gemäß § 7 Abs.1 DDG für eigene Inhalte auf diesen Seiten nach +den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 DDG sind +wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte +oder gespeicherte fremde Informationen zu überwachen oder nach +Umständen zu forschen, die auf eine rechtswidrige Tätigkeit +hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung +von Informationen nach den allgemeinen Gesetzen bleiben hiervon +unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem +Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. +Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir +diese Inhalte umgehend entfernen. + +### Haftung für Links + +Unser Angebot enthält Links zu externen Webseiten Dritter, auf +deren Inhalte wir keinen Einfluss haben. Deshalb können wir für +diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte +der verlinkten Seiten ist stets der jeweilige Anbieter oder +Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden +zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. +Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht +erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten +Seiten ist jedoch ohne konkrete Anhaltspunkte einer +Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von +Rechtsverletzungen werden wir derartige Links umgehend entfernen. + +### Urheberrecht + +Die durch die Seitenbetreiber erstellten Inhalte und Werke auf +diesen Seiten unterliegen dem deutschen Urheberrecht. Die +Vervielfältigung, Bearbeitung, Verbreitung und jede Art der +Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der +schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. +Downloads und Kopien dieser Seite sind nur für den privaten, nicht +kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser +Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte +Dritter beachtet. Insbesondere werden Inhalte Dritter als solche +gekennzeichnet. Sollten Sie trotzdem auf eine +Urheberrechtsverletzung aufmerksam werden, bitten wir um einen +entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen +werden wir derartige Inhalte umgehend entfernen. + +### Datenschutzhinweise + +**TL;DR: Wir nehmen Datensparsamkeit ernst und verarbeiten so wenig potenziell personenbezogene +Daten wie möglich. Der Webserver steht in Deutschland. Keine Cookies, kein sonstiges Tracking. +IP-Adressen werden gekürzt geloggt und nach 7 Tagen gelöscht. E-Mails werden je nach Zweck +unterschiedlich lange aufbewahrt.** + +Der Inhalt dieser Website ist allen Besuchern ohne jegliche Registrierung zugänglich. Damit du dir +die Seite ansehen kannst, wird deine IP-Adresse vom **Webserver** für die Dauer des Besuchs +verarbeitet. Dieser Webserver sowie der Mailserver werden von [Uberspace](https://uberspace.de) +bereitgestellt und befinden sich in Deutschland. Hierfür wurde ein Auftragsverarbeitungsvertrag nach +Art. 28 DSGVO geschlossen. + +Zusätzlich werden gekürzte IP-Adresse geloggt um **Aktivitäten** auf den einzelnen Seiten +nachvollziehen und **Fehler** ausfindig machen zu können (Access-Log und Error-Log). Um die +Privatsphäre der Besucher zu schützen, protokollieren wir nur die ersten 16 Bits einer IPv4-Adresse +bzw. die ersten 32 Bits einer IPv6-Adresse und löschen den Rest. Diese Logs werden nach 7 Tagen +gelöscht. + +Es werden natürlich auch keine Browser-Cookies oder andere Trackingtechnologien genutzt. + +**Rechtsgrundlage** für die Verarbeitung dieser Daten ist Art. 6 Abs. 1 lit. f) DSGVO. Das +berechtigte Interesse ist hier die Gewährleistung der Integrität, Vertraulichkeit und Verfügbarkeit +der Daten, die über diese Internetseiten verarbeitet werden. + +Wenn du uns eine E-Mail sendest, so erfolgt dies, soweit möglich, stets auf freiwilliger Basis. +Dabei werden diese Daten von uns gespeichert, allerdings ohne deine ausdrückliche Zustimmung nicht +an Dritte weitergegeben; insbesondere nicht für deren Werbezwecke. Mindestens jährlich wird durch +uns geprüft, ob eine weitere Speicherung erforderlich ist oder Aufbewahrungspflichten für die +E-Mails bestehen. Abhängig davon werden E-Mails weiter gespeichert oder gelöscht. + +Wir weisen darauf hin, dass die Datenübertragung im Internet (z. B. bei der Kommunikation per +E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch +Dritte ist nicht möglich. Der Nutzung von im Rahmen der Impressumspflicht veröffentlichten +Kontaktdaten durch Dritte zur Übersendung von nicht ausdrücklich angeforderter Werbung und +Informationsmaterialien wird hiermit ausdrücklich widersprochen. Die Betreiber dieser Website +behalten sich ausdrücklich rechtliche Schritte im Falle der unverlangten Zusendung von +Werbeinformationen, etwa durch Spam-Mails, vor. + +Falls du dein **Recht auf Auskunft, Berichtigung, Widerspruch der Verarbeitung oder Löschung von +personenbezogenen Daten** wahrnehmen willst, kontaktiere mich bitte. Auch das Beschwerderecht bei +einer Aufsichtsbehörde steht dir zu. + +Website Impressum basiert auf [impressum-generator.de](https://www.impressum-generator.de) von der [Kanzlei Hasselbach](https://www.kanzlei-hasselbach.de). diff --git a/content/index.md b/src/index.md similarity index 91% rename from content/index.md rename to src/index.md index 0394f2d..51ec950 100644 --- a/content/index.md +++ b/src/index.md @@ -1,4 +1,7 @@ -layout: baroque +--- +layout: default +title: About +--- **faucet-pipeline** takes care of **[pre-processing CSS](css)**, **[compiling modern JavaScript](js)** and framework-independent @@ -11,23 +14,29 @@ details. Creating a CSS bundle from [Sass](http://sass-lang.com) modules: ```javascript +export const sass = [{ source: "./styles/index.scss", target: "./dist/bundle.css" +}]; ``` Bundling and transpiling JavaScript: ```javascript +export const js = [{ source: "./src/index.js", target: "./dist/bundle.js", esnext: true // activates ES6 transpiler +}]; ``` Fingerprinting arbitrary files, like fonts and images: ```javascript +export const static = [{ source: "./assets", target: "./dist/assets" +}]; ``` @@ -45,12 +54,10 @@ Configuration resides in `faucet.config.js` – in this case, we want to bundle our JavaScript:: ```javascript -module.exports = { - js: [{ - source: "./src/index.js", - target: "./dist/bundle.js" - }] -}; +export const js = [{ + source: "./src/index.js", + target: "./dist/bundle.js" +}]; ``` Let's create two source files within the `src` directory, `index.js` and diff --git a/content/js.md b/src/js.md similarity index 70% rename from content/js.md rename to src/js.md index 589fbe5..731073d 100644 --- a/content/js.md +++ b/src/js.md @@ -1,4 +1,7 @@ +--- +layout: default title: faucet-pipeline-js +--- The configuration is an array of bundles you want to create. Each entry of the array is an object with at least two keys: `source` is the file that should @@ -13,13 +16,11 @@ bundle to output a different module format like ESM (your choices are: `iife`, `esm`, `umd`, `amd`, and `commonjs`): ```js -module.exports = { - js: [{ - source: "./index.js", - target: "./dist/bundle.js", - format: "esm" - }] -}; +export const js = [{ + source: "./index.js", + target: "./dist/bundle.js", + format: "esm" +}]; ``` If you chose a module format that does not support importing/exporting natively @@ -32,15 +33,13 @@ variable - you can declare that library to be "external": faucet: ```js -module.exports = { - js: [{ - source: "./index.js", - target: "./dist/bundle.js", - externals: { - jquery: "jQuery" - } - }] -}; +export const js = [{ + source: "./index.js", + target: "./dist/bundle.js", + externals: { + jquery: "jQuery" + } +}]; ``` With this configuration, importing `from "jquery"` will be rewritten to @@ -67,17 +66,15 @@ faucet-js offers three options to reduce a bundle's file size: More extreme reductions can be activated via the bundle's `compact` setting: ```js -module.exports = { - js: [{ - source: "./index.js", - target: "./dist/bundle.min.js", - compact: "minify" - }, { - source: "./index.js", - target: "./dist/bundle.mangled.js", - compact: "mangle" - }] -}; +export const js = [{ + source: "./index.js", + target: "./dist/bundle.min.js", + compact: "minify" +}, { + source: "./index.js", + target: "./dist/bundle.mangled.js", + compact: "mangle" +}]; ``` `minify` will additionally remove all non-significant whitespace, `mangle` @@ -96,27 +93,23 @@ file](https://github.com/ai/browserslist/) to specify which browsers you want to support. This is an example configuration: ```js -module.exports = { - js: [{ - source: "./index.js", - target: "./dist/bundle.js", - esnext: true - }] -}; +export const js = [{ + source: "./index.js", + target: "./dist/bundle.js", + esnext: true +}]; ``` You can also deactivate the automatic browserslist detection: ```js -module.exports = { - js: [{ - source: "./index.js", - target: "./dist/bundle.js", - esnext: { - browserslist: false - } - }] -}; +export const js = [{ + source: "./index.js", + target: "./dist/bundle.js", + esnext: { + browserslist: false + } +}]; ``` If your browserslist is configured for multiple @@ -124,36 +117,32 @@ If your browserslist is configured for multiple you can choose which one to use for each bundle: ```js -module.exports = { - js: [{ - source: "./index.js", - target: "./dist/bundle.js", - esnext: { - browserslist: "default" - } - }, { - source: "./index.js", - target: "./dist/legacy.js", - esnext: { - browserslist: "legacy" - } - }] -}; +export const js = [{ + source: "./index.js", + target: "./dist/bundle.js", + esnext: { + browserslist: "default" + } +}, { + source: "./index.js", + target: "./dist/legacy.js", + esnext: { + browserslist: "legacy" + } +}]; ``` You can also exclude modules of the bundle you don't want to transpile with `exclude`. This is useful for dependencies that are already transpiled: ```js -module.exports = { - js: [{ - source: "./index.js", - target: "./dist/bundle.js", - esnext: { - exclude: ["jquery"] - } - }] -}; +export const js = [{ + source: "./index.js", + target: "./dist/bundle.js", + esnext: { + exclude: ["jquery"] + } +}]; ``` @@ -164,13 +153,11 @@ You also need to set `typescript` to true for the bundles that should be compiled with TypeScript: ```js -module.exports = { - js: [{ - source: "./src/index.ts", - target: "./dist/bundle.js", - typescript: true - }] -}; +export const js = [{ + source: "./src/index.ts", + target: "./dist/bundle.js", + typescript: true +}]; ``` Everything described above will still work in the same way (all configuration @@ -183,13 +170,11 @@ To use JSX, you need to install the `faucet-pipeline-jsx` package. You also need to set `jsx` to true for the bundles that should be compiled with JSX: ```js -module.exports = { - js: [{ - source: "./src/index.ts", - target: "./dist/bundle.js", - jsx: true - }] -}; +export const js = [{ + source: "./src/index.ts", + target: "./dist/bundle.js", + jsx: true +}]; ``` Everything described above will still work in the same way (all configuration diff --git a/content/manifest.md b/src/manifest.md similarity index 92% rename from content/manifest.md rename to src/manifest.md index 4d78b85..abb8087 100644 --- a/content/manifest.md +++ b/src/manifest.md @@ -1,5 +1,7 @@ +--- +layout: default title: Fingerprinting & Manifest - +--- `faucet-pipeline` can fingerprint the generated files for you: It adds a hash of the file content to the file name. You can cache files with a fingerprint @@ -34,12 +36,10 @@ The manifest generation is activated when you put the `manifest` key in your configuration with an object at least containing a `file` option with a path to where you want your manifest to go. -``` -module.exports = { - manifest: { - target: "./path/to/manifest.json" - } -} +```javascript +export const manifest = { + target: "./path/to/manifest.json" +}; ``` By default, the generated manifest will have... @@ -61,15 +61,13 @@ value relative to a different folder (in some frameworks, that would be Example: -``` -module.exports = { - manifest: { - target: "./path/to/manifest.json", - key: "short", - baseURI: "/assets/", - webRoot: "./target" - } -} +```javascript +export const manifest = { + target: "./path/to/manifest.json", + key: "short", + baseURI: "/assets/", + webRoot: "./target" +}; ``` ## Advanced Configuration diff --git a/content/philosophy.md b/src/philosophy.md similarity index 90% rename from content/philosophy.md rename to src/philosophy.md index 85230a1..ea2258e 100644 --- a/content/philosophy.md +++ b/src/philosophy.md @@ -1,4 +1,7 @@ +--- +layout: default title: Motivation & Philosophy +--- > Given the choice between making something _my_ problem, and making something > _the user's_ problem, I'll choose to make it my problem every time. @@ -46,6 +49,7 @@ actually writing the code. Thus we can easily recommend it to friends and colleagues and get them started in less than a minute. Of course, faucet wouldn’t be possible without relying on fantastic work by many -people; we merely provide a bit of glue code on top. The work on this project is -sponsored by [INNOQ](https://www.innoq.com) & [fejo.dk](https://www.fejo.dk). It -is used both in production and internal applications by both companies. +people; we merely provide a bit of glue code on top. Part of the work on this +project was sponsored by [INNOQ](https://www.innoq.com) and +[fejo.dk](https://www.fejo.dk). It is used both in production and internal +applications by both companies. diff --git a/content/rails.md b/src/rails.md similarity index 88% rename from content/rails.md rename to src/rails.md index 553529a..a4feb15 100644 --- a/content/rails.md +++ b/src/rails.md @@ -1,4 +1,7 @@ +--- +layout: default title: Rails +--- If you want to use faucet-pipeline with Rails, you can use the `faucet_pipeline_rails` gem. It is [documented diff --git a/content/sass.md b/src/sass.md similarity index 78% rename from content/sass.md rename to src/sass.md index 6d4c93c..7152b22 100644 --- a/content/sass.md +++ b/src/sass.md @@ -1,4 +1,7 @@ +--- +layout: default title: faucet-pipeline-sass +--- faucet-pipeline-sass offers bundling for files written in SCSS. @@ -8,15 +11,13 @@ compiled, and `target` is the file that should be created (the path is, of course, modified a little when you use fingerprinting): ```js -module.exports = { - sass: [{ - source: "./example.scss", - target: "./output/example.css" - }, { - source: "./example2.scss", - target: "./output/subfolder/example2.css" - }] -}; +export const sass = [{ + source: "./example.scss", + target: "./output/example.css" +}, { + source: "./example2.scss", + target: "./output/subfolder/example2.css" +}]; ``` To support fingerprinting of images and fonts, use `faucet-pipeline-static` to @@ -44,13 +45,11 @@ If you don't want to prefix your CSS even though you have a Browserslist configuration, you can deactivate it per bundle: ```js -module.exports = { - sass: [{ - source: "./example.scss", - target: "./output/example.css", - browserslist: false - }] -}; +export const sass = [{ + source: "./example.scss", + target: "./output/example.css", + browserslist: false +}]; ``` If you use groups in your Browserslist, faucet-pipeline uses the `default` group @@ -58,13 +57,11 @@ by default. If you want to choose a different one, you can, for example, set it "legacy" like this: ```js -module.exports = { - sass: [{ - source: "./example.scss", - target: "./output/example.css", - browserslist: "legacy" - }] -}; +export const sass = [{ + source: "./example.scss", + target: "./output/example.css", + browserslist: "legacy" +}]; ``` ## Compacting diff --git a/content/spring-boot.md b/src/spring-boot.md similarity index 88% rename from content/spring-boot.md rename to src/spring-boot.md index 7208900..5a52046 100644 --- a/content/spring-boot.md +++ b/src/spring-boot.md @@ -1,4 +1,7 @@ +--- +layout: default title: Spring Boot +--- If you want to use faucet-pipeline with Spring Boot, you can use [this Spring Boot diff --git a/content/static.md b/src/static.md similarity index 71% rename from content/static.md rename to src/static.md index ae0924d..7530166 100644 --- a/content/static.md +++ b/src/static.md @@ -1,4 +1,7 @@ +--- +layout: default title: faucet-pipeline-static +--- The configuration is an array of folders or single files you want to copy. Each entry of the array is an object with two keys: `source` is the source folder, @@ -7,15 +10,13 @@ and `target` is the target folder. The resulting configuration might look something like this: ```js -module.exports = { - static: [{ - source: "./images", - target: "./public/images" - }, { - source: "./fonts", - target: "./public/fonts" - }] -}; +export const static = [{ + source: "./images", + target: "./public/images" +}, { + source: "./fonts", + target: "./public/fonts" +}]; ``` If you only want to copy _some_ of the files, you can select them using a @@ -27,17 +28,15 @@ In this example, we only copy `.ttf` fonts and omit images from the `templates` directory: ```js -module.exports = { - static: [{ - source: "./fonts", - target: "./public/fonts", - filter: file => file.endsWith(".ttf") - }, { - source: "./images", - target: "./public/images", - filter: file => !file.startsWith("templates/") - }] -} +export const static = [{ + source: "./fonts", + target: "./public/fonts", + filter: file => file.endsWith(".ttf") +}, { + source: "./images", + target: "./public/images", + filter: file => !file.startsWith("templates/") +}]; ``` ## Compact @@ -58,13 +57,11 @@ If you prefer to compact your images on your own, you could for example use JPGs: ```js -module.exports = { - static: [{ - source: "./src", - target: "./dist", - compact: { - jpg: require("imagemin-mozjpeg")({ quality: 80 }) - } - }] -}; +export const static = [{ + source: "./src", + target: "./dist", + compact: { + jpg: require("imagemin-mozjpeg")({ quality: 80 }) + } +}]; ``` diff --git a/content/watching.md b/src/watching.md similarity index 83% rename from content/watching.md rename to src/watching.md index 22f0e65..83feab9 100644 --- a/content/watching.md +++ b/src/watching.md @@ -1,4 +1,7 @@ +--- +layout: default title: File Watching +--- You don’t need to configure anything for file watching; you enable it with the `--watch` CLI option. However, if you want to be gentle with your file watching @@ -8,9 +11,5 @@ config file. The configuration expects an array of strings. The strings are paths relative to your configuration file. It might look like this: ```js -module.exports = { - // configuration of your pipelines... - - watchDirs: ["./src", "./lib"] -} +export const watchDirs = ["./src", "./lib"]; ``` diff --git a/views/index.jsx b/views/index.jsx deleted file mode 100644 index a7e9307..0000000 --- a/views/index.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import DefaultLayout from "../lib/components/layout"; -import { fullName, claims } from "../content/defaults"; -import Renderer, { createElement, safe } from "complate-stream"; - -let { registerView, renderView } = new Renderer(); - -registerView(render); - -export default renderView; - -function render({ slug, meta, html }) { - let { title, layout } = meta; - - let docTitle = title ? `${title} | ${fullName}` : claims.default; - let claim = docTitle === claims.default ? claims.alt : claims.default; - - return - {safe(html)} - ; -} diff --git a/views/util.js b/views/util.js deleted file mode 100644 index c285b19..0000000 --- a/views/util.js +++ /dev/null @@ -1,13 +0,0 @@ -let manifest = require("./manifest.json"); // NB: relative to bundle - -export function assetURI(filepath) { - let res = manifest[filepath]; - if(!res) { - throw new Error(`unknown asset: ${repr(filepath)}`); - } - return res; -} - -export function repr(value) { - return `\`${JSON.stringify(value)}\``; -}