diff --git a/README.md b/README.md index d664b245..a17d36c8 100644 --- a/README.md +++ b/README.md @@ -1,169 +1,92 @@ # Orejime 🍪 > Let your users choose the cookies they eat on your website. -> Orejime 🍪 is an easy to use consent manager that focuses on accessibility. -## Introduction +Orejime is a lightweight consent manager that focuses on accessibility. -Orejime 🍪 is an open-source JavaScript library you can use on your website to let users choose what third-party cookies they allow. It's specifically made to comply with the GDPR. - -Orejime 🍪 is a fork of [Klaro!](https://github.com/KIProtect/klaro) that focuses on **accessibility**. It follows Web Content Accessibility Guidelines (WCAG) via the French RGAA. +[Explore its features](http://orejime.boscop.fr) ## Getting started -Using Orejime 🍪 requires a few steps: - 1. [Installation](#installation) -1. [Third-party script tags change](#third-party-script-tags-change) 1. [Configuration](#configuration) +1. [Third-party scripts configuration](#third-party-scripts-configuration) 1. [Initialization](#initialization) ### Installation +Orejime comes with many styles and languages. +It is distributed as individual modules that follow a common convention, namely `orejime-[THEME]-[LANGUAGE]`. +For example: +* `orejime-standard-en.js` uses the standard theme with english texts +* `orejime-standard-fr.js` uses the standard theme with french texts +* `orejime-dsfr-fr.js` uses the DSFR theme with french texts + +(Learn more about [themes](#theming) & [languages](#internationalization)) + #### Via CDN -The easiest way to use the lib is to include the built files directly in the browser. +The easiest way to use Orejime is to import a distribution via a content delivery network such as unpkg: ```html - - + + ``` -If you're using this method, please avoid using the `@latest` version. Prefer a fixed one like `https://unpkg.com/orejime@2.0.1/...`. -That way you can ensure you will not be impacted by a change of API or a potential bug that could land in the latest version. +> [!TIP] +> If you're using this method, please avoid using the `@latest` version. Prefer a fixed one like `https://unpkg.com/orejime@3.0.0/...`. +> That way you can ensure you will not be impacted by a change of API or a potential bug that could land in the latest version. #### Via npm Orejime only distributes built files via npm ([learn why](./adr/001-distribution-formats.md)). -``` +```sh npm install orejime ``` -You'll find the required JS and CSS files in the `dist` folder (namely `orejime.js` & `orejime.css`). +You'll find the required JS and CSS files in the `dist` folder. -#### Old browser support - -For IE11, you'll need to have ES6 polyfills loaded on your page. One easy and efficient way to add such polyfills is to use [polyfill.io](https://polyfill.io/v2/docs/). - -### Third-party script tags change - -For each third-party script you want Orejime to manage, you must modify its ` ``` -For external scripts or img tags (for tracking pixels), do the same, and rename the `src` attribute to `data-src`: +You'll find all the available configuration options below. -```diff -- -+ -``` - -### Configuration - -You need to pass Orejime 🍪 a configuration object with, at the very least, `purposes` and `privacyPolicyUrl` properties. Each purpose listed in `purposes` must itself have at least `id`, `title` and `cookies`. +> [!NOTE] +> Very few of the following options are actually required (only `purposes` and `privacyPolicyUrl` are). +> Optional options are explicitly flagged as such.
- Here is a fully-detailed annotated example of a configuration object: -  + +Annotated example of configuration ```js var orejimeConfig = { - // Optional. You can customize the element that will contain Orejime (either - // a selector or a DOM element). - // It no element matches, an element will be created and inserted at the - // beginning of the . - orejimeElement: "#orejime", - - // Optional. - cookie: { - // Optional. You can customize the name of the cookie that Orejime uses for storing - // user consent decisions. - // defaults to "orejime". - name: "orejime", - - // Optional. You can set a custom expiration time for the Orejime cookie, in days. - // defaults to 365. - duration: 365, - - // Optional. You can provide a custom domain for the Orejime cookie, for example to make it available on every associated subdomains. - domain: 'mydomain.com', - - // Optional. You can provide a custom function to serialize the cookie contents. - stringify: (contents) => JSON.stringify(contents), - - // Optional. You can provide a custom function to unserialize the cookie contents. - parse: (cookie) => JSON.parse(cookie), - }, - - // You must provide a link to your privacy policy page + // You must provide a link to your privacy policy page for GDPR compliance. privacyPolicyUrl: "", - // Optional. If `forceModal` is set to true, Orejime will directly display - // the consent modal and not allow the user to close it before having actively - // consented or declined the use of third-party purposes. - // defaults to false - forceModal: false, - - // Optional. If `forceBanner` is set to true, Orejime will display the consent - // notice and not allow the user to close it before having actively consented - // or declined the use of third-party purposes. - // Has no effect if `forceModal` is set to true. - // defaults to false - forceBanner: false, - - // Optional. You can define the UI language directly here. If undefined, Orejime will - // use the value given in the global "lang" variable, or fallback to the value - // in the lang attribute, or fallback to "en". - lang: "en", - - // Optional. You can pass an image url to show in the notice. - // If the image is not exclusively decorative, you can pass an object - // with the image `src` and `alt` attributes: `logo: {src: '...', alt: '...'}` - logo: '/img/logo.png', - - // Optional. The theme used to render the UI (See the "theming" section below). - // If unset, this will default to "orejime", the classic built-in UI. - theme: 'orejime', - - // You can overwrite existing translations and add translations for your - // purpose descriptions and purposes. See `src/translations` for a full - // list of translations that can be overwritten - translations: { - modal: { - description: "This is an example of how to override an existing translation already used by Orejime", - } - }, - // The list of third-party purposes that Orejime will manage for you. // The purposes will appear in the modal in the same order as defined here. purposes: [ { // The id of the purpose, used internally by Orejime. - // Each id should match the `data-purpose` attribute of a +``` + +> [!WARNING] +> The `data-purpose` attribute must match the id of a purpose in the configuration. +> Orejime uses this id to find a purpose's associated scripts. +> If those don't match, Orejime won't be able to load the scripts. + +On external scripts or `img` tags (i.e. tracking pixels), follow the same steps and rename the `src` attribute to `data-src`: + +```diff +- +``` -Now that you included the JS, the CSS, configured existing third-party scripts and defined your configuration, you can initialize an instance. This can be done automatically or manually. +### Initialization -#### Automatically +Now that you installed and configured Orejime, you should see it greet you! -When including the script, the lib checks if the `window.orejimeConfig` variable exists. If it does, a new Orejime instance is created in `window.orejime`. +Anytime the `window.orejimeConfig` variable is set with a valid configuration, Orejime will pick it up and start. -#### Manually +In case you don't set this variable, Orejime can still be launched programatically by passing it a configuration: ```js -// if using Orejime in a module context: -// var Orejime = require('orejime'); - Orejime.init(orejimeConfig); ``` -#### As a module - -Previously, Orejime could be imported as any other module and bundled into application code. -With version 3, we're abandonning this functionality to provide a standalone build only ([learn why](./adr/001-distribution-formats.md)). +> [!NOTE] +> Previously, Orejime could be imported as any other module and bundled into application code. +> With version 3, we're abandonning this functionality to provide standalone builds only ([learn why](./adr/001-distribution-formats.md)). ### Theming -Orejime support multiple themes to accomodate for every situation. - -#### Default theme +#### Standard theme -This theme is loaded by default. It is meant to be simple but elegant enough to be used as-is on any website. It is easily customizable by tweaking some CSS properties. +This is a custom theme meant to be simple but elegant enough to be used as-is on any website. +It is easily customizable by tweaking some CSS properties. -Of course, you can either replace the original CSS entirely, or add your custom stylesheet to overwrite only some of the rules. - -```css -/* custom-style.css */ -.orejime-Env { - --orejime-font-family: monospace; - --orejime-background: black; - --orejime-color: yellow; -} -``` +You can either replace the original CSS entirely, or add your custom stylesheet to overwrite only some of the rules. ```html - + + ``` +You'll find the available CSS properties in [the theme's stylesheet](src/ui/themes/standard/index.css). + #### DSFR theme This theme is meant to be used on websites using the official design system of the french government. As those sites already include the DSFR styles, this theme does not provide any styles of its own but only makes use of the correct markup and class names. See the [consent manager component](https://www.systeme-de-design.gouv.fr/composants-et-modeles/composants/gestionnaire-de-consentement) on the DSFR docs for an overview. +### Internationalization + +Orejime is available in most european languages: +Catalan, Dutch, English, Estonian, Finnish, French, German, Hungarian, Italian, Norwegian, Occitan, Romanian, Spanish, Swedish. + +> [!NOTE] +> Each and every translated text is overridable via [the configuration](#configuration). + ## API -* `Orejime.init(config)`: creates a new Orejime instance with the given config object -* `Orejime.defaultConfig`: object containing all the default properties of an instance +Functions and references are made available on the global scope: + +* `loadOrejime(config)`: creates a new Orejime instance with the given config object ### Orejime instance -* `prompt()`: opens the consent modal -* `manager`: the Manager instance used. See `src/core/Manager.ts` -* `config`: the complete config object used +* `orejime.prompt()`: opens the consent modal +* `orejime.manager`: the core consent manager (see `src/core/Manager.ts`) +* `orejime.config`: the complete config object used ## Migrating @@ -335,18 +359,18 @@ See the [consent manager component](https://www.systeme-de-design.gouv.fr/compos A major overhaul of the configuration took place in this version, as to clarify naming and align more with the GDPR vocabulary. -If you were already using version 2, a tool to migrate your current configuration is available here : https://orejime.boscop.fr/migration. +If you were already using version 2, a tool to migrate your current configuration is available here : https://orejime.boscop.fr/#migration. ## Development -If you want to contribute to Orejime, or make a special build for yourself, clone the project then: +If you want to contribute to Orejime, or make a custom build for yourself, clone the project and run these commands: ``` npm install npm start ``` -You can then open the demo page on `http://localhost:3000` - it will be reloaded automatically when the JS or CSS changes. +You can then open the demo page at `http://localhost:3000`, which will be reloaded automatically whenever the JS or CSS changes. ## License & credits @@ -354,8 +378,10 @@ This project is licensed under a BSD-3 license. Orejime started as a fork of [Klaro!](https://github.com/KIProtect/klaro). A lot of stuff changed since. A few were integrated in the original project, but eventually some big bricks changed and it became difficult, or sometimes not even necessary, to push those changes in. -Orejime is maintained by [Boscop (French)](http://boscop.fr). +Orejime is maintained by [Boscop (French)](http://boscop.fr). ### What does "Orejime" mean? -"Orejime" is a play-on-word. You can pronounce it like "Au régime" in French, which means "on a diet". 🍪 +"Orejime" is a play-on-word. You can pronounce it like "Au régime" in French, which means "on a diet". + +🍪🍪🍪 diff --git a/adr/002-standalone-bundles.md b/adr/002-standalone-bundles.md new file mode 100644 index 00000000..dba13cbc --- /dev/null +++ b/adr/002-standalone-bundles.md @@ -0,0 +1,24 @@ +--- +date: +status: +--- + +# Standalone bundles + +## Context + +As of now, Orejime is split into many chunks to isolate the core from the language and UI. +However, it is often used on websites using a single language, and always a single theme. + +## Considerations + +* Async loading relies on bundler magic to locate chunks. +* A bundle containing the core, lang and UI is more optimized than when split and loaded asynchronously, because resources are mutualized and compression acts on the whole bundle at once. Also, this save the time needed to import the chunks. +* Loading different versions of a bundle requires no more work than setting options in the config. In most cases, this will actually be easier. +* The split was meant to reduce network and preocessing usage by loading the bare minimum code. However, Orejime would pop anytime a user visits a website for the first time, and the UI would thus be loaded and cached. We might as well load and cache the whole bundle at once. +* Generating a bundle for each combination of themes and languages could lead to bloat, but we shouldn't add lots of themes. Anyways, even a large list of bundles wouldn't really be a problem, as long as each one is optimized. + +## Decision + +Orejime will now be distributed as many standalone packages, each providing a single theme and language. +For example, `orejime-dsfr-en` would provide orejime with the DSFR theme and the english translations. diff --git a/e2e/OrejimePage.ts b/e2e/OrejimePage.ts index bdc8a7b2..a6137686 100644 --- a/e2e/OrejimePage.ts +++ b/e2e/OrejimePage.ts @@ -17,14 +17,14 @@ export class OrejimePage { Orejime - + - + ` diff --git a/package-lock.json b/package-lock.json index f96db950..43796105 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,8 +31,6 @@ "preact": "^10.23.2", "prettier": "^2.2.1", "prettier-loader": "^3.3.0", - "sass": "^1.51.0", - "sass-loader": "^12.6.0", "sharp": "^0.33.5", "shiki": "^2.2.0", "shx": "^0.3.4", @@ -10088,16 +10086,6 @@ "node": ">=6" } }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/launch-editor": { "version": "2.9.1", "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", @@ -10571,7 +10559,8 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/nice-try": { "version": "1.0.5", @@ -13938,220 +13927,6 @@ "dev": true, "license": "MIT" }, - "node_modules/sass": { - "version": "1.61.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.61.0.tgz", - "integrity": "sha512-PDsN7BrVkNZK2+dj/dpKQAWZavbAQ87IXqVvw2+oEYI+GwlTWkvbQtL7F2cCNbMqJEYKPh1EcjSxsnqIb/kyaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/sass-loader": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", - "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", - "dev": true, - "license": "MIT", - "dependencies": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - } - } - }, - "node_modules/sass/node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/sass/node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/sass/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sass/node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/sass/node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sass/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/sass/node_modules/immutable": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", - "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", - "dev": true, - "license": "MIT" - }, - "node_modules/sass/node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/sass/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/sass/node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sass/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/sass/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", @@ -14585,16 +14360,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", diff --git a/package.json b/package.json index 67e03b5d..fd226533 100644 --- a/package.json +++ b/package.json @@ -69,8 +69,6 @@ "preact": "^10.23.2", "prettier": "^2.2.1", "prettier-loader": "^3.3.0", - "sass": "^1.51.0", - "sass-loader": "^12.6.0", "sharp": "^0.33.5", "shiki": "^2.2.0", "shx": "^0.3.4", diff --git a/rspack.config.js b/rspack.config.js index 9f877afe..bbc41672 100644 --- a/rspack.config.js +++ b/rspack.config.js @@ -2,9 +2,8 @@ const fs = require('fs'); const path = require('path'); const {rspack} = require('@rspack/core'); const sharp = require('sharp'); -const pkg = require('./package.json'); const services = require('./site/services.json'); -const theme = require('./site/themes/boscop-light-soft-color-theme.json'); +const codeTheme = require('./site/themes/boscop-light-soft-color-theme.json'); const fullPath = path.resolve.bind(path, __dirname); const isDev = process.env.NODE_ENV === 'development'; @@ -20,19 +19,12 @@ module.exports = { } }, entry: { - orejime: ['./src/umd.ts', './src/styles/orejime.scss'], - migrations: './src/migrations/index.ts' + migrations: './src/migrations/index.ts', + ...standaloneEntries() }, output: { filename: '[name].js', - chunkFilename: (pathData) => { - // strips file names from generated chunk names - return isDev - ? pathData.chunk.name - : pathData.chunk.name.replace(/(\-ts|\-index\-ts)$/, '.js'); - }, path: fullPath('dist'), - publicPath: 'auto', clean: true }, module: { @@ -62,16 +54,11 @@ module.exports = { } }, { - test: /\.ya?ml$/, - use: 'yaml-loader' - }, - { - test: /\.s[ac]ss$/i, + test: /\.css$/i, type: 'javascript/auto', use: [ rspack.CssExtractRspackPlugin.loader, 'css-loader', - 'sass-loader' ] } ] @@ -79,7 +66,9 @@ module.exports = { resolve: { extensions: ['.js', '.ts', '.tsx'], fallback: { - fs: false + fs: false, + // Avoids a warning from uneval. + 'internal-prop': false } }, optimization: { @@ -88,26 +77,11 @@ module.exports = { splitChunks: false }, plugins: [ - new rspack.BannerPlugin({ - banner: - pkg.name + - ' v' + - pkg.version + - ' - ' + - pkg.license + - ' license, ' + - 'original work Copyright (c) 2018 DPKit, ' + - 'modified work Copyright (c) 2019 Boscop, ' + - 'all rights reserved.' - }), new rspack.CssExtractRspackPlugin({ - filename: 'orejime.css' + filename: 'orejime-standard.css' }), new rspack.CopyRspackPlugin({ patterns: [ - { - from: 'src/styles' - }, { from: 'site/assets', to: 'assets', @@ -146,6 +120,38 @@ module.exports = { ] }; +// Generates entries for each possible combination of theme +// and language. +// @see ./adr/002-standalone-bundles.md +function standaloneEntries() { + const themes = fs.readdirSync(fullPath('src/ui/themes')); + const langs = fs + .readdirSync(fullPath('src/translations')) + .map((file) => path.basename(file, '.ts')); + + const entries = {}; + + for (const theme of themes) { + for (const lang of langs) { + entries[`orejime-${theme}-${lang}`] = standaloneEntry(theme, lang); + } + } + + return entries; +} + +function standaloneEntry(theme, lang) { + return ( + 'data:text/javascript,' + + `import theme from '${fullPath(`./src/ui/themes/${theme}/index.ts`)}';` + + `import translations from '${fullPath( + `./src/translations/${lang}.ts` + )}';` + + `import {setupUmd} from '${fullPath('./src/umd.ts')}';` + + 'setupUmd(theme, translations);' + ); +} + // Configures an HTML plugin to render an example page about // a given feature. // Those pages include snippets of JS and/or CSS to setup @@ -191,7 +197,7 @@ async function featureTemplateCode(name, lang) { const {codeToHtml} = await import('shiki'); const highlightedCode = await codeToHtml(code, { lang, - theme + theme: codeTheme }); return { diff --git a/site/features/dsfr.html b/site/features/dsfr.html index 3e795acc..0fbfbdc4 100644 --- a/site/features/dsfr.html +++ b/site/features/dsfr.html @@ -184,7 +184,7 @@

Configuration

- + diff --git a/site/features/dsfr.js b/site/features/dsfr.js index e37e8334..c5ce15cf 100644 --- a/site/features/dsfr.js +++ b/site/features/dsfr.js @@ -1,6 +1,4 @@ window.orejimeConfig = { - theme: 'dsfr', - lang: 'fr', purposes: [ { id: 'mandatory', diff --git a/site/features/i18n.js b/site/features/i18n.js index e85badeb..73576413 100644 --- a/site/features/i18n.js +++ b/site/features/i18n.js @@ -1,7 +1,4 @@ window.orejimeConfig = { - // the base language - lang: 'fr', - // some custom translations translations: { banner: { configure: 'Configurer' diff --git a/site/features/orejime.html b/site/features/orejime.html index 9253d7eb..21a16d6a 100644 --- a/site/features/orejime.html +++ b/site/features/orejime.html @@ -10,6 +10,7 @@ /> + @@ -40,6 +41,8 @@ <% } %> + +