From f99b5f7d2858c130aaddc421645dfe5675b99203 Mon Sep 17 00:00:00 2001 From: LB Johnston Date: Thu, 20 Oct 2022 06:02:30 +1000 Subject: [PATCH 1/3] Install & configure Prettier (code formatting) - fixes #114 - relates to #151 --- .prettierignore | 15 ++++- .prettierrc.json | 5 ++ Makefile | 2 + package.json | 92 ++++++++++++++-------------- webpack.config.js | 152 +++++++++++++++++++++++----------------------- yarn.lock | 5 ++ 6 files changed, 149 insertions(+), 122 deletions(-) create mode 100644 .prettierrc.json diff --git a/.prettierignore b/.prettierignore index 45f591f1..848076a9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,7 +1,16 @@ -*.html -venv -.venv +# Irrelevant files ignored for performance reasons. +*.min.js +**/lib/ +**/vendor/ +_build .git +.mypy_cache +.venv +coverage/ media node_modules +public/ static +venv +# Files which contain incompatible syntax. +*.html diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..b974e716 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "quoteProps": "consistent", + "singleQuote": true, + "trailingComma": "all" +} diff --git a/Makefile b/Makefile index 458fc62e..b6f8fb19 100644 --- a/Makefile +++ b/Makefile @@ -10,11 +10,13 @@ test-coverage: format: poetry run isort apps poetry run black apps + yarn format lint: poetry run flake8 apps poetry run isort --check-only --diff apps poetry run black --check --diff apps + yarn lint frontend: yarn diff --git a/package.json b/package.json index 394ca4fe..2dc4d0ab 100644 --- a/package.json +++ b/package.json @@ -1,46 +1,50 @@ { - "name": "guide", - "private": true, - "author": "", - "engines": { - "node": "^16" - }, - "scripts": { - "start": "webpack --mode=development --watch --progress", - "build": "webpack --mode=production" - }, - "devDependencies": { - "@babel/cli": "^7.17.3", - "@babel/core": "^7.17.5", - "@babel/preset-env": "^7.16.11", - "babel-loader": "^8.2.3", - "copy-webpack-plugin": "^10.2.4", - "css-loader": "^6.6.0", - "file-loader": "^6.2.0", - "mini-css-extract-plugin": "^2.5.3", - "postcss": "^8.4.6", - "postcss-loader": "^6.2.1", - "postcss-preset-env": "^7.4.1", - "sass": "^1.49.8", - "sass-loader": "^12.6.0", - "webpack": "^5.69.1", - "webpack-cli": "^4.9.2", - "webpack-manifest-plugin": "^4.1.1" - }, - "browserslist": [ - "Firefox ESR", - "last 2 Chrome versions", - "last 2 ChromeAndroid versions", - "last 2 Edge versions", - "last 1 Firefox version", - "last 2 iOS versions", - "last 3 Safari versions", - "not safari 13", - "not ie 11" - ], - "dependencies": { - "@popperjs/core": "^2.11.5", - "bootstrap": "^5.1.3", - "lodash.debounce": "^4.0.8" - } + "name": "guide", + "private": true, + "author": "", + "engines": { + "node": "^16" + }, + "scripts": { + "start": "webpack --mode=development --watch --progress", + "build": "webpack --mode=production", + "format": "prettier --write .", + "lint:format": "prettier --check .", + "lint": "yarn lint:format" + }, + "devDependencies": { + "@babel/cli": "^7.17.3", + "@babel/core": "^7.17.5", + "@babel/preset-env": "^7.16.11", + "babel-loader": "^8.2.3", + "copy-webpack-plugin": "^10.2.4", + "css-loader": "^6.6.0", + "file-loader": "^6.2.0", + "mini-css-extract-plugin": "^2.5.3", + "postcss": "^8.4.6", + "postcss-loader": "^6.2.1", + "postcss-preset-env": "^7.4.1", + "prettier": "^2.7.1", + "sass": "^1.49.8", + "sass-loader": "^12.6.0", + "webpack": "^5.69.1", + "webpack-cli": "^4.9.2", + "webpack-manifest-plugin": "^4.1.1" + }, + "browserslist": [ + "Firefox ESR", + "last 2 Chrome versions", + "last 2 ChromeAndroid versions", + "last 2 Edge versions", + "last 1 Firefox version", + "last 2 iOS versions", + "last 3 Safari versions", + "not safari 13", + "not ie 11" + ], + "dependencies": { + "@popperjs/core": "^2.11.5", + "bootstrap": "^5.1.3", + "lodash.debounce": "^4.0.8" + } } diff --git a/webpack.config.js b/webpack.config.js index ff5d8e01..e7b8f621 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,89 +1,91 @@ -const path = require("path"); -const webpack = require("webpack"); -const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -const CopyWebpackPlugin = require("copy-webpack-plugin"); +const path = require('path'); +const webpack = require('webpack'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); const { WebpackManifestPlugin } = require('webpack-manifest-plugin'); const postcssPresetEnv = require('postcss-preset-env'); -const source = path.resolve(path.join("apps", "frontend", "static_src")); -const destination = path.resolve(path.join("apps", "frontend", "static")); +const source = path.resolve(path.join('apps', 'frontend', 'static_src')); +const destination = path.resolve(path.join('apps', 'frontend', 'static')); const config = { - entry: { - main: [ - path.join(source, "js", "main.js"), - path.join(source, "scss", "main.scss"), - ], - }, - output: { - path: destination, - publicPath: "/static/", - filename: "[name]-[fullhash].js", - clean: true, - }, - module: { - rules: [ - { - test: /\.js$/, - exclude: /node_modules/, - use: { - loader: "babel-loader", - options: { - presets: ["@babel/preset-env"] - } - } - }, - { - test: /\.(scss|css)$/, - use: [ - MiniCssExtractPlugin.loader, - { - loader: "css-loader", - options: { - sourceMap: true, + entry: { + main: [ + path.join(source, 'js', 'main.js'), + path.join(source, 'scss', 'main.scss'), + ], + }, + output: { + path: destination, + publicPath: '/static/', + filename: '[name]-[fullhash].js', + clean: true, + }, + module: { + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + presets: ['@babel/preset-env'], + }, + }, }, - }, - { - loader: "postcss-loader", - options: { - sourceMap: true, - postcssOptions: { - plugins: [ - postcssPresetEnv({ enableClientSidePolyfills: false }) - ] - } + { + test: /\.(scss|css)$/, + use: [ + MiniCssExtractPlugin.loader, + { + loader: 'css-loader', + options: { + sourceMap: true, + }, + }, + { + loader: 'postcss-loader', + options: { + sourceMap: true, + postcssOptions: { + plugins: [ + postcssPresetEnv({ + enableClientSidePolyfills: false, + }), + ], + }, + }, + }, + 'sass-loader', + ], }, - }, - "sass-loader", ], - }, - ], - }, - resolve: { - alias: { - "~fonts": path.resolve(path.join(source, "fonts")), - "~images": path.resolve(path.join(source, "images")), }, - }, - plugins: [ - new MiniCssExtractPlugin({ - filename: "[name]-[fullhash].css", - }), - new CopyWebpackPlugin({ - patterns: [ - { - from: path.join(source, "images"), - to: path.join(destination, "images"), + resolve: { + alias: { + '~fonts': path.resolve(path.join(source, 'fonts')), + '~images': path.resolve(path.join(source, 'images')), }, - ] - }), - new WebpackManifestPlugin({ publicPath: "" }), - ], + }, + plugins: [ + new MiniCssExtractPlugin({ + filename: '[name]-[fullhash].css', + }), + new CopyWebpackPlugin({ + patterns: [ + { + from: path.join(source, 'images'), + to: path.join(destination, 'images'), + }, + ], + }), + new WebpackManifestPlugin({ publicPath: '' }), + ], }; module.exports = (env, argv) => { - if (argv.mode === "development") { - config.devtool = "inline-source-map"; - } - return config; + if (argv.mode === 'development') { + config.devtool = 'inline-source-map'; + } + return config; }; diff --git a/yarn.lock b/yarn.lock index 494a9614..9fd2c0ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2608,6 +2608,11 @@ postcss@^8.4.6, postcss@^8.4.7: picocolors "^1.0.0" source-map-js "^1.0.2" +prettier@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" From 444c6a798cc72d1c1f43f90b0673a08726166412 Mon Sep 17 00:00:00 2001 From: LB Johnston Date: Thu, 20 Oct 2022 06:30:33 +1000 Subject: [PATCH 2/3] Readme - add development scripts reference --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index e39fa0bd..410bbfa7 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,12 @@ Steps: If you're a Python or Django developer, fork the repo and join us. You'll find answers to many common new contributor questions in our [contributing guidelines](https://docs.wagtail.org/en/stable/contributing/index.html). +## Development + +- Run formatting (Black Prettier) `make format` +- Run linting (Flake8, isort, Black, Prettier) `make lint` +- Run tests `make test` + # Other Notes ## Google Summer of Code From c58ec89699b3035575915c8e2bb4c82ae2e03e08 Mon Sep 17 00:00:00 2001 From: LB Johnston Date: Thu, 20 Oct 2022 06:02:37 +1000 Subject: [PATCH 3/3] Run Prettier on existing code --- README.md | 39 +++++----- apps/frontend/static_src/js/feedback/index.js | 58 +++++++------- apps/frontend/static_src/js/main.js | 62 +++++++-------- .../static_src/js/mobile-menu/index.js | 26 +++---- .../static_src/js/section-link/index.js | 26 +++---- .../static_src/scss/components/header.scss | 4 +- .../static_src/scss/components/heading.scss | 2 +- .../static_src/scss/components/rich-text.scss | 15 ++-- .../scss/components/section-link.scss | 12 +-- .../static_src/scss/components/toc.scss | 4 +- apps/frontend/static_src/scss/functions.scss | 2 +- apps/frontend/static_src/scss/main.scss | 76 +++++++++---------- apps/frontend/static_src/scss/mixins.scss | 4 +- apps/frontend/static_src/scss/typography.scss | 8 +- apps/frontend/static_src/scss/variables.scss | 8 +- docs/hosting-environment.md | 16 ++-- 16 files changed, 183 insertions(+), 179 deletions(-) diff --git a/README.md b/README.md index 410bbfa7..e8559d93 100644 --- a/README.md +++ b/README.md @@ -3,19 +3,20 @@ Guide is a website to help content editors, moderators, administrators, and other users learn how to user the Wagtail content management system (CMS). The Wagtail guide will ultimately include: -- Tutorials -- How-to articles -- Reference materials -- Walkthroughs and visual learning materials + +- Tutorials +- How-to articles +- Reference materials +- Walkthroughs and visual learning materials You can learn more about the documentation system [here](https://documentation.divio.com/). # Table of Contents -- [Installation](#installation) -- [Gitpod](#gitpod) -- [Contributing](#contributing) -- [Other Notes](#other-notes) +- [Installation](#installation) +- [Gitpod](#gitpod) +- [Contributing](#contributing) +- [Other Notes](#other-notes) # Installation @@ -23,11 +24,11 @@ We assume that you have basic knowledge of Node/Yarn/Webpack and Python/Django/W #### Dependencies -- Python >= 3.9 -- Poetry -- Git -- Node 16.* -- [Yarn](https://yarnpkg.com/) +- Python >= 3.9 +- Poetry +- Git +- Node 16.\* +- [Yarn](https://yarnpkg.com/) ### Setting up Wagtail guide in a virtual environment @@ -68,11 +69,10 @@ With Gitpod you can deploy a ready-to-code Wagtail Guide development environment Steps: -1. Click the ``Open in Gitpod`` button. +1. Click the `Open in Gitpod` button. 2. Relax: a development environment with an active Wagtail Guide site will be created for you. 3. Login at `/admin/` with username `admin` and password `changeme` - # Contributing If you're a Python or Django developer, fork the repo and join us. You'll find answers to many common new contributor questions in our [contributing guidelines](https://docs.wagtail.org/en/stable/contributing/index.html). @@ -91,13 +91,12 @@ This project is one of three [Wagtail](https://wagtail.org/) projects being spon ### Contributor -- [Hitansh Shah](https://github.com/Hitansh-Shah) +- [Hitansh Shah](https://github.com/Hitansh-Shah) ### Mentors -- [Thibaud Colas](https://github.com/thibaudcolas) -- [Coen van der Kamp](https://github.com/allcaps) -- [Meagen Voss](https://github.com/vossisboss) - +- [Thibaud Colas](https://github.com/thibaudcolas) +- [Coen van der Kamp](https://github.com/allcaps) +- [Meagen Voss](https://github.com/vossisboss) You can learn more about our Google Summer of Code project in [Google Summer of Code: Wagtail Editor Guide](https://wagtail.org/blog/google-summer-of-code-wagtail-editor-guide/), [Wagtail CMS projects for Google Summer of Code 2022](https://wagtail.org/blog/wagtail-cms-projects-for-google-summer-of-code-2022/) or on our [wiki page](https://github.com/wagtail/wagtail/wiki/Google-Summer-of-Code-2022). diff --git a/apps/frontend/static_src/js/feedback/index.js b/apps/frontend/static_src/js/feedback/index.js index bcc51d04..dd5d6246 100644 --- a/apps/frontend/static_src/js/feedback/index.js +++ b/apps/frontend/static_src/js/feedback/index.js @@ -1,16 +1,16 @@ -import { Tooltip } from "bootstrap"; +import { Tooltip } from 'bootstrap'; // Function to fetch cookie according to django docs // https://docs.djangoproject.com/en/4.1/howto/csrf/#acquiring-the-token-if-csrf-use-sessions-and-csrf-cookie-httponly-are-false function getCookie(name) { let cookieValue = null; - if (document.cookie && document.cookie !== "") { - const cookies = document.cookie.split(";"); + if (document.cookie && document.cookie !== '') { + const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); // Does this cookie string begin with the name we want? - if (cookie.substring(0, name.length + 1) === name + "=") { + if (cookie.substring(0, name.length + 1) === name + '=') { cookieValue = decodeURIComponent( - cookie.substring(name.length + 1) + cookie.substring(name.length + 1), ); break; } @@ -18,51 +18,51 @@ function getCookie(name) { } return cookieValue; } -const csrftoken = getCookie("csrftoken"); +const csrftoken = getCookie('csrftoken'); export const handleFeedback = () => { // Code to enable tooltip according to // https://getbootstrap.com/docs/5.2/components/tooltips/#enable-tooltips const tooltipTriggerList = document.querySelectorAll( - '[data-bs-toggle="tooltip"]' + '[data-bs-toggle="tooltip"]', ); const tooltipList = [...tooltipTriggerList].map( - (tooltipTriggerEl) => new Tooltip(tooltipTriggerEl) + (tooltipTriggerEl) => new Tooltip(tooltipTriggerEl), ); - const happyButton = document.querySelector("[data-happy-button]"); - const unhappyButton = document.querySelector("[data-unhappy-button]"); + const happyButton = document.querySelector('[data-happy-button]'); + const unhappyButton = document.querySelector('[data-unhappy-button]'); const feedbackContainer = document.querySelector( - "[data-feedback-container]" + '[data-feedback-container]', ); const additionalFeedbackContainer = document.querySelector( - "[data-additional-feedback-container]" + '[data-additional-feedback-container]', ); - const submitButton = document.querySelector("[data-submit-button]"); - const feedbackText = document.querySelector("[data-feedback-text]"); + const submitButton = document.querySelector('[data-submit-button]'); + const feedbackText = document.querySelector('[data-feedback-text]'); let feedbackPk = null; const post_feedback = async (feedback) => { try { const res = await fetch(window.location.pathname, { - method: "POST", + method: 'POST', body: JSON.stringify({ feedback, }), headers: { - "X-CSRFToken": csrftoken, - "Content-type": "application/json; charset=UTF-8", + 'X-CSRFToken': csrftoken, + 'Content-type': 'application/json; charset=UTF-8', }, }); const data = await res.json(); tooltipList.forEach((tooltip) => { tooltip.dispose(); }); - feedbackContainer.innerHTML = "Thanks for your feedback!"; - if (feedback == "unhappy") { - feedbackPk = data["pk"]; - additionalFeedbackContainer.classList.add("active"); + feedbackContainer.innerHTML = 'Thanks for your feedback!'; + if (feedback == 'unhappy') { + feedbackPk = data['pk']; + additionalFeedbackContainer.classList.add('active'); } } catch (err) { console.log(err); @@ -72,30 +72,30 @@ export const handleFeedback = () => { const update_feedback = async (pk) => { try { await fetch(window.location.pathname, { - method: "POST", + method: 'POST', body: JSON.stringify({ pk, feedback_text: feedbackText.value, }), headers: { - "X-CSRFToken": csrftoken, - "Content-type": "application/json; charset=UTF-8", + 'X-CSRFToken': csrftoken, + 'Content-type': 'application/json; charset=UTF-8', }, }); - additionalFeedbackContainer.innerHTML = ""; + additionalFeedbackContainer.innerHTML = ''; } catch (err) { console.log(err); } }; if (happyButton) { - happyButton.addEventListener("click", () => post_feedback("happy")); + happyButton.addEventListener('click', () => post_feedback('happy')); } if (unhappyButton) { - unhappyButton.addEventListener("click", () => post_feedback("unhappy")); + unhappyButton.addEventListener('click', () => post_feedback('unhappy')); } if (submitButton) { - submitButton.addEventListener("click", () => - update_feedback(feedbackPk) + submitButton.addEventListener('click', () => + update_feedback(feedbackPk), ); } }; diff --git a/apps/frontend/static_src/js/main.js b/apps/frontend/static_src/js/main.js index 16201812..a514aab6 100644 --- a/apps/frontend/static_src/js/main.js +++ b/apps/frontend/static_src/js/main.js @@ -1,14 +1,14 @@ -import { Dropdown, Tooltip } from "bootstrap"; -import { initSectionLink } from "./section-link"; -import { handleFeedback } from "./feedback"; -import debounce from "lodash.debounce"; -import MobileMenu from "./mobile-menu"; +import { Dropdown, Tooltip } from 'bootstrap'; +import { initSectionLink } from './section-link'; +import { handleFeedback } from './feedback'; +import debounce from 'lodash.debounce'; +import MobileMenu from './mobile-menu'; initSectionLink(); handleFeedback(); -const searchInput = document.querySelector("[data-search-input]"); -const searchIconButton = document.querySelector("[data-search-icon-button]"); +const searchInput = document.querySelector('[data-search-input]'); +const searchIconButton = document.querySelector('[data-search-icon-button]'); const onSearchInputChange = async (event) => { const query = event.target.value; @@ -16,7 +16,7 @@ const onSearchInputChange = async (event) => { const res = await fetch( `${window.location.origin}/search_json/?${new URLSearchParams({ query, - }).toString()}` + }).toString()}`, ); const data = await res.json(); injectResultsInHTML(data); @@ -25,15 +25,15 @@ const onSearchInputChange = async (event) => { window.alert(`Error: ${err}`); } }; -searchInput.addEventListener("keyup", debounce(onSearchInputChange, 350)); +searchInput.addEventListener('keyup', debounce(onSearchInputChange, 350)); const removeExistingChildren = (parent) => { - parent.innerHTML = ""; + parent.innerHTML = ''; }; -searchIconButton.addEventListener("click", () => { - const resultsDiv = document.querySelector("[data-results]"); +searchIconButton.addEventListener('click', () => { + const resultsDiv = document.querySelector('[data-results]'); const resultsCountContainer = document.querySelector( - "[data-results-count-container]" + '[data-results-count-container]', ); removeExistingChildren(resultsDiv); @@ -41,26 +41,26 @@ searchIconButton.addEventListener("click", () => { }); const injectResultsInHTML = (results) => { - const resultsDiv = document.querySelector("[data-results]"); + const resultsDiv = document.querySelector('[data-results]'); const resultsCountContainer = document.querySelector( - "[data-results-count-container]" + '[data-results-count-container]', ); removeExistingChildren(resultsDiv); removeExistingChildren(resultsCountContainer); - const resultsCountDiv = document.createElement("div"); + const resultsCountDiv = document.createElement('div'); resultsCountDiv.innerText = `${results.length} ${ - results.length == 1 ? "result" : "results" + results.length == 1 ? 'result' : 'results' } found`; - resultsCountDiv.classList.add("m-3", "mx-5"); + resultsCountDiv.classList.add('m-3', 'mx-5'); resultsCountContainer.appendChild(resultsCountDiv); for (const result of results) { - const resultDiv = document.createElement("div"); - const resultLink = document.createElement("a"); - const resultDescription = document.createElement("div"); - const resultParentSection = document.createElement("div"); + const resultDiv = document.createElement('div'); + const resultLink = document.createElement('a'); + const resultDescription = document.createElement('div'); + const resultParentSection = document.createElement('div'); resultLink.innerText = result.title; resultDescription.innerText = result.search_description; resultParentSection.innerText = result.parent_section; @@ -68,15 +68,15 @@ const injectResultsInHTML = (results) => { resultDiv.appendChild(resultParentSection); resultDiv.appendChild(resultLink); resultDiv.appendChild(resultDescription); - resultParentSection.classList.add("py-2"); + resultParentSection.classList.add('py-2'); resultLink.classList.add( - "fw-bold", - "fs-5", - "text-decoration-none", - "text-dark" + 'fw-bold', + 'fs-5', + 'text-decoration-none', + 'text-dark', ); - resultDescription.classList.add("text-muted", "py-2"); - resultDiv.classList.add("mx-5", "py-4", "border-top", "border-bottom"); + resultDescription.classList.add('text-muted', 'py-2'); + resultDiv.classList.add('mx-5', 'py-4', 'border-top', 'border-bottom'); resultsDiv.appendChild(resultDiv); } }; @@ -86,8 +86,8 @@ function initComponent(ComponentClass) { items.forEach((item) => new ComponentClass(item)); } -document.addEventListener("DOMContentLoaded", () => { +document.addEventListener('DOMContentLoaded', () => { // Remove no-js class if JS is enabled - document.documentElement.classList.remove("no-js"); + document.documentElement.classList.remove('no-js'); initComponent(MobileMenu); }); diff --git a/apps/frontend/static_src/js/mobile-menu/index.js b/apps/frontend/static_src/js/mobile-menu/index.js index d393c0f3..d5d10220 100644 --- a/apps/frontend/static_src/js/mobile-menu/index.js +++ b/apps/frontend/static_src/js/mobile-menu/index.js @@ -1,12 +1,12 @@ class MobileMenu { static selector() { - return "[data-mobile-menu-toggle]"; + return '[data-mobile-menu-toggle]'; } constructor(node) { this.node = node; - this.body = document.querySelector("body"); - this.mobileMenu = document.querySelector("[data-mobile-menu]"); + this.body = document.querySelector('body'); + this.mobileMenu = document.querySelector('[data-mobile-menu]'); this.state = { open: false, @@ -16,7 +16,7 @@ class MobileMenu { } bindEventListeners() { - this.node.addEventListener("click", () => { + this.node.addEventListener('click', () => { this.toggle(); }); } @@ -36,21 +36,21 @@ class MobileMenu { // document.addEventListener('onMenuOpen', () => { // // do stuff here...; // }); - const menuOpenEvent = new Event("onMenuOpen"); + const menuOpenEvent = new Event('onMenuOpen'); document.dispatchEvent(menuOpenEvent); - this.node.classList.add("is-open"); - this.node.setAttribute("aria-expanded", "true"); - this.body.classList.add("no-scroll"); - this.mobileMenu.classList.add("is-visible"); + this.node.classList.add('is-open'); + this.node.setAttribute('aria-expanded', 'true'); + this.body.classList.add('no-scroll'); + this.mobileMenu.classList.add('is-visible'); this.state.open = true; } close() { - this.node.classList.remove("is-open"); - this.node.setAttribute("aria-expanded", "false"); - this.body.classList.remove("no-scroll"); - this.mobileMenu.classList.remove("is-visible"); + this.node.classList.remove('is-open'); + this.node.setAttribute('aria-expanded', 'false'); + this.body.classList.remove('no-scroll'); + this.mobileMenu.classList.remove('is-visible'); this.state.open = false; } diff --git a/apps/frontend/static_src/js/section-link/index.js b/apps/frontend/static_src/js/section-link/index.js index 2d130e2f..49952329 100644 --- a/apps/frontend/static_src/js/section-link/index.js +++ b/apps/frontend/static_src/js/section-link/index.js @@ -1,14 +1,14 @@ export const initSectionLink = () => { - const headings = document.querySelectorAll("h1, h2, h3, h4, h5, h6"); - headings.forEach((heading) => { - if (heading.id) { - let sectionLink = document.createElement("a"); - let link = document.createTextNode("¶"); - sectionLink.appendChild(link); - sectionLink.setAttribute("href", "#" + heading.id); - sectionLink.setAttribute("class", "section-link"); - sectionLink.setAttribute("title", "Section link"); - heading.appendChild(sectionLink); - } - }); -} + const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6'); + headings.forEach((heading) => { + if (heading.id) { + let sectionLink = document.createElement('a'); + let link = document.createTextNode('¶'); + sectionLink.appendChild(link); + sectionLink.setAttribute('href', '#' + heading.id); + sectionLink.setAttribute('class', 'section-link'); + sectionLink.setAttribute('title', 'Section link'); + heading.appendChild(sectionLink); + } + }); +}; diff --git a/apps/frontend/static_src/scss/components/header.scss b/apps/frontend/static_src/scss/components/header.scss index 7145eaef..88159c1e 100644 --- a/apps/frontend/static_src/scss/components/header.scss +++ b/apps/frontend/static_src/scss/components/header.scss @@ -19,7 +19,7 @@ // Mask off menu behind logo &::after { - content: ""; + content: ''; pointer-events: none; position: absolute; z-index: -1; @@ -113,7 +113,7 @@ inset: auto; &::before { - content: ""; + content: ''; position: absolute; inset-inline-start: -24px; height: 30px; diff --git a/apps/frontend/static_src/scss/components/heading.scss b/apps/frontend/static_src/scss/components/heading.scss index 1711cd1b..b9aa27c0 100644 --- a/apps/frontend/static_src/scss/components/heading.scss +++ b/apps/frontend/static_src/scss/components/heading.scss @@ -18,7 +18,7 @@ h6 { &::after { display: block; - content: ""; + content: ''; width: 70px; height: 1px; margin-top: ($gutter * 2); diff --git a/apps/frontend/static_src/scss/components/rich-text.scss b/apps/frontend/static_src/scss/components/rich-text.scss index a619141a..d8dacb4f 100644 --- a/apps/frontend/static_src/scss/components/rich-text.scss +++ b/apps/frontend/static_src/scss/components/rich-text.scss @@ -1,7 +1,11 @@ code { - // Using Wagtail’s monospace font: + // Using Wagtail’s monospace font: // https://github.com/wagtail/wagtail/blob/849d4d71cae41de56e43832546429cbb8ad289d5/client/src/tokens/typography.js#L38 - font-family: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono', + 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro', + 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace, + 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', + 'Noto Color Emoji'; } kbd { @@ -9,12 +13,13 @@ kbd { background-color: #eee; border-radius: 3px; border: 1px solid #b4b4b4; - box-shadow: 0 1px 1px rgba(0, 0, 0, .2), 0 2px 0 0 rgba(255, 255, 255, .7) inset; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), + 0 2px 0 0 rgba(255, 255, 255, 0.7) inset; color: #333; display: inline-block; - font-size: .85em; + font-size: 0.85em; font-weight: 700; line-height: 1; padding: 2px 4px; white-space: nowrap; -} \ No newline at end of file +} diff --git a/apps/frontend/static_src/scss/components/section-link.scss b/apps/frontend/static_src/scss/components/section-link.scss index adff5b38..66db87ea 100644 --- a/apps/frontend/static_src/scss/components/section-link.scss +++ b/apps/frontend/static_src/scss/components/section-link.scss @@ -1,7 +1,7 @@ .section-link { - display: none; - text-decoration: none; - margin-left: 0.25em; + display: none; + text-decoration: none; + margin-left: 0.25em; } h2, @@ -9,7 +9,7 @@ h3, h4, h5, h6 { - &:hover .section-link { - display: inline; - } + &:hover .section-link { + display: inline; + } } diff --git a/apps/frontend/static_src/scss/components/toc.scss b/apps/frontend/static_src/scss/components/toc.scss index ecfa19e5..68627a39 100644 --- a/apps/frontend/static_src/scss/components/toc.scss +++ b/apps/frontend/static_src/scss/components/toc.scss @@ -26,13 +26,13 @@ margin-bottom: ($gutter * 0.5); &::before { - content: ""; + content: ''; display: inline-block; height: 20px; width: 20px; margin-right: 13px; // arrow in circle fa icon - background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjMDA3RDdFIiBkPSJNMjgwLjIgMTUwLjJjLTcuMS02LjQtMTguMS04LTI1LjktNC4xcy0xNS4yIDEyLjQtMTUuMiAyMWwuMDAyIDU2TDE1MiAyMjRjLTEzLjIgMC0yNCAxMC44LTI0IDI0djE2YzAgMTMuMyAxMC44IDI0IDI0IDI0bDg4LS45djU2YzAgOS41MzEgNS42NTYgMTguMTYgMTQuMzggMjJhMjQuMDI1IDI0LjAyNSAwIDAgMCAyNS45MS00LjM3NWw5Ni04OC43NUMzODEuMiAyNjguMyAzODQgMjYxLjkgMzg0IDI1NS4yYy0uMzEzLTcuNzgxLTIuODc1LTEzLjI1LTcuODQ0LTE3Ljc1TDI4MC4yIDE1MC4yek0yNTYgMEMxMTQuNiAwIDAgMTE0LjYgMCAyNTZzMTE0LjYgMjU2IDI1NiAyNTYgMjU2LTExNC42IDI1Ni0yNTZTMzk3LjQgMCAyNTYgMHptMCA0NjRjLTExNC43IDAtMjA4LTkzLjMxLTIwOC0yMDhTMTQxLjMgNDggMjU2IDQ4czIwOCA5My4zMSAyMDggMjA4LTkzLjMgMjA4LTIwOCAyMDh6Ii8+PC9zdmc+"); + background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjMDA3RDdFIiBkPSJNMjgwLjIgMTUwLjJjLTcuMS02LjQtMTguMS04LTI1LjktNC4xcy0xNS4yIDEyLjQtMTUuMiAyMWwuMDAyIDU2TDE1MiAyMjRjLTEzLjIgMC0yNCAxMC44LTI0IDI0djE2YzAgMTMuMyAxMC44IDI0IDI0IDI0bDg4LS45djU2YzAgOS41MzEgNS42NTYgMTguMTYgMTQuMzggMjJhMjQuMDI1IDI0LjAyNSAwIDAgMCAyNS45MS00LjM3NWw5Ni04OC43NUMzODEuMiAyNjguMyAzODQgMjYxLjkgMzg0IDI1NS4yYy0uMzEzLTcuNzgxLTIuODc1LTEzLjI1LTcuODQ0LTE3Ljc1TDI4MC4yIDE1MC4yek0yNTYgMEMxMTQuNiAwIDAgMTE0LjYgMCAyNTZzMTE0LjYgMjU2IDI1NiAyNTYgMjU2LTExNC42IDI1Ni0yNTZTMzk3LjQgMCAyNTYgMHptMCA0NjRjLTExNC43IDAtMjA4LTkzLjMxLTIwOC0yMDhTMTQxLjMgNDggMjU2IDQ4czIwOCA5My4zMSAyMDggMjA4LTkzLjMgMjA4LTIwOCAyMDh6Ii8+PC9zdmc+'); } a { diff --git a/apps/frontend/static_src/scss/functions.scss b/apps/frontend/static_src/scss/functions.scss index 5458d744..a8ff475e 100644 --- a/apps/frontend/static_src/scss/functions.scss +++ b/apps/frontend/static_src/scss/functions.scss @@ -1,4 +1,4 @@ -@use "sass:math"; +@use 'sass:math'; // Strip the unit from the given value and return the value @function strip-unit($value) { diff --git a/apps/frontend/static_src/scss/main.scss b/apps/frontend/static_src/scss/main.scss index fe493818..b3fefb9e 100644 --- a/apps/frontend/static_src/scss/main.scss +++ b/apps/frontend/static_src/scss/main.scss @@ -1,44 +1,44 @@ // Setup -@import "./vendor/normalize"; -@import "./typography"; -@import "./variables"; -@import "./functions"; -@import "./mixins"; +@import './vendor/normalize'; +@import './typography'; +@import './variables'; +@import './functions'; +@import './mixins'; // Bootstrap components and config -@import "~bootstrap/scss/functions"; -@import "~bootstrap/scss/variables"; -@import "~bootstrap/scss/mixins"; -@import "~bootstrap/scss/dropdown"; -@import "~bootstrap/scss/modal"; -@import "~bootstrap/scss/tooltip"; +@import '~bootstrap/scss/functions'; +@import '~bootstrap/scss/variables'; +@import '~bootstrap/scss/mixins'; +@import '~bootstrap/scss/dropdown'; +@import '~bootstrap/scss/modal'; +@import '~bootstrap/scss/tooltip'; // Custom component styles -@import "./components/alert"; -@import "./components/app"; -@import "./components/base"; -@import "./components/burger"; -@import "./components/dropdown-toggle"; -@import "./components/error-page"; -@import "./components/feedback-emoji"; -@import "./components/feedback"; -@import "./components/footer"; -@import "./components/grid"; -@import "./components/header"; -@import "./components/heading"; -@import "./components/introduction"; -@import "./components/language-selector"; -@import "./components/link-block"; -@import "./components/nav-buttons"; -@import "./components/navigation"; -@import "./components/primary-nav"; -@import "./components/rich-text"; -@import "./components/rich-text-image"; -@import "./components/search"; -@import "./components/section"; -@import "./components/section-link"; -@import "./components/skip-link"; -@import "./components/streamfield"; -@import "./components/toc"; +@import './components/alert'; +@import './components/app'; +@import './components/base'; +@import './components/burger'; +@import './components/dropdown-toggle'; +@import './components/error-page'; +@import './components/feedback-emoji'; +@import './components/feedback'; +@import './components/footer'; +@import './components/grid'; +@import './components/header'; +@import './components/heading'; +@import './components/introduction'; +@import './components/language-selector'; +@import './components/link-block'; +@import './components/nav-buttons'; +@import './components/navigation'; +@import './components/primary-nav'; +@import './components/rich-text'; +@import './components/rich-text-image'; +@import './components/search'; +@import './components/section'; +@import './components/section-link'; +@import './components/skip-link'; +@import './components/streamfield'; +@import './components/toc'; -@import "./utilities"; +@import './utilities'; diff --git a/apps/frontend/static_src/scss/mixins.scss b/apps/frontend/static_src/scss/mixins.scss index bbf98b92..636072e2 100644 --- a/apps/frontend/static_src/scss/mixins.scss +++ b/apps/frontend/static_src/scss/mixins.scss @@ -1,5 +1,5 @@ -@use "sass:list"; -@use "sass:map"; +@use 'sass:list'; +@use 'sass:map'; // Media queries @mixin media-query($queries...) { diff --git a/apps/frontend/static_src/scss/typography.scss b/apps/frontend/static_src/scss/typography.scss index a17f590b..cccdff07 100644 --- a/apps/frontend/static_src/scss/typography.scss +++ b/apps/frontend/static_src/scss/typography.scss @@ -1,12 +1,12 @@ @font-face { - font-family: "Kumbh Sans"; - src: url("../fonts/KumbhSans-Regular.woff2") format("woff2"); + font-family: 'Kumbh Sans'; + src: url('../fonts/KumbhSans-Regular.woff2') format('woff2'); font-weight: 400; font-display: block; } @font-face { - font-family: "Kumbh Sans"; - src: url("../fonts/KumbhSans-Bold.woff2") format("woff2"); + font-family: 'Kumbh Sans'; + src: url('../fonts/KumbhSans-Bold.woff2') format('woff2'); font-weight: 700; } diff --git a/apps/frontend/static_src/scss/variables.scss b/apps/frontend/static_src/scss/variables.scss index 583a0833..0868f3d2 100644 --- a/apps/frontend/static_src/scss/variables.scss +++ b/apps/frontend/static_src/scss/variables.scss @@ -20,9 +20,9 @@ $color--active: $color--blue; $color--page-bg: $color--light-grey; // Typography -$font-family-base: Kumbh Sans, -apple-system, BlinkMacSystemFont, "Segoe UI", - system-ui, Roboto, "Helvetica Neue", Arial, sans-serif, Apple Color Emoji, - "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; +$font-family-base: Kumbh Sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', + system-ui, Roboto, 'Helvetica Neue', Arial, sans-serif, Apple Color Emoji, + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; // scss-docs-start nav-variables $nav-link-padding-y: 0.25rem; @@ -95,4 +95,4 @@ $small-font-sizes: ( ); // Breakpoints - should match bootstrap -$breakpoints: ("medium" "(min-width: 599px)", "large" "(min-width: 1023px)"); +$breakpoints: ('medium' '(min-width: 599px)', 'large' '(min-width: 1023px)'); diff --git a/docs/hosting-environment.md b/docs/hosting-environment.md index b03b4562..1f70dc4f 100644 --- a/docs/hosting-environment.md +++ b/docs/hosting-environment.md @@ -2,12 +2,12 @@ The Wagtail Guide is a Dockerized Django application running on Heroku: -- Persistent data is stored in Heroku Postgres -- Heroku Data for Redis is used as a cache -- Logs are archived to Papertrail for historical analysis -- User-uploaded files are stored in AWS S3 -- Email is handled by Mailgun -- Sentry is used for error monitoring +- Persistent data is stored in Heroku Postgres +- Heroku Data for Redis is used as a cache +- Logs are archived to Papertrail for historical analysis +- User-uploaded files are stored in AWS S3 +- Email is handled by Mailgun +- Sentry is used for error monitoring The application itself runs in Heroku's Europe region (`eu-west-1` (Dublin, Ireland)). @@ -15,7 +15,7 @@ The application itself runs in Heroku's Europe region (`eu-west-1` (Dublin, Irel Deployment is handled automatically by Heroku. When commits are pushed to `main`, Heroku automatically begins building and deploying the site. This deployment only occurs _after_ CI has run and passed. -Currently, only a staging environment exists, so `main` deploys to staging. Once a production environment exists, this will be updated. +Currently, only a staging environment exists, so `main` deploys to staging. Once a production environment exists, this will be updated. ## Access @@ -27,4 +27,4 @@ Whilst Torchbox's sysadmin team maintain and monitor the application's infrastru ## Useful links -- https://github.com/wagtail/guide/pull/47 +- https://github.com/wagtail/guide/pull/47