Skip to content

Commit 85bb208

Browse files
committed
Initial commit
0 parents  commit 85bb208

File tree

9 files changed

+246
-0
lines changed

9 files changed

+246
-0
lines changed

LICENSE

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Copyright (C) 2018 by Martijn van der Ven <[email protected]>
2+
3+
Permission to use, copy, modify, and/or distribute this software for any
4+
purpose with or without fee is hereby granted.
5+
6+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
7+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
8+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
9+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
10+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
11+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
12+
PERFORMANCE OF THIS SOFTWARE.

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# ![](logo/discourse-64.png) Discourse HTML
2+
3+
A super simple [Browser Extension][] for redirecting [Discourse][] community
4+
websites to their HTML versions, rather than their [js;dr][] defaults.
5+
6+
1. Automatically [append `?_escaped_fragment_`][] to any known Discourse URL.
7+
8+
2. Offer an options page for the user to configure Discourse URLs.
9+
10+
## Differences from spec
11+
12+
The extension was created with [the Browser Extensions specification][spec] in
13+
mind. It turns out this is very hard to do while also supporting real
14+
life browsers.
15+
16+
* This extension uses the [`options_ui` manifest key][] instead of the
17+
[`options_page` manifest key][] from the spec.
18+
* This extension asks for the non-standard `storage` permission to use the [Web
19+
Storage API][].
20+
21+
Any other differences should be reported and either documented here or fixed
22+
as bugs.
23+
24+
## Code Style
25+
26+
This extension follows the [JavaScript Standard Style][]. I apologise if you
27+
love semicolons. Make sure to run it under the WebExtensions environment:
28+
29+
```
30+
standard --env webextensions
31+
```
32+
33+
## Licenses
34+
35+
* The official logo [`discourse.png`][] is “®, Civilized Discourse Construction
36+
Kit, Inc.” and was used as a base for this extension’s logo.
37+
38+
* Everything else is released under the BSD Zero Clause License (0BSD).
39+
Please see the [`LICENSE`](LICENSE) file for more information.
40+
41+
[Browser Extension]: https://browserext.github.io/
42+
[Discourse]: https://www.discourse.org/
43+
[js;dr]: https://indieweb.org/js;dr
44+
[append `?_escaped_fragment_`]: https://news.ycombinator.com/item?id=14247848
45+
[pull requests]: https://help.github.com/articles/creating-a-pull-request/
46+
[spec]: https://browserext.github.io/browserext/
47+
[`options_ui` manifest key]: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/options_ui
48+
[`options_page` manifest key]: https://browserext.github.io/browserext/#list-of-keys
49+
[Web Storage API]: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage
50+
[JavaScript Standard Style]: https://standardjs.com/
51+
[`discourse.png`]: https://github.com/discourse/discourse/blob/96b46170941f9ef8f492a993b0fbcbf591a1e9ae/images/discourse.png

logo/discourse-32.png

1.98 KB
Loading

logo/discourse-64.png

5.01 KB
Loading

manifest.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "Discourse HTML",
3+
"version": "1.0",
4+
"description": "Redirects Discourse community websites to their HTML versions, rather than their js;dr defaults.",
5+
"icons": {
6+
"32": "logo/discourse-32.png",
7+
"64": "logo/discourse-64.png"
8+
},
9+
"developer": {
10+
"name": "Martijn van der Ven",
11+
"url": "https://vanderven.se/martijn/"
12+
},
13+
"background": {
14+
"scripts": [
15+
"src/background.js"
16+
],
17+
"persistent": true
18+
},
19+
"options_ui": {
20+
"browser_style": true,
21+
"page": "src/options.html"
22+
},
23+
"manifest_version": 2,
24+
"permissions": [
25+
"webRequest",
26+
"webRequestBlocking",
27+
"<all_urls>",
28+
"storage"
29+
]
30+
}

src/background.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict'
2+
3+
const trigger = '_escaped_fragment_'
4+
5+
function rewriter (request) {
6+
let url = new window.URL(request.url)
7+
if (url.searchParams.has(trigger) === false) {
8+
url.searchParams.set(trigger, '')
9+
return { 'redirectUrl': url.href }
10+
}
11+
}
12+
function register (patterns) {
13+
browser.webRequest.onBeforeRequest.removeListener(rewriter)
14+
if (patterns.length > 0) {
15+
browser.webRequest.onBeforeRequest.addListener(
16+
rewriter,
17+
{urls: patterns, types: ['main_frame', 'sub_frame']},
18+
['blocking']
19+
)
20+
}
21+
}
22+
23+
browser.storage.onChanged.addListener(({patterns}) => {
24+
if (patterns !== undefined) {
25+
register(patterns.newValue)
26+
}
27+
})
28+
29+
browser.storage.local.get({patterns: []})
30+
.then(({patterns}) => register(patterns))

src/options.html

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Discourse HTML Options</title>
6+
<style>
7+
table {
8+
margin: 2em 0 0;
9+
border-collapse: collapse;
10+
border: none;
11+
}
12+
th, td {
13+
padding: 0;
14+
}
15+
th, label {
16+
font-weight: bold;
17+
text-align: left;
18+
}
19+
p, caption {
20+
margin: 0 0 .6em;
21+
text-align: left;
22+
}
23+
label {
24+
display: block;
25+
margin-bottom: 6px;
26+
}
27+
input {
28+
font-size: inherit;
29+
font-family: inherit;
30+
line-height: inherit;
31+
display: inline-block;
32+
width: 40em;
33+
padding-top: .3em;
34+
padding-bottom: .3em;
35+
}
36+
button {
37+
font-size: inherit;
38+
font-family: inherit;
39+
line-height: inherit;
40+
margin-left: 1em;
41+
}
42+
th + th {
43+
padding-left: 1em;
44+
}
45+
th, td {
46+
padding-bottom: 6px;
47+
}
48+
</style>
49+
</head>
50+
<body>
51+
<p>Add a <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Match_patterns">match pattern</a> for a Discourse instance to enable URL rewriting.</p>
52+
<form>
53+
<label>Pattern</label>
54+
<input type="text"><button type="submit">Add</button>
55+
</form>
56+
<table>
57+
<caption>Enabled match patterns</caption>
58+
<thead>
59+
<tr>
60+
<th>Pattern</th>
61+
<th>Actions</th>
62+
</tr>
63+
</thead>
64+
<tbody>
65+
</tbody>
66+
</table>
67+
<template>
68+
<tr>
69+
<td><input type="text" readonly></td>
70+
<td><button>Remove</button></td>
71+
</tr>
72+
</template>
73+
<script src="options.js"></script>
74+
</body>
75+
</html>

src/options.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict'
2+
3+
const input = document.querySelector('input')
4+
const tbody = document.querySelector('tbody')
5+
const template = document.querySelector('template').content
6+
let cache = []
7+
8+
function drawTable (patterns) {
9+
cache = patterns
10+
tbody.innerHTML = ''
11+
for (let pattern of patterns) {
12+
template.querySelector('input').value = pattern
13+
tbody.appendChild(document.importNode(template, true))
14+
}
15+
}
16+
17+
document.querySelector('form').addEventListener('submit', submit => {
18+
submit.preventDefault()
19+
let pattern = input.value
20+
if (pattern.length > 0) {
21+
input.value = ''
22+
browser.storage.local.set({
23+
patterns: [pattern, ...cache].filter((v, i, a) => a.indexOf(v) === i)
24+
})
25+
}
26+
})
27+
28+
tbody.addEventListener('click', click => {
29+
if (click.target.nodeName === 'BUTTON') {
30+
let pattern = click.target.parentNode.parentNode.querySelector('input').value
31+
browser.storage.local.set({patterns: cache.filter(item => item !== pattern)})
32+
}
33+
})
34+
35+
browser.storage.onChanged.addListener(({patterns}) => {
36+
if (patterns !== undefined) {
37+
drawTable(patterns.newValue)
38+
}
39+
})
40+
41+
browser.storage.local.get({patterns: []})
42+
.then(({patterns}) => drawTable(patterns))

web-ext-config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
ignoreFiles: [
3+
'README.md',
4+
'web-ext-config.js'
5+
]
6+
}

0 commit comments

Comments
 (0)