-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* [#59, #70] Make PR and branch name configurable Use configurable template strings for generating branch names, commit messages and shell commands. The configured template strings are compiled into formatter functions. Since browsers do not allow `eval`, `Function` etc. in web extensions (Content-Security Policy), we compile custom formatter functions that work without `eval`-ing and do not allow arbitrary JavaScript. While working on this feature, we implemented an initial spike using `lodash.template` (which uses `Function`). We decided not to pursue this approach, as it required sandboxing the templates — something that is not easily implemented in a way that works for different browsers. The formatted branch name, commit message and command is now attached to each ticket on load now instead of generating them on-the-fly. Notable changes: - Add custom template implementation and helper functions for formatting values used inside of templates (e.g. lowercase, dasherize, …) - Format tickets on load (attach output to tickets as "fmt" property) - Update webpack configurations for WebExtension API browsers and Safari - Generate an options.html and options.js for WebExtension-compatible browsers to allow the user to customize the templates - Add `Settings.plist` to implement template preferences in Safari - Create custom options.scss Additional changes: - Prevent chrome from checking whether it is the default browser when launching via chrome-launcher - Update "ExtractTextPlugin" filename template to automatically name extracted CSS after the entry: `[name].css` References: Safari Extensions Development Guide, "Settings and Local Storage": https://web.archive.org/web/20171215000607/https://developer.apple.com/library/content/documentation/Tools/Conceptual/SafariExtensionGuide/ExtensionSettings/ExtensionSettings.html Google Chrome: Using eval in Chrome Extensions. Safely.: https://web.archive.org/web/20171215234603/https://developer.chrome.com/extensions/sandboxingEval Google Chrome: Options: https://web.archive.org/web/20171216121413/https://developer.chrome.com/extensions/optionsV2 MDN web docs: Add-ons: Implement a settings page https://web.archive.org/web/20171216121512/https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Implement_a_settings_page * Simplify formatter creation * Extract and unit-test enhancer function * Update documentation * Bump version number for the next release
- Loading branch information
1 parent
4101b64
commit a612e07
Showing
42 changed files
with
980 additions
and
256 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"private": true, | ||
"version": "1.3.0", | ||
"version": "2.0.0", | ||
"name": "tickety-tick", | ||
"description": "A browser extension that helps you to create commit messages and branch names from story trackers.", | ||
"author": "Bodo Tasche <[email protected]>", | ||
|
@@ -18,13 +18,13 @@ | |
"watch:firefox-local": "npm run build:firefox-local -- --watch", | ||
"watch:safari": "npm run build:safari -- --watch", | ||
"open:chrome": "./script/open-in-chrome ./dist/chrome https://github.com/bitcrowd/tickety-tick", | ||
"open:firefox": "web-ext run --source-dir ./dist/firefox --pref startup.homepage_welcome_url=https://github.com/bitcrowd/tickety-tick", | ||
"open:firefox-local": "web-ext run --source-dir ./dist/firefox-local --pref startup.homepage_welcome_url=https://github.com/bitcrowd/tickety-tick", | ||
"bundle:chrome": "cross-env BUNDLE=true npm run build:chrome", | ||
"bundle:firefox": "cross-env BUNDLE=true npm run build:firefox", | ||
"lint": "eslint '**/*.{js,jsx}'", | ||
"test": "cross-env NODE_ENV=test jasmine", | ||
"test:coverage": "nyc npm test", | ||
"test:watch": "cross-env NODE_ENV=test nodemon --exec jasmine", | ||
"test:watch": "cross-env NODE_ENV=test nodemon --ext js,jsx,json --exec jasmine", | ||
"checks": "npm run lint && npm run test" | ||
}, | ||
"devDependencies": { | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import enhance from '../src/common/enhance'; | ||
import format, { defaults } from '../src/common/format'; | ||
|
||
describe('ticket enhancer', () => { | ||
const ticket = { | ||
id: 'BTC-042', | ||
title: 'Add more tests for src/common/format.js', | ||
type: 'enhancement', | ||
}; | ||
|
||
const templates = defaults; | ||
|
||
it('attaches format output to tickets as "fmt" property', () => { | ||
const formatter = format(templates); | ||
const enhancer = enhance(templates); | ||
|
||
expect(enhancer(ticket)).toEqual({ | ||
fmt: { | ||
branch: formatter.branch(ticket), | ||
commit: formatter.commit(ticket), | ||
command: formatter.command(ticket), | ||
}, | ||
...ticket, | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import format, { helpers } from '../src/common/format'; | ||
|
||
describe('ticket formatting', () => { | ||
const ticket = { | ||
id: 'BTC-042', | ||
title: 'Add more tests for src/common/format.js', | ||
type: 'enhancement', | ||
}; | ||
|
||
describe('default format', () => { | ||
const fmt = format({}); | ||
|
||
describe('commit', () => { | ||
it('includes ticket id and title', () => { | ||
const formatted = fmt.commit(ticket); | ||
expect(formatted).toBe(`[#${ticket.id}] ${ticket.title}`); | ||
}); | ||
}); | ||
|
||
describe('branch', () => { | ||
const { slugify } = helpers; | ||
|
||
it('includes ticket type, id and title', () => { | ||
const formatted = fmt.branch(ticket); | ||
expect(formatted).toBe(`${ticket.type}/${slugify(ticket.id)}-${slugify(ticket.title)}`); | ||
}); | ||
|
||
it('formats type to "feature" if not provided', () => { | ||
const typeless = { id: ticket.id, title: ticket.title }; | ||
const formatted = fmt.branch(typeless); | ||
expect(formatted).toBe(`feature/${slugify(ticket.id)}-${slugify(ticket.title)}`); | ||
}); | ||
}); | ||
|
||
describe('command', () => { | ||
const { shellquote } = helpers; | ||
|
||
it('includes the quoted branch name and commit message', () => { | ||
const branch = fmt.branch(ticket); | ||
const commit = fmt.commit(ticket); | ||
|
||
const formatted = fmt.command(ticket); | ||
|
||
expect(formatted).toBe(`git checkout -b ${shellquote(branch)}` | ||
+ ` && git commit --allow-empty -m ${shellquote(commit)}`); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('helpers', () => { | ||
describe('lowercase', () => { | ||
const { lowercase } = helpers; | ||
|
||
it('lowercases strings', () => { | ||
expect(lowercase('QUIET')).toBe('quiet'); | ||
}); | ||
}); | ||
|
||
describe('shellquote', () => { | ||
const { shellquote } = helpers; | ||
|
||
it('wraps the input in single-quotes', () => { | ||
expect(shellquote('echo "pwned"')).toBe('\'echo "pwned"\''); | ||
}); | ||
|
||
it('escapes any single-quotes in the input', () => { | ||
const input = 'you\'; echo aren\'t "pwned"'; | ||
const quoted = '\'you\'\\\'\'; echo aren\'\\\'\'t "pwned"\''; | ||
expect(shellquote(input)).toBe(quoted); | ||
}); | ||
}); | ||
|
||
describe('slugify', () => { | ||
const { slugify } = helpers; | ||
|
||
it('formats normal strings', () => { | ||
const formatted = slugify('hello'); | ||
expect(formatted).toBe('hello'); | ||
}); | ||
|
||
it('lowercases strings', () => { | ||
const formatted = slugify('Bitcrowd'); | ||
expect(formatted).toBe('bitcrowd'); | ||
}); | ||
|
||
it('formats spaces to dashes', () => { | ||
const formatted = slugify('hello bitcrowd'); | ||
expect(formatted).toBe('hello-bitcrowd'); | ||
}); | ||
|
||
it('formats special characters', () => { | ||
const formatted = slugify('Señor Dévèloper'); | ||
expect(formatted).toBe('senor-developer'); | ||
}); | ||
|
||
it('formats umlauts', () => { | ||
const formatted = slugify('äöüß'); | ||
expect(formatted).toBe('aeoeuess'); | ||
}); | ||
|
||
it('strips brackets', () => { | ||
const formatted = slugify('[#23] Add (more)'); | ||
expect(formatted).toBe('23-add-more'); | ||
}); | ||
|
||
it('formats slashes to dashes', () => { | ||
const formatted = slugify('src/js/format'); | ||
expect(formatted).toBe('src-js-format'); | ||
}); | ||
|
||
it('formats dots to dashes', () => { | ||
const formatted = slugify('format.js'); | ||
expect(formatted).toBe('format-js'); | ||
}); | ||
|
||
it('strips hashes', () => { | ||
const formatted = slugify('##23 #hashtag'); | ||
expect(formatted).toBe('23-hashtag'); | ||
}); | ||
}); | ||
|
||
describe('trim', () => { | ||
const { trim } = helpers; | ||
|
||
it('removes leading and trailing whitespace', () => { | ||
expect(trim('\t black\t\t ')).toBe('black'); | ||
}); | ||
}); | ||
|
||
describe('uppercase', () => { | ||
const { uppercase } = helpers; | ||
|
||
it('uppercases strings', () => { | ||
expect(uppercase('loud')).toBe('LOUD'); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.