Skip to content

Commit

Permalink
Use Webpack for Cotton Candy's assets. (bartfeenstra#909)
Browse files Browse the repository at this point in the history
  • Loading branch information
bartfeenstra authored Nov 13, 2022
1 parent f6863a7 commit 9e257c9
Show file tree
Hide file tree
Showing 27 changed files with 236 additions and 91 deletions.
21 changes: 19 additions & 2 deletions betty/cotton_candy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import logging
import re
from pathlib import Path
from shutil import copy2
from typing import Optional, TYPE_CHECKING, Set, Type, Dict, Callable

from PyQt6.QtWidgets import QWidget
Expand All @@ -11,9 +13,10 @@
from betty.config import Configuration, ConfigurationError, DumpedConfiguration, minimize_dumped_configuration
from betty.cotton_candy.search import Index
from betty.error import ensure_context
from betty.generate import Generator
from betty.gui import GuiBuilder
from betty.jinja2 import Jinja2Provider
from betty.npm import _Npm, NpmBuilder
from betty.npm import _Npm, NpmBuilder, npm
from betty.project import EntityReferences

if TYPE_CHECKING:
Expand Down Expand Up @@ -127,7 +130,7 @@ def dump(self) -> DumpedConfiguration:


@reactive
class CottonCandy(Theme, ConfigurableExtension[CottonCandyConfiguration], GuiBuilder, ReactiveInstance, NpmBuilder, Jinja2Provider):
class CottonCandy(Theme, ConfigurableExtension[CottonCandyConfiguration], Generator, GuiBuilder, ReactiveInstance, NpmBuilder, Jinja2Provider):
@classmethod
def depends_on(cls) -> Set[Type[Extension]]:
return {_Npm}
Expand Down Expand Up @@ -158,3 +161,17 @@ def globals(self) -> Dict[str, Callable]:
return {
'search_index': lambda: Index(self.app).build(),
}

async def npm_build(self, working_directory_path: Path, assets_directory_path: Path) -> None:
await self.app.extensions[_Npm].install(type(self), working_directory_path)
await npm(('run', 'webpack'), cwd=working_directory_path)
self._copy_npm_build(working_directory_path / 'webpack-build', assets_directory_path)
logging.getLogger().info('Built the Cotton Candy front-end assets.')

def _copy_npm_build(self, source_directory_path: Path, destination_directory_path: Path) -> None:
copy2(source_directory_path / 'cotton_candy.css', destination_directory_path / 'cotton_candy.css')
copy2(source_directory_path / 'cotton_candy.js', destination_directory_path / 'cotton_candy.js')

async def generate(self) -> None:
assets_directory_path = await self.app.extensions[_Npm].ensure_assets(self)
self._copy_npm_build(assets_directory_path, self.app.project.configuration.www_directory_path)
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
root: true
parserOptions:
ecmaVersion: 5
sourceType: script
ecmaVersion: 6
sourceType: module
env:
browser: true
es6: true
node: true
extends:
- standard
- eslint:recommended
- plugin:compat/recommended
rules:
no-var: off
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use strict'

var _CLOSE_KEYS = ['Escape']
var _PREVIOUS_FILE_KEYS = ['ArrowLeft']
var _NEXT_FILE_KEYS = ['ArrowRight']
const _CLOSE_KEYS = ['Escape']
const _PREVIOUS_FILE_KEYS = ['ArrowLeft']
const _NEXT_FILE_KEYS = ['ArrowRight']

var _positionX = null
var _positionY = null
let _positionX = null
let _positionY = null

function _initializeFiles () {
_initializeFileExtendedOpen()
Expand All @@ -14,9 +14,9 @@ function _initializeFiles () {
}

function _initializeFileExtendedOpen () {
var links = document.getElementsByClassName('file-extended-open')
for (var i = 0; i < links.length; i++) {
var link = links[i]
const links = document.getElementsByClassName('file-extended-open')
for (let i = 0; i < links.length; i++) {
const link = links[i]
link.addEventListener('click', _openExtended)
}
}
Expand All @@ -27,9 +27,9 @@ function _openExtended () {
}

function _initializeFileExtendedClose () {
var links = document.getElementsByClassName('file-extended-close')
for (var i = 0; i < links.length; i++) {
var link = links[i]
const links = document.getElementsByClassName('file-extended-close')
for (let i = 0; i < links.length; i++) {
const link = links[i]
link.addEventListener('click', _closeExtended)
}
}
Expand All @@ -48,17 +48,17 @@ function _closeExtended (e) {
function _initializeFileExtendedKeyPresses () {
document.addEventListener('keydown', function (e) {
if (_CLOSE_KEYS.indexOf(e.key) !== -1) {
var close = document.querySelector('.file-extended:target .file-extended-close a')
const close = document.querySelector('.file-extended:target .file-extended-close a')
if (close) {
close.click()
}
} else if (_PREVIOUS_FILE_KEYS.indexOf(e.key) !== -1) {
var previous = document.querySelector('.file-extended:target .file-extended-previous a')
const previous = document.querySelector('.file-extended:target .file-extended-previous a')
if (previous) {
previous.click()
}
} else if (_NEXT_FILE_KEYS.indexOf(e.key) !== -1) {
var next = document.querySelector('.file-extended:target .file-extended-next a')
const next = document.querySelector('.file-extended:target .file-extended-next a')
if (next) {
next.click()
}
Expand Down
6 changes: 6 additions & 0 deletions betty/cotton_candy/assets/betty.npm._Npm/src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use strict'

import './file' // eslint-disable-line no-unused-vars
import './search' // eslint-disable-line no-unused-vars
import './show' // eslint-disable-line no-unused-vars
import mainStyle from './main.scss' // eslint-disable-line no-unused-vars
12 changes: 12 additions & 0 deletions betty/cotton_candy/assets/betty.npm._Npm/src/main.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@import "accessibility.scss";
@import "citation.scss";
@import "entity.scss";
@import "file.scss";
@import "meta.scss";
@import "overlay.scss";
@import "page.scss";
@import "permalink.scss";
@import "person.scss";
@import "search.scss";
@import "show.scss";
@import "text.scss";
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import url("variables.css");
@import "variables.scss";

.has-overlay {
position: fixed;
Expand Down Expand Up @@ -34,7 +34,7 @@
}

.overlay-close {
background-image: var(--close-svg-url);
background-image: $close-svg-url;
background-position: center;
background-repeat: no-repeat;
background-size: 2rem 2rem;
Expand Down
24 changes: 24 additions & 0 deletions betty/cotton_candy/assets/betty.npm._Npm/src/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"main": "main.js",
"engines": {
"node": ">= 16"
},
"dependencies": {
"@babel/core": "^7.19.6",
"@babel/preset-env": "^7.19.4",
"babel-loader": "^9.1.0",
"clean-webpack-plugin": "^4.0.0",
"core-js": "^3.26.0",
"css-loader": "^6.7.1",
"mini-css-extract-plugin": "^2.6.1",
"postcss-loader": "^7.0.1",
"sass": "^1.56.1",
"sass-loader": "^13.2.0",
"style-loader": "^3.3.1",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0"
},
"scripts": {
"webpack": "webpack --config webpack.config.js"
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import url("variables.css");
@import "variables.scss";

html {
height: 100%;
Expand Down Expand Up @@ -51,7 +51,7 @@ footer {
* Navigation.
*/
#site-title {
background-image: var(--betty-32-32-png-url);
background-image: $betty-32-32-png-url;
background-position: center;
background-repeat: no-repeat;
display: block;
Expand Down Expand Up @@ -87,12 +87,12 @@ footer {

.nav-primary-expandable:hover .nav-primary-action {
background-color: #fff;
color: var(--link-active-color);
color: $link-active-color;
}

.nav-primary-expanded {
background-color: #fff;
border-bottom: 0.3em var(--primary-active-color) solid;
border-bottom: 0.3em $primary-active-color solid;
display: none;
left: 0;
margin: 0;
Expand Down Expand Up @@ -130,7 +130,7 @@ footer {
}

#nav-sections .nav-primary-action {
background-image: var(--menu-svg-url);
background-image: $menu-svg-url;
background-position: center;
background-repeat: no-repeat;
background-size: 2rem 2rem;
Expand All @@ -139,7 +139,7 @@ footer {
}

#nav-locale .nav-primary-action {
background-image: var(--language-svg-url);
background-image: $language-svg-url;
background-position: center;
background-repeat: no-repeat;
background-size: 2rem 2rem;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import url("variables.css");
@import "variables.scss";

.permalink {
color: #777;
Expand All @@ -10,7 +10,7 @@
}

.permalink:hover {
color: var(--link-active-color);
color: $link-active-color;
}

h1:hover .permalink,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'
var _HIDE_SEARCH_KEYS = ['Escape']
var _NEXT_RESULT_KEYS = ['ArrowDown']
var _PREVIOUS_RESULT_KEYS = ['ArrowUp']
const _HIDE_SEARCH_KEYS = ['Escape']
const _NEXT_RESULT_KEYS = ['ArrowDown']
const _PREVIOUS_RESULT_KEYS = ['ArrowUp']

function Search () {
this._query = null
Expand All @@ -11,7 +11,7 @@ function Search () {
this._queryElement = document.getElementById('search-query')
this._resultsContainer = document.getElementById('search-results-container')
this._documentY = null
var _this = this
const _this = this

// Prevent default form submission behaviors, such as HTTP requests.
this._form.addEventListener('submit', function (e) {
Expand Down Expand Up @@ -66,7 +66,7 @@ Search.prototype._navigateResults = function (keyCode) {

if (document.activeElement.classList.contains('search-result-target')) {
// If the focus lies on a search result, focus on the previous search result if there is one.
var previousSearchResultContainer = document.activeElement.closest('.search-result').previousElementSibling
const previousSearchResultContainer = document.activeElement.closest('.search-result').previousElementSibling
if (previousSearchResultContainer) {
previousSearchResultContainer.querySelector('.search-result-target').focus()
return
Expand All @@ -78,15 +78,15 @@ Search.prototype._navigateResults = function (keyCode) {
} else if (_NEXT_RESULT_KEYS.indexOf(keyCode) !== -1) {
// If the focus lies on the query input element, focus on the first search result.
if (document.activeElement === this._queryElement) {
var resultTargets = this._resultsContainer.getElementsByClassName('search-result-target')
const resultTargets = this._resultsContainer.getElementsByClassName('search-result-target')
if (0 in resultTargets) {
resultTargets[0].focus()
}
return
}
// If the focus lies on a search result, focus on the next search result if there is one.
if (document.activeElement.classList.contains('search-result-target')) {
var nextSearchResultContainer = document.activeElement.closest('.search-result').nextElementSibling
const nextSearchResultContainer = document.activeElement.closest('.search-result').nextElementSibling
if (nextSearchResultContainer) {
nextSearchResultContainer.querySelector('.search-result-target').focus()
}
Expand Down Expand Up @@ -129,9 +129,9 @@ Search.prototype._performCacheQuery = function (query) {
}

Search.prototype._performFromCachedQuery = function () {
var query = this._query
const query = this._query
this._query = null
var _this = this
const _this = this
this._setSearchResults(this._index.filter(function (result) {
return _this._match(query, result.text)
}))
Expand All @@ -145,11 +145,11 @@ Search.prototype._performCached = function (query) {
Search.prototype._performUncached = function (query) {
this._query = query
this.perform = this._performCacheQuery
var _this = this
var indexRequest = new XMLHttpRequest()
const _this = this
const indexRequest = new XMLHttpRequest()
indexRequest.open('GET', this._indexUrl)
indexRequest.addEventListener('load', function () {
var index = JSON.parse(indexRequest.response)
const index = JSON.parse(indexRequest.response)
_this._index = index.index
_this._resultContainerTemplate = index.resultContainerTemplate
_this._resultsContainerTemplate = index.resultsContainerTemplate
Expand All @@ -162,8 +162,8 @@ Search.prototype._performUncached = function (query) {
Search.prototype.perform = Search.prototype._performUncached

Search.prototype._match = function (query, haystack) {
var queryParts = query.toLowerCase().split(/\s/)
for (var i in queryParts) {
const queryParts = query.toLowerCase().split(/\s/)
for (const i in queryParts) {
if (haystack.indexOf(queryParts[i]) === -1) {
return false
}
Expand All @@ -172,7 +172,7 @@ Search.prototype._match = function (query, haystack) {
}

Search.prototype._renderResults = function (results) {
var _this = this
const _this = this
return this._resultsContainerTemplate
.replace('<!-- betty-search-results -->', results.map(function (result) {
return _this._renderResult(result)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import url("variables.css");
@import "variables.scss";

#search {
display: none;
Expand Down Expand Up @@ -34,8 +34,8 @@
}

#search label[for="search-query"] {
background-color: var(--primary-inactive-color);
background-image: var(--search-svg-url);
background-color: $primary-inactive-color;
background-image: $search-svg-url;
background-position: center;
background-repeat: no-repeat;
background-size: 1.5rem 1.5rem;
Expand All @@ -50,7 +50,7 @@

#search label[for="search-query"]:hover,
#search.overlay label[for="search-query"] {
background-color: var(--primary-active-color);
background-color: $primary-active-color;
}

#search.overlay form {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
'use strict'

function initializeToggles () {
var toggles = document.getElementsByClassName('show-toggle')
for (var i = 0; i < toggles.length; i++) {
const toggles = document.getElementsByClassName('show-toggle')
for (let i = 0; i < toggles.length; i++) {
initializeToggle(toggles[i])
}
}

function initializeToggle (toggle) {
toggle.addEventListener('click', function () {
var container = getContainer(this)
const container = getContainer(this)
if (container) {
container.classList.toggle('show-shown')
}
Expand Down
Loading

0 comments on commit 9e257c9

Please sign in to comment.