Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement options page to persist Prettier config #56

Merged
merged 40 commits into from
Oct 29, 2019
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
8ebbda8
Generate a new React app for the options page
nickmccurdy Oct 17, 2019
12deda1
Fix issues loading options page in extension
nickmccurdy Oct 17, 2019
8231626
Merge branch 'master' into options
nickmccurdy Oct 17, 2019
f40c39d
Remove CRA features we don't need
nickmccurdy Oct 21, 2019
d2fae29
Add initial options based on Code Sandbox
nickmccurdy Oct 21, 2019
f3cf1e5
Set initial values based on default options
nickmccurdy Oct 22, 2019
41c4a62
Upgrade Formik to fix initial values of checkboxes
nickmccurdy Oct 22, 2019
e32c6c6
Persist options with chrome.storage.sync
nickmccurdy Oct 22, 2019
76ddfad
Replace Formik with custom form handling
nickmccurdy Oct 22, 2019
ebb4d42
Use options for formatting
nickmccurdy Oct 22, 2019
bb80a9e
Fix number options being saved as strings
nickmccurdy Oct 22, 2019
8064e58
Merge branch 'master' into options
nickmccurdy Oct 23, 2019
9fe5a41
Fix ESLint for CRA files
nickmccurdy Oct 23, 2019
8d52005
Use recommended config from eslint-plugin-react
nickmccurdy Oct 23, 2019
735f598
Remove setOptions from dependencies
nickmccurdy Oct 23, 2019
1728726
Add eslint-plugin-react-hooks (used by CRA)
nickmccurdy Oct 23, 2019
fd15bff
Merge branch 'master' into options
nickmccurdy Oct 23, 2019
cd3442c
Update dependency version syntax
nickmccurdy Oct 23, 2019
cba3015
Remove old and unused options.html
nickmccurdy Oct 24, 2019
cc961b3
Add React app to original webpack config
nickmccurdy Oct 24, 2019
ba0e327
Move options page into extension/src/options
nickmccurdy Oct 24, 2019
a86a9c8
Rename main.js to content.js
nickmccurdy Oct 24, 2019
aef9f04
Load CSS directly from HTML (not JS/webpack)
nickmccurdy Oct 24, 2019
18f9e91
Merge App.js into index.js
nickmccurdy Oct 24, 2019
0be7bd8
Error on exhaustive-deps
nickmccurdy Oct 25, 2019
a7b312c
Configure react-devtools
nickmccurdy Oct 27, 2019
2bf6862
Revert "Configure react-devtools"
nickmccurdy Oct 27, 2019
963090f
Import react-devtools directly
nickmccurdy Oct 28, 2019
fd8150a
Disable source maps to fix CSP in development
nickmccurdy Oct 28, 2019
7b64d57
Merge branch 'master' into options
nickmccurdy Oct 29, 2019
d0d1f36
Add React devtools usage to readme
nickmccurdy Oct 29, 2019
ce0a44d
Hide require.extensions warning
nickmccurdy Oct 29, 2019
f357b7d
Make installs faster by not building automatically
nickmccurdy Oct 29, 2019
6e7f43e
Remove extra whitespace in script
nickmccurdy Oct 29, 2019
11ee886
Only minimize code in production for performance
nickmccurdy Oct 29, 2019
755268a
Only import react-devtools in development
nickmccurdy Oct 29, 2019
fdc53fa
Merge branch 'master' into options
nickmccurdy Oct 29, 2019
d0ded2f
Replace window.chrome with just chrome
nickmccurdy Oct 29, 2019
2c37194
Scope options page storage to an options property
nickmccurdy Oct 29, 2019
111660e
Credit the Code Sandbox source in a comment
nickmccurdy Oct 29, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 12 additions & 8 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@
"env": {
"node": true
},
"plugins": ["prettier"],
"extends": ["prettier"],
"plugins": ["prettier", "react-hooks"],
"extends": ["plugin:react/recommended", "prettier"],
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
"sourceType": "module"
},
"rules": {
"curly": "error",
Expand Down Expand Up @@ -52,7 +49,9 @@
}
],
"sort-vars": "error",
"strict": ["error", "global"]
"strict": ["error", "global"],
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
nickmccurdy marked this conversation as resolved.
Show resolved Hide resolved
},
"overrides": [
{
Expand All @@ -61,5 +60,10 @@
"browser": true
}
}
]
],
"settings": {
"react": {
"version": "detect"
}
}
}
3 changes: 2 additions & 1 deletion extension/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"options_page": "options.html",
"options_page": "options/public/index.html",
"permissions": ["storage"],
"content_scripts": [
{
"matches": ["https://stackoverflow.com/*", "https://github.com/*"],
Expand Down
7 changes: 0 additions & 7 deletions extension/options.html

This file was deleted.

12 changes: 12 additions & 0 deletions extension/options/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
nickmccurdy marked this conversation as resolved.
Show resolved Hide resolved
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Prettier Options</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="../../dist/options.js"></script>
</body>
</html>
140 changes: 140 additions & 0 deletions extension/options/src/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import React, { useEffect, useState } from "react";
nickmccurdy marked this conversation as resolved.
Show resolved Hide resolved

const defaultOptions = {
arrowParens: "avoid",
bracketSpacing: true,
jsxBracketSameLine: false,
printWidth: 80,
semi: true,
singleQuote: false,
tabWidth: 2,
trailingComma: "none",
useTabs: false
};

function App() {
const [options, setOptions] = useState();

useEffect(() => {
window.chrome.storage.sync.get(defaultOptions, setOptions);
nickmccurdy marked this conversation as resolved.
Show resolved Hide resolved
kaicataldo marked this conversation as resolved.
Show resolved Hide resolved
}, []);

useEffect(() => {
if (options) {
kaicataldo marked this conversation as resolved.
Show resolved Hide resolved
window.chrome.storage.sync.set(options);
}
}, [options]);

function handleChange({ target: { checked, name, type, value } }) {
setOptions({
...options,
[name]:
type === "checkbox"
? checked
: type === "number"
? parseInt(value)
: value
});
}

return options ? (
kaicataldo marked this conversation as resolved.
Show resolved Hide resolved
<>
<h1>
<a href="https://prettier.io/docs/en/options.html">Prettier Options</a>
nickmccurdy marked this conversation as resolved.
Show resolved Hide resolved
</h1>
<hr />
<label>Print width</label>
<input
type="number"
name="printWidth"
value={options.printWidth}
onChange={handleChange}
/>
<p>Specify the line length that the printer will wrap on.</p>
<hr />
<label>Tab width</label>
<input
type="number"
name="tabWidth"
value={options.tabWidth}
onChange={handleChange}
/>
<p>Specify the number of spaces per indentation-level.</p>
<hr />
<label>Use tabs</label>
<input
type="checkbox"
name="useTabs"
checked={options.useTabs}
onChange={handleChange}
/>
<p>Indent lines with tabs instead of spaces.</p>
<hr />
<label>Semicolons</label>
<input
type="checkbox"
name="semi"
checked={options.semi}
onChange={handleChange}
/>
<p>Print semicolons at the ends of statements.</p>
<hr />
<label>Use single quotes</label>
<input
type="checkbox"
name="singleQuote"
checked={options.singleQuote}
onChange={handleChange}
/>
<p>
Use {"'"}single{"'"} quotes instead of {'"'}double{'"'} quotes.
</p>
<hr />
<label>Trailing commas</label>
<select
name="trailingComma"
value={options.trailingComma}
onChange={handleChange}
>
<option>none</option>
<option>es5</option>
<option>all</option>
</select>
<p>Print trailing commas wherever possible.</p>
<hr />
<label>Bracket spacing</label>
<input
type="checkbox"
name="bracketSpacing"
checked={options.bracketSpacing}
onChange={handleChange}
/>
<p>Print spaces between brackets in object literals.</p>
<hr />
<label>JSX Brackets</label>
<input
type="checkbox"
name="jsxBracketSameLine"
checked={options.jsxBracketSameLine}
onChange={handleChange}
/>
<p>
Put the `{">"}` of a multi-line JSX element at the end of the last line
instead of being alone on the next line.
</p>
<hr />
<label>Arrow Function Parentheses</label>
<select
name="arrowParens"
value={options.arrowParens}
onChange={handleChange}
>
<option>avoid</option>
<option>always</option>
</select>
<p>Include parentheses around a sole arrow function parameter.</p>
</>
) : null;
}

export default App;
13 changes: 13 additions & 0 deletions extension/options/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
6 changes: 6 additions & 0 deletions extension/options/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import "./index.css";
import App from "./App";
import React from "react";
import ReactDOM from "react-dom";

ReactDOM.render(<App />, document.getElementById("root"));
16 changes: 10 additions & 6 deletions extension/src/content/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import parserTypescript from "prettier/parser-typescript";
import parserYaml from "prettier/parser-yaml";
import prettier from "prettier/standalone";

function init() {
function init(options) {
const prettierPlugins = [
parserAngular,
parserBabylon,
Expand Down Expand Up @@ -136,7 +136,8 @@ function init() {
event.preventDefault();
const formattedText = prettier.format(textArea.value, {
parser: "markdown",
plugins: prettierPlugins
plugins: prettierPlugins,
...options
});
textArea.focus();
textArea.select();
Expand Down Expand Up @@ -390,7 +391,8 @@ function init() {
try {
formattedSnippet = prettier.format(snippet, {
parser: PARSERS_LANG_MAP[lang],
plugins: prettierPlugins
plugins: prettierPlugins,
...options
});
} catch {}

Expand Down Expand Up @@ -418,7 +420,8 @@ function init() {
try {
formattedText = prettier.format(codeLines.join("\n"), {
parser: PARSERS_LANG_MAP[lang],
plugins: prettierPlugins
plugins: prettierPlugins,
...options
});
} catch {
return;
Expand Down Expand Up @@ -449,7 +452,8 @@ function init() {

inputEl.value = prettier.format(inputEl.value, {
parser: "markdown",
plugins: prettierPlugins
plugins: prettierPlugins,
...options
});
inputEl.focus();
});
Expand Down Expand Up @@ -482,4 +486,4 @@ function init() {
}
}

init();
chrome.storage.sync.get(init);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't necessarily a blocker (we can fix this later if need be), but this only runs when the page is loaded, correct? One use case this might not handle very gracefully is when a GitHub/StackOverflow tab is open and someone goes and changes the settings (they wouldn't go into effect until the page is reloaded).

We could probably fix this by reading from chrome storage each time Prettier formats (again, does not need to be a blocker to land this, just want to make sure it's commented here for posterity).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot to implement this, but we should be able to use chrome.storage.onChanged.addListener to subscribe to option updates in the content script.

11 changes: 10 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,24 @@
"zip": "cd extension && jszip-cli add . -i .DS_Store -o ../extension.zip -f"
},
"dependencies": {
"prettier": "1.18.2"
"prettier": "1.18.2",
"react": "16.11.0",
"react-dom": "16.11.0"
},
"devDependencies": {
"@babel/core": "7.6.4",
"@babel/preset-react": "7.6.3",
"@ffflorian/jszip-cli": "3.0.2",
"babel-loader": "8.0.6",
"css-loader": "3.2.0",
"eslint": "6.5.1",
"eslint-config-prettier": "6.4.0",
"eslint-plugin-prettier": "3.1.1",
"eslint-plugin-react": "7.16.0",
"eslint-plugin-react-hooks": "2.2.0",
"husky": "3.0.9",
"lint-staged": "9.4.2",
"style-loader": "1.0.0",
"webpack": "4.41.2",
"webpack-cli": "3.3.9"
},
Expand Down
24 changes: 22 additions & 2 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,29 @@ const path = require("path");
const TerserPlugin = require("terser-webpack-plugin"); // included as a dependency of webpack

module.exports = {
entry: "./extension/src/content/index.js",
entry: {
main: "./extension/src/content/index.js",
options: "./extension/options/src/index.js"
},
mode: "production",
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
exclude: /node_modules/,
test: /\.js$/,
use: {
loader: "babel-loader",
nickmccurdy marked this conversation as resolved.
Show resolved Hide resolved
options: {
presets: ["@babel/preset-react"]
}
}
}
]
},
optimization: {
minimize: true,
minimizer: [
Expand All @@ -18,7 +39,6 @@ module.exports = {
]
},
output: {
filename: "main.js",
path: path.resolve(__dirname, "extension/dist")
},
performance: {
Expand Down