diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..f91e635
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,6 @@
+{
+ "arrowParens": "avoid",
+ "proseWrap": "preserve",
+ "singleQuote": true,
+ "tabWidth": 2
+}
diff --git a/README.md b/README.md
index 99a5bb0..66acb13 100644
--- a/README.md
+++ b/README.md
@@ -2,11 +2,11 @@
---
-__Medium TOC__ is a simple tool to generate tables of contents for Medium articles. Check it out: [www.mediumtoc.com](https://www.mediumtoc.com)
+**Medium TOC** is a simple tool to generate tables of contents for Medium articles. Check it out: [www.mediumtoc.com](https://www.mediumtoc.com)
-| ![starting](https://github.com/adamisntdead/medium-toc/blob/master/resources/start.png?raw=true) | ![resulting](https://github.com/adamisntdead/medium-toc/blob/master/resources/result.png?raw=true) |
-|---------|---------|
-| Enter A URL | Get The Contents |
+| ![starting](https://github.com/adamisntdead/medium-toc/blob/master/resources/start.png?raw=true) | ![resulting](https://github.com/adamisntdead/medium-toc/blob/master/resources/result.png?raw=true) |
+| ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- |
+| Enter A URL | Get The Contents |
## Installation
diff --git a/backend/app.js b/backend/app.js
index 181ddf8..ced7aea 100644
--- a/backend/app.js
+++ b/backend/app.js
@@ -1,25 +1,24 @@
-const express = require("express");
-const cors = require("cors");
-const createTOC = require("./lib/create-toc");
+const express = require('express');
+const cors = require('cors');
+const createTOC = require('./lib/create-toc');
-const app = express()
-app.use(cors())
+const app = express();
+app.use(cors());
app.get('/', (req, res) => {
- const url = 'https://' + req.query.url
+ const url = 'https://' + req.query.url;
createTOC(url)
- .then(results => {
- res.send({
- url,
- results
+ .then(results => {
+ res.send({
+ url,
+ results,
+ });
})
- })
- .catch(error => {
- res.sendStatus(502)
- })
-
-})
+ .catch(error => {
+ res.sendStatus(502);
+ });
+});
app.listen(process.env.PORT || 8080, () => {
- console.log('Server Started')
-})
\ No newline at end of file
+ console.log('Server Started');
+});
diff --git a/backend/lib/create-toc.js b/backend/lib/create-toc.js
index d79d87a..7d85a5c 100644
--- a/backend/lib/create-toc.js
+++ b/backend/lib/create-toc.js
@@ -1,17 +1,17 @@
-const rp = require("request-promise");
-const cheerio = require("cheerio");
+const rp = require('request-promise');
+const cheerio = require('cheerio');
function createTOC(uri) {
return rp(uri)
.then(body => cheerio.load(body))
.then($ => {
// Get The Article ID
- const articleId = uri.substring(uri.lastIndexOf("-") + 1);
+ const articleId = uri.substring(uri.lastIndexOf('-') + 1);
// Get the headings
let results = [];
- $("body")
- .find("h2, h3, h4, h5, h6")
+ $('body')
+ .find('h2, h3, h4, h5, h6')
.each((_, elem) => {
const title = elem.children[0].data;
const headingCode = elem.attribs.id;
@@ -25,7 +25,7 @@ function createTOC(uri) {
results.push({
title,
headingCode,
- link
+ link,
});
});
diff --git a/config/webpack.config.dev.js b/config/webpack.config.dev.js
index 740a444..f96650e 100644
--- a/config/webpack.config.dev.js
+++ b/config/webpack.config.dev.js
@@ -84,7 +84,6 @@ module.exports = {
// for React Native Web.
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
alias: {
-
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
@@ -115,7 +114,6 @@ module.exports = {
options: {
formatter: eslintFormatter,
eslintPath: require.resolve('eslint'),
-
},
loader: require.resolve('eslint-loader'),
},
@@ -144,7 +142,6 @@ module.exports = {
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
-
// This is a feature of `babel-loader` for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
diff --git a/config/webpack.config.prod.js b/config/webpack.config.prod.js
index f1f7aac..9338693 100644
--- a/config/webpack.config.prod.js
+++ b/config/webpack.config.prod.js
@@ -90,8 +90,8 @@ module.exports = {
// for React Native Web.
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
alias: {
- "react": "preact-compat",
- "react-dom": "preact-compat",
+ react: 'preact-compat',
+ 'react-dom': 'preact-compat',
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
@@ -122,7 +122,6 @@ module.exports = {
options: {
formatter: eslintFormatter,
eslintPath: require.resolve('eslint'),
-
},
loader: require.resolve('eslint-loader'),
},
@@ -150,7 +149,6 @@ module.exports = {
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
-
compact: true,
},
},
diff --git a/config/webpackDevServer.config.js b/config/webpackDevServer.config.js
index f12d315..94d6da1 100644
--- a/config/webpackDevServer.config.js
+++ b/config/webpackDevServer.config.js
@@ -9,7 +9,7 @@ const paths = require('./paths');
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const host = process.env.HOST || '0.0.0.0';
-module.exports = function(proxy, allowedHost) {
+module.exports = function (proxy, allowedHost) {
return {
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
// websites from potentially accessing local content through DNS rebinding:
diff --git a/package.json b/package.json
index bd1ee5d..4874768 100644
--- a/package.json
+++ b/package.json
@@ -47,10 +47,13 @@
"webpack-manifest-plugin": "1.3.2",
"whatwg-fetch": "2.0.3"
},
- "devDependencies": {},
+ "devDependencies": {
+ "prettier": "^2.0.4"
+ },
"scripts": {
- "start": "node scripts/start.js",
"build": "node scripts/build.js",
+ "format": "prettier --write '**/*.{css,md,js}'",
+ "start": "node scripts/start.js",
"test": "node scripts/test.js --env=jsdom"
},
"jest": {
diff --git a/scripts/start.js b/scripts/start.js
index c5acbe5..da82989 100644
--- a/scripts/start.js
+++ b/scripts/start.js
@@ -92,8 +92,8 @@ choosePort(HOST, DEFAULT_PORT)
openBrowser(urls.localUrlForBrowser);
});
- ['SIGINT', 'SIGTERM'].forEach(function(sig) {
- process.on(sig, function() {
+ ['SIGINT', 'SIGTERM'].forEach(function (sig) {
+ process.on(sig, function () {
devServer.close();
process.exit();
});
diff --git a/scripts/test.js b/scripts/test.js
index 399bfd3..736f166 100644
--- a/scripts/test.js
+++ b/scripts/test.js
@@ -23,5 +23,4 @@ if (!process.env.CI && argv.indexOf('--coverage') < 0) {
argv.push('--watch');
}
-
jest.run(argv);
diff --git a/src/App.css b/src/App.css
index 9aa00c7..b71b642 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,4 +1,5 @@
-html, body {
+html,
+body {
padding: 0;
margin: 0;
box-sizing: border-box;
@@ -25,7 +26,7 @@ html, body {
h1 {
font-family: 'Times New Roman', Times, serif;
font-size: 3.5rem;
- color: #4A4A4A;
+ color: #4a4a4a;
letter-spacing: 1.27px;
font-weight: bold;
diff --git a/src/App.js b/src/App.js
index 3043949..5b7ca5d 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,10 +1,10 @@
-import React, { Component } from "react";
-import Loadable from "react-loading-overlay";
+import React, { Component } from 'react';
+import Loadable from 'react-loading-overlay';
-import Instruction from "./instruction/Instruction.js";
-import Display from "./display/Display";
-import getHeadings from "./api/get-headings";
-import "./App.css";
+import Instruction from './instruction/Instruction.js';
+import Display from './display/Display';
+import getHeadings from './api/get-headings';
+import './App.css';
class App extends Component {
constructor(props) {
@@ -14,16 +14,15 @@ class App extends Component {
message:
"Just enter the public url of a medium article and we'll create a table of contents.",
loading: false,
- results: []
+ results: [],
};
this.handleSubmit = this.handleSubmit.bind(this);
}
-
handleSubmit(url) {
this.setState({
- loading: true
+ loading: true,
});
getHeadings(url)
@@ -33,7 +32,7 @@ class App extends Component {
message:
"Couldn't find headings for this URL. Please check it is correct, and is a Medium article. If the article is a draft, use the 'share' url.",
error: true,
- loading: false
+ loading: false,
});
return;
}
@@ -41,17 +40,17 @@ class App extends Component {
this.setState({
error: false,
message:
- "Done! Just copy and paste whats below into your Medium article!",
+ 'Done! Just copy and paste whats below into your Medium article!',
results: results.results,
- loading: false
+ loading: false,
});
})
.catch(error => {
this.setState({
message:
- "There was an error fetching content. Make sure the URL is correct and you are connected to the internet.",
+ 'There was an error fetching content. Make sure the URL is correct and you are connected to the internet.',
error: true,
- loading: false
+ loading: false,
});
});
}
@@ -66,7 +65,9 @@ class App extends Component {
text="Creating Your Table Of Contents..."
>
-
+
{
- const div = document.createElement("div");
+it('renders without crashing', () => {
+ const div = document.createElement('div');
ReactDOM.render( , div);
ReactDOM.unmountComponentAtNode(div);
});
diff --git a/src/api/get-headings.js b/src/api/get-headings.js
index c1f0778..b2f84da 100644
--- a/src/api/get-headings.js
+++ b/src/api/get-headings.js
@@ -1,8 +1,8 @@
-const apiUrl = "https://toc-backend-oirlqadtnt.now.sh";
+const apiUrl = 'https://toc-backend-oirlqadtnt.now.sh';
function getHeadings(url) {
- const urlPath = url.replace(/^(http|https):\/\//, "");
+ const urlPath = url.replace(/^(http|https):\/\//, '');
- return fetch(apiUrl + "?url=" + encodeURI(urlPath)).then(resp => resp.json());
+ return fetch(apiUrl + '?url=' + encodeURI(urlPath)).then(resp => resp.json());
}
export default getHeadings;
diff --git a/src/display/Display.js b/src/display/Display.js
index 0088229..451d01b 100644
--- a/src/display/Display.js
+++ b/src/display/Display.js
@@ -1,13 +1,13 @@
-import React from 'react'
-import TOC from "../toc/TOC";
-import UrlForm from "../form/Form";
+import React from 'react';
+import TOC from '../toc/TOC';
+import UrlForm from '../form/Form';
-const Display = ({results, handleSubmit}) => {
+const Display = ({ results, handleSubmit }) => {
if (results.length > 0) {
return ;
} else {
return ;
}
-}
+};
export default Display;
diff --git a/src/form/Form.css b/src/form/Form.css
index 44ac988..e7610ba 100644
--- a/src/form/Form.css
+++ b/src/form/Form.css
@@ -1,6 +1,6 @@
.button {
display: block;
- border: 1px solid #00AB6C;
+ border: 1px solid #00ab6c;
border-radius: 8px;
background-color: transparent;
font-size: 24px;
@@ -22,108 +22,132 @@
margin: auto;
}
-* {
- box-sizing:border-box;
+* {
+ box-sizing: border-box;
}
/* form starting stylings ------------------------------- */
-.group {
- position:relative;
- margin-bottom:45px;
+.group {
+ position: relative;
+ margin-bottom: 45px;
}
-input {
- font-size:18px;
- padding:10px 10px 10px 5px;
- display:block;
- width:100%;
- border:none;
- border-bottom:1px solid #757575;
-}
-input:focus { outline:none; }
+input {
+ font-size: 18px;
+ padding: 10px 10px 10px 5px;
+ display: block;
+ width: 100%;
+ border: none;
+ border-bottom: 1px solid #757575;
+}
+input:focus {
+ outline: none;
+}
input:invalid {
box-shadow: none;
}
/* LABEL ======================================= */
-label {
- color:#999;
- font-size:18px;
- font-weight:normal;
- position:absolute;
- pointer-events:none;
- left:5px;
- top:10px;
- transition:0.2s ease all;
- -moz-transition:0.2s ease all;
- -webkit-transition:0.2s ease all;
+label {
+ color: #999;
+ font-size: 18px;
+ font-weight: normal;
+ position: absolute;
+ pointer-events: none;
+ left: 5px;
+ top: 10px;
+ transition: 0.2s ease all;
+ -moz-transition: 0.2s ease all;
+ -webkit-transition: 0.2s ease all;
}
/* active state */
-input:focus ~ label, input:valid ~ label {
- top:-20px;
- font-size:14px;
- color:#00AB6C;
+input:focus ~ label,
+input:valid ~ label {
+ top: -20px;
+ font-size: 14px;
+ color: #00ab6c;
}
/* BOTTOM BARS ================================= */
-.bar { position:relative; display:block; width:100%; }
-.bar:before, .bar:after {
- content:'';
- height:2px;
- width:0;
- bottom:1px;
- position:absolute;
- background:#00AB6C;
- transition:0.2s ease all;
- -moz-transition:0.2s ease all;
- -webkit-transition:0.2s ease all;
+.bar {
+ position: relative;
+ display: block;
+ width: 100%;
+}
+.bar:before,
+.bar:after {
+ content: '';
+ height: 2px;
+ width: 0;
+ bottom: 1px;
+ position: absolute;
+ background: #00ab6c;
+ transition: 0.2s ease all;
+ -moz-transition: 0.2s ease all;
+ -webkit-transition: 0.2s ease all;
}
.bar:before {
- left:50%;
+ left: 50%;
}
.bar:after {
- right:50%;
+ right: 50%;
}
/* active state */
-input:focus ~ .bar:before, input:focus ~ .bar:after {
- width:50%;
+input:focus ~ .bar:before,
+input:focus ~ .bar:after {
+ width: 50%;
}
/* HIGHLIGHTER ================================== */
.highlight {
- position:absolute;
- height:60%;
- width:100px;
- top:25%;
- left:0;
- pointer-events:none;
- opacity:0.5;
+ position: absolute;
+ height: 60%;
+ width: 100px;
+ top: 25%;
+ left: 0;
+ pointer-events: none;
+ opacity: 0.5;
}
/* active state */
input:focus ~ .highlight {
- -webkit-animation:inputHighlighter 0.3s ease;
- -moz-animation:inputHighlighter 0.3s ease;
- animation:inputHighlighter 0.3s ease;
+ -webkit-animation: inputHighlighter 0.3s ease;
+ -moz-animation: inputHighlighter 0.3s ease;
+ animation: inputHighlighter 0.3s ease;
}
/* ANIMATIONS ================ */
@-webkit-keyframes inputHighlighter {
- from { background:#00AB6C; }
- to { width:0; background:transparent; }
+ from {
+ background: #00ab6c;
+ }
+ to {
+ width: 0;
+ background: transparent;
+ }
}
@-moz-keyframes inputHighlighter {
- from { background:#00AB6C; }
- to { width:0; background:transparent; }
+ from {
+ background: #00ab6c;
+ }
+ to {
+ width: 0;
+ background: transparent;
+ }
}
@keyframes inputHighlighter {
- from { background:#00AB6C; }
- to { width:0; background:transparent; }
+ from {
+ background: #00ab6c;
+ }
+ to {
+ width: 0;
+ background: transparent;
+ }
}
.input {
margin-top: 100px;
-}
\ No newline at end of file
+}
diff --git a/src/form/Form.js b/src/form/Form.js
index a3afb03..f64106d 100644
--- a/src/form/Form.js
+++ b/src/form/Form.js
@@ -1,10 +1,10 @@
-import React, { Component } from "react";
-import "./Form.css";
+import React, { Component } from 'react';
+import './Form.css';
class Form extends Component {
constructor(props) {
super(props);
- this.state = { value: "" };
+ this.state = { value: '' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
@@ -34,7 +34,9 @@ class Form extends Component {
Article URL
- Go
+
+ Go
+
);
}
diff --git a/src/index.js b/src/index.js
index 7f76cb9..fae3e35 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,8 +1,8 @@
-import React from "react";
-import ReactDOM from "react-dom";
-import "./index.css";
-import App from "./App";
-import registerServiceWorker from "./registerServiceWorker";
+import React from 'react';
+import ReactDOM from 'react-dom';
+import './index.css';
+import App from './App';
+import registerServiceWorker from './registerServiceWorker';
-ReactDOM.render( , document.getElementById("root"));
+ReactDOM.render( , document.getElementById('root'));
registerServiceWorker();
diff --git a/src/instruction/Instruction.css b/src/instruction/Instruction.css
index 537405a..c3af47b 100644
--- a/src/instruction/Instruction.css
+++ b/src/instruction/Instruction.css
@@ -2,7 +2,7 @@
font-family: Helvetica, sans-serif;
font-weight: 300;
font-size: 2rem;
- color: #AEAEAE;
+ color: #aeaeae;
letter-spacing: 0.71px;
width: 100;
}
diff --git a/src/instruction/Instruction.js b/src/instruction/Instruction.js
index 294394d..f51205c 100644
--- a/src/instruction/Instruction.js
+++ b/src/instruction/Instruction.js
@@ -1,10 +1,18 @@
-import React, { Component } from "react";
-import "./Instruction.css";
+import React, { Component } from 'react';
+import './Instruction.css';
-const extraHelp = Get more help.
+const extraHelp = (
+
+ Get more help.
+
+);
-const Instruction = ({error, message}) =>
-
{message} {(() => error ? extraHelp : '')()}
+const Instruction = ({ error, message }) => (
+
+
+ {message} {(() => (error ? extraHelp : ''))()}
+
+);
export default Instruction;
diff --git a/src/registerServiceWorker.js b/src/registerServiceWorker.js
index a682a17..a3e6c0c 100644
--- a/src/registerServiceWorker.js
+++ b/src/registerServiceWorker.js
@@ -9,9 +9,9 @@
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
- window.location.hostname === "localhost" ||
+ window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
- window.location.hostname === "[::1]" ||
+ window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
@@ -19,7 +19,7 @@ const isLocalhost = Boolean(
);
export default function register() {
- if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {
+ if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
if (publicUrl.origin !== window.location.origin) {
@@ -29,7 +29,7 @@ export default function register() {
return;
}
- window.addEventListener("load", () => {
+ window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
@@ -40,8 +40,8 @@ export default function register() {
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
- "This web app is being served cache-first by a service " +
- "worker. To learn more, visit https://goo.gl/SC7cgQ"
+ 'This web app is being served cache-first by a service ' +
+ 'worker. To learn more, visit https://goo.gl/SC7cgQ'
);
});
} else {
@@ -59,25 +59,25 @@ function registerValidSW(swUrl) {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
- if (installingWorker.state === "installed") {
+ if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
- console.log("New content is available; please refresh.");
+ console.log('New content is available; please refresh.');
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
- console.log("Content is cached for offline use.");
+ console.log('Content is cached for offline use.');
}
}
};
};
})
.catch(error => {
- console.error("Error during service worker registration:", error);
+ console.error('Error during service worker registration:', error);
});
}
@@ -88,7 +88,7 @@ function checkValidServiceWorker(swUrl) {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
- response.headers.get("content-type").indexOf("javascript") === -1
+ response.headers.get('content-type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
@@ -103,13 +103,13 @@ function checkValidServiceWorker(swUrl) {
})
.catch(() => {
console.log(
- "No internet connection found. App is running in offline mode."
+ 'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
- if ("serviceWorker" in navigator) {
+ if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
diff --git a/src/toc/TOC.css b/src/toc/TOC.css
index cc0e191..06cbb71 100644
--- a/src/toc/TOC.css
+++ b/src/toc/TOC.css
@@ -7,4 +7,4 @@
.results a {
color: #000;
-}
\ No newline at end of file
+}
diff --git a/src/toc/TOC.js b/src/toc/TOC.js
index 8ba0ffe..a45d6ec 100644
--- a/src/toc/TOC.js
+++ b/src/toc/TOC.js
@@ -1,5 +1,5 @@
-import React, { Component } from "react";
-import "./TOC.css";
+import React, { Component } from 'react';
+import './TOC.css';
class TOC extends Component {
render() {
@@ -8,7 +8,11 @@ class TOC extends Component {
Table of Contents
diff --git a/yarn.lock b/yarn.lock
index 07bf06f..43e4917 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4946,6 +4946,11 @@ preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
+prettier@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.4.tgz#2d1bae173e355996ee355ec9830a7a1ee05457ef"
+ integrity sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w==
+
pretty-bytes@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-4.0.2.tgz#b2bf82e7350d65c6c33aa95aaa5a4f6327f61cd9"