Switch from JS Standard Style to plain ESLint

The codebase hasn't been checked against Standard in ages, so remove it
and configure plain ESLint and eslint-plugin-react instead. Also fix a
few small bugs discovered by ESLint and plugin-react.
This commit is contained in:
Christopher Gurnee 2022-10-20 22:02:57 +00:00
parent 763516b19d
commit 529162bec0
12 changed files with 255 additions and 2542 deletions

38
.eslintrc.json Normal file
View file

@ -0,0 +1,38 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended"
],
"overrides": [
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"plugins": [
"react"
],
"rules": {
"react/prop-types": "off",
"no-constant-condition": ["error", { "checkLoops": false }]
},
"settings": {
"react": {
"version": "detect"
},
"componentWrapperFunctions": [
"connect"
],
"linkComponents": [
{"name": "Link", "linkAttribute": "to"},
{"name": "NavLink", "linkAttribute": "to"}
]
}
}

2659
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -19,13 +19,11 @@
"url": "https://github.com/gurnec/removeddit/issues"
},
"homepage": "https://github.com/gurnec/removeddit#readme",
"standard": {
"parser": "babel-eslint"
},
"scripts": {
"start": "webpack-dev-server --mode development",
"build": "webpack --mode production",
"css": "sass -s compressed src/sass/index.sass >dist/main.css && sass -s compressed node_modules/css-toggle-switch/dist/toggle-switch-px.css >>dist/main.css"
"css": "sass -s compressed src/sass/index.sass >dist/main.css && sass -s compressed node_modules/css-toggle-switch/dist/toggle-switch-px.css >>dist/main.css",
"eslint": "eslint src/*.js 'src/api/**' 'src/pages/**'"
},
"dependencies": {
"@ali-tas/htmldiff-js": "^1.1.3",
@ -48,8 +46,8 @@
"babel-loader": "^8.2.5",
"css-toggle-switch": "^4.1.0",
"eslint": "^8.25.0",
"eslint-plugin-react": "^7.31.10",
"sass": "^1.55.0",
"standard": "^16.0.4",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1"

View file

@ -158,7 +158,7 @@ export const getComments = async (callback, threadID, maxComments, after = 0, be
return getComments(callback, threadID, maxComments, 1503014401, before)
firstChunk = false
const loadedAllComments = response.metadata.hasOwnProperty('total_results') ?
const loadedAllComments = Object.prototype.hasOwnProperty.call(response.metadata, 'total_results') ?
response.metadata.results_returned >= response.metadata.total_results :
comments.length < chunkSize/2
if (comments.length)

View file

@ -9,6 +9,8 @@ import About from './pages/about'
import Thread from './pages/thread'
import NotFound from './pages/404'
/* global __dirname */ // an eslint directive
ReactDOM.render(
<Provider>
<BrowserRouter basename={__dirname}>

View file

@ -1,5 +1,5 @@
import React from 'react'
export default () => (
<h2>404 Error - Not found</h2>
)
export default function NotFound() {
return <h2>404 Error - Not found</h2>
}

View file

@ -43,23 +43,23 @@ const About = props => {
</p>
<p>
Created by <a href='https://github.com/JubbeArt/'>Jesper Wrang</a> and
uses <a href='https://pushshift.io/'>Jason Baumgartner's service</a> for getting removed comments.
uses <a href='https://pushshift.io/'>Jason Baumgartner&apos;s service</a> for getting removed comments.
</p>
<h2 className='todo'>FAQ</h2>
<div id='delete' className={hash == '#delete' ? 'highlighted' : undefined}>
<b className='question'><Link to='/about#delete'>Q:</Link> I posted some sensitive information on Reddit. Can you delete this from your page?</b>
<p>
No, I can't remove anything myself since I am not the not the one storing all the deleted comments.
No, I can&apos;t remove anything myself since I am not the not the one storing all the deleted comments.
This is done by an external service called Pushshift.io.
If you want something sensitive removed permanently you should follow the <a href='https://www.reddit.com/r/pushshift/comments/pat409/online_removal_request_form_for_removal_requests/'>instructions here</a>.
</p>
</div>
<div id='removeddit' className={hash == '#removeddit' ? 'highlighted' : undefined}>
<b className='question'><Link to='/about#removeddit'>Q:</Link> Didn't this site used to be named Removeddit?</b>
<b className='question'><Link to='/about#removeddit'>Q:</Link> Didn&apos;t this site used to be named Removeddit?</b>
<p>
The Removeddit site stopped working a short while ago, and this site was made to partially replace it.
All creddit for the software which makes this site possible goes to the original author, Jesper Wrang.
Any bugs or problems are due to this site's operator.
Any bugs or problems are due to this site&apos;s operator.
In particular, Unddit does not currently support browsing subreddits, only specific posts.
</p>
</div>
@ -69,23 +69,23 @@ const About = props => {
This page is only possible because of the amazing work done by Jason.
His service <a href='https://pushshift.io/'>Pushshift.io</a> actively listens for new comments on Reddit and stores them in a database.
Then sites like Unddit and Reveddit can fetch these comments from Pushshift.
Unddit knows what comments Reddit shows (from Reddit's API) and what comments should be shown (from Pushshift's API).
Unddit knows what comments Reddit shows (from Reddit&apos;s API) and what comments should be shown (from Pushshift&apos;s API).
By comparing the comments from these 2 APIs, it can figure out what has been deleted and removed.
</p>
</div>
<div id='firefox' className={hash == '#firefox' ? 'highlighted' : undefined}>
<b className='question'><Link to='/about#firefox'>Q:</Link> Why doesn't it work in Firefox?</b>
<b className='question'><Link to='/about#firefox'>Q:</Link> Why doesn&apos;t it work in Firefox?</b>
<p>
If you have enabled Strict Enhanced Tracking Protection in Firefox, this will prevent Unddit from contacting Reddit's API.
If you have enabled Strict Enhanced Tracking Protection in Firefox, this will prevent Unddit from contacting Reddit&apos;s API.
Luckily there is an easy workaround.
Click on the shield symbol on the left side of the address bar, and then switch off Enhanced Tracking Protection for this site.
It will still be enabled for other sites.
</p>
</div>
<div id='edge' className={hash == '#edge' ? 'highlighted' : undefined}>
<b className='question'><Link to='/about#edge'>Q:</Link> Why doesn't it work in Edge?</b>
<b className='question'><Link to='/about#edge'>Q:</Link> Why doesn&apos;t it work in Edge?</b>
<p>
If you have enabled Strict Tracking Protection in Edge, this will prevent Unddit from contacting Reddit's API.
If you have enabled Strict Tracking Protection in Edge, this will prevent Unddit from contacting Reddit&apos;s API.
Luckily there is an easy workaround.
Click on the padlock symbol on the left side of the address bar, and then switch off Tracking Protection for this site.
It will still be enabled for other sites.
@ -101,18 +101,18 @@ const About = props => {
</p>
</div>
<div id='difference' className={hash == '#difference' ? 'highlighted' : undefined}>
<b className='question'><Link to='/about#difference'>Q:</Link> What's the difference between Ceddit and Removeddit/Unddit?</b>
<b className='question'><Link to='/about#difference'>Q:</Link> What&apos;s the difference between Ceddit and Removeddit/Unddit?</b>
<p>
Not much. Removeddit was created as a temporary replacement for Ceddit, at a time when Ceddit didn't work.
Not much. Removeddit was created as a temporary replacement for Ceddit, at a time when Ceddit didn&apos;t work.
Jesper thought this was necessary since he used Ceddit more then Reddit itself.
Months later Ceddit was fixed, but he didn't see any reason to remove what he had built.
Months later Ceddit was fixed, but he didn&apos;t see any reason to remove what he had built.
Today both sites live side by side and strive for the same goal.
</p>
<div>
There are some minor differences in them though:
<ul>
<li>
Ceddit respects user-made deletions while Removeddit does not. This decision was made early on and I feel like it's too late to change now.
Ceddit respects user-made deletions while Removeddit does not. This decision was made early on and I feel like it&apos;s too late to change now.
If I had created Removeddit today I might had thought more about what was right here.
</li>
<li>
@ -120,7 +120,7 @@ const About = props => {
Removeddit also uses significantly less JavaScript on the page which also should make the page load faster.
</li>
<li>
Ceddit provides user lookup while Removeddit doesn't.
Ceddit provides user lookup while Removeddit doesn&apos;t.
</li>
</ul>
</div>

View file

@ -4,7 +4,9 @@ import { prettyScore, prettyDate, prettyTimeDiff, exactDateTime, parse, redditTh
isDeleted, isRemoved, editedModes, editedTitles } from '../../utils'
import { Diff } from '@ali-tas/htmldiff-js'
export default (props) => {
const hasOwnProperty = Object.prototype.hasOwnProperty
const Post = (props) => {
if (!props.title) {
const permalink = `/r/${props.subreddit}/comments/${props.id}/`
return <div className={props.removed ? 'thread removed' : 'thread'} key={props.removed ? 'post-removed' : 'post-empty'}>
@ -59,15 +61,15 @@ export default (props) => {
const innerHTML = Array(editedModes.length)
if (props.removed && isRemoved(props.selftext)) {
if (!props.hasOwnProperty('retrieved_utc') && !props.hasOwnProperty('retrieved_on') || !props.hasOwnProperty('created_utc')) {
if (!hasOwnProperty.call(props, 'retrieved_utc') && !hasOwnProperty.call(props, 'retrieved_on') || !hasOwnProperty.call(props, 'created_utc')) {
innerHTML[editedModes.orig] = '<p>[removed too quickly to be archived]</p>'
} else {
const retrieved = props.hasOwnProperty('retrieved_utc') ? props.retrieved_utc : props.retrieved_on;
const retrieved = hasOwnProperty.call(props, 'retrieved_utc') ? props.retrieved_utc : props.retrieved_on;
innerHTML[editedModes.orig] = `<p>[removed within ${prettyTimeDiff(retrieved - props.created_utc)}]</p>`
}
} else if (props.selftext && (props.is_self || !isDeleted(props.selftext))) {
innerHTML[editedModes.orig] = parse(props.selftext)
if (props.hasOwnProperty('edited_selftext')) {
if (hasOwnProperty.call(props, 'edited_selftext')) {
innerHTML[editedModes.edited] = parse(props.edited_selftext)
innerHTML[editedModes.rich] = Diff.execute(innerHTML[editedModes.orig], innerHTML[editedModes.edited])
}
@ -83,7 +85,7 @@ export default (props) => {
<Link to={props.permalink} replace={props.isLocFullPost}>{props.num_comments}&nbsp;comments</Link>&nbsp;
<a href={`https://www.reddit.com${props.permalink}`}>reddit</a>&nbsp;
<a href={`https://www.reveddit.com${props.permalink}`}>reveddit</a>
{props.hasOwnProperty('edited_selftext') &&
{hasOwnProperty.call(props, 'edited_selftext') &&
<a onClick= {() => setEditedMode((editedMode + 1) % editedModes.length)}
onKeyDown={e => e.key == 'Enter' && setEditedMode((editedMode + 1) % editedModes.length)}
tabIndex= {0}
@ -129,3 +131,5 @@ export default (props) => {
}
</div>
}
export default Post

View file

@ -4,6 +4,8 @@ import { prettyScore, prettyDate, prettyTimeDiff, exactDateTime,
parse, isRemoved, editedModes, editedTitles } from '../../utils'
import { Diff } from '@ali-tas/htmldiff-js'
const hasOwnProperty = Object.prototype.hasOwnProperty
const Comment = (props) => {
let commentStyle = 'comment '
@ -20,23 +22,23 @@ const Comment = (props) => {
const innerHTML = Array(editedModes.length)
if (props.removed && isRemoved(props.body)) {
if (!props.hasOwnProperty('retrieved_utc') && !props.hasOwnProperty('retrieved_on') || !props.hasOwnProperty('created_utc')) {
if (!hasOwnProperty.call(props, 'retrieved_utc') && !hasOwnProperty.call(props, 'retrieved_on') || !hasOwnProperty.call(props, 'created_utc')) {
innerHTML[editedModes.orig] = '<p>[removed too quickly to be archived]</p>'
} else if (props.created_utc < 1627776000) { // Aug 1 2021
const retrieved = props.hasOwnProperty('retrieved_utc') ? props.retrieved_utc : props.retrieved_on;
const retrieved = hasOwnProperty.call(props, 'retrieved_utc') ? props.retrieved_utc : props.retrieved_on;
innerHTML[editedModes.orig] = `<p>[removed within ${prettyTimeDiff(retrieved - props.created_utc)}]</p>`
}
// After around Aug 1 2021, Pushshift began updating comments from Reddit after around
// 24-48 hours, including removing(?) comments that were removed from Reddit. The presence
// of either retrieved_utc or retrieved_on can currently be used to test for this behaviour.
else if (props.hasOwnProperty('retrieved_utc')) {
else if (hasOwnProperty.call(props, 'retrieved_utc')) {
innerHTML[editedModes.orig] = `<p>[removed within ${prettyTimeDiff(props.retrieved_utc - props.created_utc)}]</p>`
} else {
innerHTML[editedModes.orig] = `<p>[either removed too quickly, or <a href='https://www.reddit.com/r/pushshift/comments/pgzdav/the_api_now_appears_to_rewrite_nearly_all/'>removed(?) from archive</a> after ${prettyTimeDiff(props.retrieved_on - props.created_utc, true)}]</p>`
}
} else {
innerHTML[editedModes.orig] = parse(props.body)
if (props.hasOwnProperty('edited_body')) {
if (hasOwnProperty.call(props, 'edited_body')) {
innerHTML[editedModes.edited] = parse(props.edited_body)
innerHTML[editedModes.rich] = Diff.execute(innerHTML[editedModes.orig], innerHTML[editedModes.edited])
}
@ -80,7 +82,7 @@ const Comment = (props) => {
<span className='space' />
{props.created_utc &&
<span className='comment-time' title={exactDateTime(props.created_utc)}>{prettyDate(props.created_utc)}</span>}
{(props.hasOwnProperty('edited_body') || props.edited) &&
{(hasOwnProperty.call(props, 'edited_body') || props.edited) &&
<span className='comment-time' title={props.edited ? exactDateTime(props.edited) : 'within 3 minutes'}
>* (last edited {prettyDate(props.edited ? props.edited : props.created_utc)})</span>}
</div>
@ -91,7 +93,7 @@ const Comment = (props) => {
<a href={`https://www.reddit.com${permalink}`}>reddit</a>
<a href={`https://www.reveddit.com${permalink}`}>reveddit</a>
{parentlink}
{props.hasOwnProperty('edited_body') &&
{hasOwnProperty.call(props, 'edited_body') &&
<a onClick= {() => setEditedMode((editedMode + 1) % editedModes.length)}
onKeyDown={e => e.key == "Enter" && setEditedMode((editedMode + 1) % editedModes.length)}
tabIndex= {0}

View file

@ -2,8 +2,8 @@ import React from 'react'
const getProcent = (part, total) => (total === 0 ? '0.0' : ((100 * part) / total).toFixed(1))
export default props => (
<div id='comment-info'>
export default function CommentInfo(props) {
return <div id='comment-info'>
<span className='nowrap removed-text'>
removed comments: {props.removed}/{props.total} ({getProcent(props.removed, props.total)}%)
</span>
@ -11,4 +11,4 @@ export default props => (
deleted comments: {props.deleted}/{props.total} ({getProcent(props.deleted, props.total)}%)
</span>
</div>
)
}

View file

@ -97,11 +97,11 @@ class Thread extends React.Component {
// the comment's ids must have already been updated by fullnamesToShortIDs()
useRedditComment (comment) {
if (isRemoved(comment.body)) {
this.state.removed++
commentHint.removed = true
this.state.removed++ // eslint-disable-line react/no-direct-mutation-state
comment.removed = true
} else if (isDeleted(comment.body)) {
this.state.deleted++
commentHint.deleted = true
this.state.deleted++ // eslint-disable-line react/no-direct-mutation-state
comment.deleted = true
}
this.state.pushshiftCommentLookup.set(comment.id, comment)
}
@ -111,7 +111,7 @@ class Thread extends React.Component {
componentDidMount () {
const { subreddit, threadID, commentID } = this.props.match.params
const { location } = this.props
this.state.post = { subreddit, id: threadID }
this.setState({ post: {subreddit, id: threadID} })
this.props.global.setLoading('Loading post...')
console.time('Load comments')
@ -237,7 +237,7 @@ class Thread extends React.Component {
if (comment?.link_id != threadID) {
console.timeEnd('Load comments')
this.props.global.setError({ message: 'Invalid permalink' })
this.state.loadingComments = false
this.setState({loadingComments: false})
console.error('link_id mismatch:', comment)
return
}
@ -659,7 +659,7 @@ class Thread extends React.Component {
<>
{isSingleComment &&
<div className='view-rest-of-comment'>
<div>you are viewing a single comment's thread.</div><div>
<div>you are viewing a single comment&apos;s thread.</div><div>
{this.state.reloadingComments ?
<span className='nowrap faux-link'>view the rest of the comments &rarr;</span> :
<span className='nowrap'><Link to={() => ({

View file

@ -112,9 +112,9 @@ class GlobalState extends Container {
// A redux-like connect function for Unstated
export const connect = Component => {
return props => (
<Subscribe to={[GlobalState]}>
return function Connected(props) {
return <Subscribe to={[GlobalState]}>
{globalState => <Component {...props} global={globalState} />}
</Subscribe>
)
}
}