Skip to content

Commit

Permalink
Partials (#560)
Browse files Browse the repository at this point in the history
* Add new "partials" feature.
* Adds templates with shortcuts as Handlebars partials.
* Use static exports in content script stores.
* Remove deprecated Fastmail plugin.
* Improve setting up the template context before parsing.
* Speed up unit tests.
  • Loading branch information
ghinda authored Dec 4, 2024
1 parent b30bb4b commit e7a4ee8
Show file tree
Hide file tree
Showing 43 changed files with 1,079 additions and 1,063 deletions.
File renamed without changes.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ xcuserdata/
test/bundle

# firebase config, for firefox reviewers
.firebase-config.json
.firebase-config*.json

# playwright
/test-results/
Expand Down
7 changes: 7 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ export default [
'no-console': 'error',
},
},
{
ignores: [
'ext/*',
'test/bundle/*',
'safari/*',
],
},
]
1,170 changes: 560 additions & 610 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "briskine",
"version": "7.13.13",
"version": "7.14.0",
"description": "Write everything faster.",
"private": true,
"type": "module",
Expand All @@ -11,8 +11,8 @@
"start:firefox:android": "web-ext run --source-dir ./ext/ -t firefox-android",
"staging": "webpack -w --mode=production --env mode=staging",
"build": "webpack --mode=production --env mode=production",
"sourcebuild": "git archive --format zip --output sourcebuild/sourcebuild-${npm_package_version}.zip HEAD; zip -u sourcebuild/sourcebuild-${npm_package_version}.zip .firebase-config.json",
"lint": "eslint 'src/**/*.js' test/test-server.js",
"sourcebuild": "git archive --format zip --output sourcebuild/sourcebuild-${npm_package_version}.zip HEAD; zip -u sourcebuild/sourcebuild-${npm_package_version}.zip .firebase-config-production.json",
"lint": "eslint",
"playwright:firefox": "npm run build -- manifest=2 && playwright test --project=firefox",
"playwright:chrome": "npm run build && playwright test --project=chromium",
"playwright:run": "npm run playwright:firefox && npm run playwright:chrome",
Expand Down Expand Up @@ -60,10 +60,10 @@
"globals": "^15.1.0",
"http-server": "^14.1.1",
"mini-css-extract-plugin": "^2.0.0",
"mocha": "^10.0.0",
"mocha": "^11.0.0",
"mockdate": "^3.0.2",
"puppeteer": "^23.3.0",
"purgecss-webpack-plugin": "^6.0.0",
"purgecss-webpack-plugin": "^7.0.0",
"web-ext": "^8.0.0",
"webpack": "^5.11.1",
"webpack-cli": "^5.0.0"
Expand Down
4 changes: 3 additions & 1 deletion playwright/ckeditor/ckeditor.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
<body>
<textarea id="editor"></textarea>
<script>
ClassicEditor.create(document.querySelector('#editor'))
ClassicEditor.create(document.querySelector('#editor'), {
licenseKey: 'GPL',
})
</script>
</body>
</html>
4 changes: 2 additions & 2 deletions src/content/autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import zendeskPlugin from './plugins/zendesk.js'
import crmPlugin from './plugins/crm.js'
import universalPlugin from './plugins/universal.js'

import store from '../store/store-content.js'
import {updateTemplateStats} from '../store/store-content.js'
import {isContentEditable} from './editors/editor-contenteditable.js'

// register plugins,
Expand Down Expand Up @@ -124,6 +124,6 @@ export function getSelectedWord (params) {

export async function autocomplete (params) {
await runPlugins(Object.assign({}, params))
await store.updateTemplateStats(params.quicktext)
await updateTemplateStats(params.quicktext)
return params
}
4 changes: 2 additions & 2 deletions src/content/dashboard-events-client.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import store from '../store/store-content.js'
import {refetchCollections} from '../store/store-content.js'
import config from '../config.js'

const prefix = 'briskine-dashboard'
Expand Down Expand Up @@ -30,7 +30,7 @@ function clearCache (collection) {
clearCacheTimer = setTimeout(() => {
const updates = batchedUpdates.slice()
refetching.then(() => {
refetching = store.refetchCollections(updates)
refetching = refetchCollections(updates)
})

clearCacheTimer = null
Expand Down
4 changes: 2 additions & 2 deletions src/content/dialog/dialog-settings.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {For, mergeProps} from 'solid-js'

import store from '../../store/store-content.js'
import {setExtensionData} from '../../store/store-content.js'
import config from '../../config.js'

const sortOptions = [
Expand Down Expand Up @@ -37,7 +37,7 @@ export default function DialogSettings (originalProps) {
updatedData.dialogTags = e.target.checked
}

store.setExtensionData(updatedData)
setExtensionData(updatedData)
}

return (
Expand Down
43 changes: 26 additions & 17 deletions src/content/dialog/dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@ import {Show, onMount, onCleanup, createSignal, createEffect, mergeProps} from '
import {render} from 'solid-js/web'

import config from '../../config.js'
import store from '../../store/store-content.js'
import {
getTemplates,
getTags,
getAccount,
getExtensionData,
on as storeOn,
off as storeOff,
searchTemplates,
openPopup,
} from '../../store/store-content.js'
import {isContentEditable} from '../editors/editor-contenteditable.js'
import {bubbleTagName} from '../bubble/bubble.js'
import {getEditableCaret, getContentEditableCaret, getDialogPosition} from './dialog-position.js'
Expand Down Expand Up @@ -232,19 +241,19 @@ function Dialog (originalProps) {
}

async function templatesUpdated () {
setTemplates(await store.getTemplates())
setTemplates(await getTemplates())
}

async function tagsUpdated () {
setTags(await store.getTags())
setTags(await getTags())
}

function extensionDataUpdated (data) {
setExtensionData(data)
}

async function loadData () {
const extensionData = await store.getExtensionData()
const extensionData = await getExtensionData()
extensionDataUpdated(extensionData)

await templatesUpdated()
Expand All @@ -254,7 +263,7 @@ function Dialog (originalProps) {
}

function setAuthState () {
store.getAccount()
getAccount()
.then(() => {
return true
})
Expand Down Expand Up @@ -348,12 +357,12 @@ function Dialog (originalProps) {
onMount(() => {
// check authentication state
setAuthState()
store.on('login', setAuthState)
store.on('logout', setAuthState)
storeOn('login', setAuthState)
storeOn('logout', setAuthState)

store.on('templates-updated', templatesUpdated)
store.on('tags-updated', tagsUpdated)
store.on('extension-data-updated', extensionDataUpdated)
storeOn('templates-updated', templatesUpdated)
storeOn('tags-updated', tagsUpdated)
storeOn('extension-data-updated', extensionDataUpdated)

let searchDebouncer
searchField = element.querySelector('input[type=search]')
Expand All @@ -367,7 +376,7 @@ function Dialog (originalProps) {
const searchValue = e.target.value
if (searchValue) {
searchDebouncer = setTimeout(async () => {
const {query, results} = await store.searchTemplates(searchValue)
const {query, results} = await searchTemplates(searchValue)
if (query === searchValue) {
setSearchQuery(searchValue)
setSearchResults(results)
Expand Down Expand Up @@ -411,7 +420,7 @@ function Dialog (originalProps) {
// login button
if (target.closest('.dialog-login-btn')) {
e.preventDefault()
store.openPopup()
openPopup()
setVisible(false)
}
})
Expand Down Expand Up @@ -442,12 +451,12 @@ function Dialog (originalProps) {
window.removeEventListener('keydown', hideOnEsc, true)
window.removeEventListener('keydown', handleSearchFieldShortcuts, true)

store.off('login', setAuthState)
store.off('logout', setAuthState)
storeOff('login', setAuthState)
storeOff('logout', setAuthState)

store.off('templates-updated', templatesUpdated)
store.off('tags-updated', tagsUpdated)
store.off('extension-data-updated', extensionDataUpdated)
storeOff('templates-updated', templatesUpdated)
storeOff('tags-updated', tagsUpdated)
storeOff('extension-data-updated', extensionDataUpdated)

window.removeEventListener('keydown', stopTargetPropagation, true)
window.removeEventListener('keypress', stopTargetPropagation, true)
Expand Down
4 changes: 3 additions & 1 deletion src/content/editors/editor-ckeditor.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ describe('editor CKEditor', function () {
$script.textContent = `
import ClassicEditor from 'https://cdn.jsdelivr.net/npm/@ckeditor/ckeditor5-build-classic/+esm'
await ClassicEditor.create(document.querySelector('#ckeditor'))
await ClassicEditor.create(document.querySelector('#ckeditor'), {
licenseKey: 'GPL',
})
window.dispatchEvent(new Event('ckeditor-ready'))
`
document.body.appendChild($script)
Expand Down
5 changes: 1 addition & 4 deletions src/content/helpers/and.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// conditional and helper
import Handlebars from 'handlebars'

function and (...args) {
export default function and (...args) {
// last argument is the handlebars options object
const params = args.slice(0, args.length - 1)
const valid = params.every((p) => Boolean(p))
Expand All @@ -11,5 +9,4 @@ function and (...args) {
return valid ? params[params.length - 1] : undefined
}

Handlebars.registerHelper('and', and)

10 changes: 2 additions & 8 deletions src/content/helpers/capitalize.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
// capitalize string helper
import Handlebars from 'handlebars'

function capitalize (str = '') {
export function capitalize (str = '') {
if (typeof str !== 'string') {
return ''
}

return str.charAt(0).toUpperCase() + str.slice(1)
}

Handlebars.registerHelper('capitalize', capitalize)

function capitalizeAll (str = '') {
export function capitalizeAll (str = '') {
if (typeof str !== 'string') {
return ''
}
Expand All @@ -20,5 +16,3 @@ function capitalizeAll (str = '') {
return capitalize(word)
})
}

Handlebars.registerHelper('capitalizeAll', capitalizeAll)
6 changes: 1 addition & 5 deletions src/content/helpers/choice.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
// legacy random choice helper
// {{ choice 'one, two, three' }}

import Handlebars from 'handlebars'

function choice (args) {
export default function choice (args) {
// split by comma and trim
args = args.split(',').map((a) => a.trim())
return args[Math.floor(Math.random() * args.length)]
}

Handlebars.registerHelper('choice', choice)
7 changes: 1 addition & 6 deletions src/content/helpers/compare.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// compare helper
import Handlebars from 'handlebars'

function compare (operator = '', ...args) {
export default function compare (operator = '', ...args) {
// last argument is the handlebars options object
const params = args.slice(0, args.length - 1)

Expand Down Expand Up @@ -37,6 +35,3 @@ function compare (operator = '', ...args) {
}
})
}

Handlebars.registerHelper('compare', compare)

6 changes: 1 addition & 5 deletions src/content/helpers/date.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// Legacy date helper,
// will be deprecated in the future.
import Handlebars from 'handlebars'
import moment from 'moment'

// format a date using Moment.js
// http://momentjs.com/
// moment syntax example: moment(Date("2011-07-18T15:50:52")).format("MMMM YYYY")
// usage: {{date '+7' 'days' "DD MMMM"}} -> 13 December
// usage: {{date '-7' 'days' "DD MMMM YYYY"}} -> 29 November 2015
function date (literal, unit, format) {
export default function date (literal, unit, format) {
format = typeof(format) === 'string' ? format : 'YYYY-MM-DD'
unit = typeof(unit) === 'string' ? unit : 'days'

Expand All @@ -20,6 +19,3 @@ function date (literal, unit, format) {

return moment().add(literal, unit).format(format)
}

Handlebars.registerHelper('date', date)

7 changes: 1 addition & 6 deletions src/content/helpers/domain.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// domain handlebars helper
import Handlebars from 'handlebars'

function underscored (str) {
return str.replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/[-\s]+/g, '_').toLowerCase().trim()
}
Expand All @@ -15,7 +13,7 @@ function humanize (str) {
return titleize(underscored(str).replace(/_id$/, '').replace(/_/g, ' '))
}

function domain (text) {
export default function domain (text) {
if (!text || typeof text !== 'string') {
return text
}
Expand All @@ -28,6 +26,3 @@ function domain (text) {
var domain = tld.split('.')[0] // AWESOME-sweet-bakery
return humanize(domain) // Awesome Sweet Bakery
}

Handlebars.registerHelper('domain', domain)

7 changes: 1 addition & 6 deletions src/content/helpers/list.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// general purpose list helper
// exposes all methods on the Array object
import Handlebars from 'handlebars'

function list (arr = [], method, ...args) {
export default function list (arr = [], method, ...args) {
// convenience method to convert strings to arrays.
// avoids having to use string split before using list methods.
if (typeof arr === 'string') {
Expand All @@ -21,6 +19,3 @@ function list (arr = [], method, ...args) {
const params = args.slice(0, args.length - 1)
return Array.prototype[method].apply(arr, params)
}

Handlebars.registerHelper('list', list)

5 changes: 1 addition & 4 deletions src/content/helpers/moment.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Handlebars from 'handlebars'
import moment from 'moment'

function helperMoment (dateParam, options) {
export default function helperMoment (dateParam, options) {
// check if str is a valid date
let dateString
if (typeof dateParam === 'string' && moment(dateParam).isValid()) {
Expand Down Expand Up @@ -69,5 +68,3 @@ function helperMoment (dateParam, options) {

return date[display].apply(date, displayParams)
}

Handlebars.registerHelper('moment', helperMoment)
7 changes: 1 addition & 6 deletions src/content/helpers/or.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
// conditional or helper
import Handlebars from 'handlebars'

function or (...args) {
export default function or (...args) {
// last argument is the handlebars options object
const params = args.slice(0, args.length - 1)
return params.find((p) => Boolean(p))
}

Handlebars.registerHelper('or', or)

Loading

0 comments on commit e7a4ee8

Please sign in to comment.