Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 40 additions & 36 deletions README.md

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ updates:

| Version | Supported |
| ------- | ------------------ |
| 4.0.x | :white_check_mark: |
| 4.1.x | :white_check_mark: |

## Reporting a Vulnerability

Expand Down Expand Up @@ -64,8 +64,8 @@ npm version patch # or minor, or major
git push --follow-tags

# Or manually create and push a signed tag
git tag -s 4.0.0 -m "Release version 4.0.0"
git push origin 4.0.0
git tag -s 4.1.0 -m "Release version 4.0.0"
git push origin 4.1.0
```

## Release Verification
Expand All @@ -76,10 +76,10 @@ All releases should be signed with GPG/SSH signatures for verification:

```bash
# Verify the signature on a release tag
git verify-tag 4.0.0
git verify-tag 4.1.0

# Show tag details with signature
git tag -v 4.0.0
git tag -v 4.1.0
```

### Verifying Signed Commits
Expand Down
18 changes: 9 additions & 9 deletions bookmarklets.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
{
"name": "KillStickyHeaders",
"file": "killStickyHeaders.bookmarklet",
"version": "2.0.0"
"version": "2.1.0"
},
{
"name": "Linklighter",
Expand All @@ -23,42 +23,42 @@
{
"name": "OpenInBrave",
"file": "openinbrave.bookmarklet",
"version": "1.1.1"
"version": "1.1.2"
},
{
"name": "OpenInFirefox",
"file": "openinfirefox.bookmarklet",
"version": "1.6.1"
"version": "1.6.2"
},
{
"name": "OpenInFirefox-Focus",
"file": "openinfirefox-focus.bookmarklet",
"version": "1.1.1"
"version": "1.1.2"
},
{
"name": "OpenInFirefox-Private",
"file": "openinfirefox-private.bookmarklet",
"version": "1.1.1"
"version": "1.1.2"
},
{
"name": "OpenInGoodReader",
"file": "openingoodreader.bookmarklet",
"version": "1.5.1"
"version": "1.5.2"
},
{
"name": "OpenInTextastic",
"file": "openintextastic.bookmarklet",
"version": "1.1.1"
"version": "1.1.2"
},
{
"name": "OpenInWorkingCopy",
"file": "openinworkingcopy.bookmarklet",
"version": "1.6.1"
"version": "1.6.2"
},
{
"name": "OpenURLParam",
"file": "openurlparam.bookmarklet",
"version": "1.1.1"
"version": "1.2.0"
},
{
"name": "UtmStrip",
Expand Down
2 changes: 1 addition & 1 deletion dist/killStickyHeaders.bookmarklet
Original file line number Diff line number Diff line change
@@ -1 +1 @@
javascript:'use%20strict'%3B(()=%3E%7Bconst%20o=document.querySelectorAll('body%20%2A')%3Bfor(const%20e%20of%20Array.from(o))if('fixed'===getComputedStyle(e).position)%7Bconst%20o=e.parentNode%3Bo%26%26o.removeChild(e)%7D%7D)()%3Bvoid'2.0.0'
javascript:Array.from(document.querySelectorAll('body%20%2A')).filter(e=%3E%5B'fixed'%2C'sticky'%5D.includes(getComputedStyle(e).position)).forEach(e=%3Ee.remove())%3Bvoid'2.1.0'
2 changes: 1 addition & 1 deletion dist/openinbrave.bookmarklet
Original file line number Diff line number Diff line change
@@ -1 +1 @@
javascript:if(%2FiP(.d%7Chone)%2F.test(navigator.userAgent))location.href='brave:%2F%2Fopen-url%3Furl='%2BencodeURIComponent(location.href)%3Bvoid'1.1.1'
javascript:if(%2FiP(ad%7Chone)%2F.test(navigator.userAgent))location.href='brave:%2F%2Fopen-url%3Furl='%2BencodeURIComponent(location.href)%3Bvoid'1.1.2'
2 changes: 1 addition & 1 deletion dist/openinfirefox-focus.bookmarklet
Original file line number Diff line number Diff line change
@@ -1 +1 @@
javascript:if(%2FiP(.d%7Chone)%2F.test(navigator.userAgent))location.href=%60firefox-focus:%2F%2Fopen-url%3Furl=%24%7BencodeURIComponent(location.href)%7D%26private=true%60%3Bvoid'1.1.1'
javascript:if(%2FiP(ad%7Chone)%2F.test(navigator.userAgent))location.href=%60firefox-focus:%2F%2Fopen-url%3Furl=%24%7BencodeURIComponent(location.href)%7D%26private=true%60%3Bvoid'1.1.2'
2 changes: 1 addition & 1 deletion dist/openinfirefox-private.bookmarklet
Original file line number Diff line number Diff line change
@@ -1 +1 @@
javascript:if(%2FiP(.d%7Chone)%2F.test(navigator.userAgent))location.href=%60firefox:%2F%2Fopen-url%3Furl=%24%7BencodeURIComponent(location.href)%7D%26private=true%60%3Bvoid'1.1.1'
javascript:if(%2FiP(ad%7Chone)%2F.test(navigator.userAgent))location.href=%60firefox:%2F%2Fopen-url%3Furl=%24%7BencodeURIComponent(location.href)%7D%26private=true%60%3Bvoid'1.1.2'
2 changes: 1 addition & 1 deletion dist/openinfirefox.bookmarklet
Original file line number Diff line number Diff line change
@@ -1 +1 @@
javascript:if(%2FiP(.d%7Chone)%2F.test(navigator.userAgent))location.href='firefox:%2F%2Fopen-url%3Furl='%2BencodeURIComponent(location.href)%3Bvoid'1.6.1'
javascript:if(%2FiP(ad%7Chone)%2F.test(navigator.userAgent))location.href='firefox:%2F%2Fopen-url%3Furl='%2BencodeURIComponent(location.href)%3Bvoid'1.6.2'
2 changes: 1 addition & 1 deletion dist/openingoodreader.bookmarklet
Original file line number Diff line number Diff line change
@@ -1 +1 @@
javascript:if(%2FiP(.d%7Chone)%2F.test(navigator.userAgent)%26%26%2F%5C.pdf(%24%7C%5C%3F)%2F.test(location.href))location.href='gr'%2Blocation.href%3Bvoid'1.5.1'
javascript:if(%2FiP(ad%7Chone)%2F.test(navigator.userAgent)%26%26%2F%5C.pdf(%24%7C%5C%3F)%2F.test(location.href))location.href='gr'%2Blocation.href%3Bvoid'1.5.2'
2 changes: 1 addition & 1 deletion dist/openintextastic.bookmarklet
Original file line number Diff line number Diff line change
@@ -1 +1 @@
javascript:if(%2FiP(.d%7Chone)%2F.test(navigator.userAgent))location.href=location.href.replace(%2F%5Ehttps%3F%2F%2C'textastic')%3Bvoid'1.1.1'
javascript:if(%2FiP(ad%7Chone)%2F.test(navigator.userAgent))location.href=location.href.replace(%2F%5Ehttps%3F%2F%2C'textastic')%3Bvoid'1.1.2'
2 changes: 1 addition & 1 deletion dist/openinworkingcopy.bookmarklet
Original file line number Diff line number Diff line change
@@ -1 +1 @@
javascript:if(%2FiP(.d%7Chone)%2F.test(navigator.userAgent)%26%26('bitbucket.org'===location.host%7C%7C'github.com'===location.host))location.href=%60working-copy:%2F%2Fshow%3Fremote=%24%7BencodeURIComponent(location.href.split('%2F').slice(0%2C5).join('%2F'))%7D.git%60%3Bvoid'1.6.1'
javascript:if(%2FiP(ad%7Chone)%2F.test(navigator.userAgent)%26%26('bitbucket.org'===location.host%7C%7C'github.com'===location.host))location.href=%60working-copy:%2F%2Fshow%3Fremote=%24%7BencodeURIComponent(location.href.split('%2F').slice(0%2C5).join('%2F'))%7D.git%60%3Bvoid'1.6.2'
2 changes: 1 addition & 1 deletion dist/openurlparam.bookmarklet
Original file line number Diff line number Diff line change
@@ -1 +1 @@
javascript:const%20c=location.search.search('url=')%3Bif(c%3E-1)%7Blet%20o=location.search.slice(4%2Bc)%3Bconst%20t=o.indexOf('%26')%3Bif(t%3E-1%26%26(o=o.slice(0%2Ct))%2Co.length%3E5)%7Bconst%20c=decodeURIComponent(o)%3Btry%7Bconst%20o=new%20URL(c%2Clocation.href)%3B'https:'===o.protocol%26%26location.replace(o.href)%7Dcatch%7B%7D%7D%7Dvoid'1.1.1'
javascript:'use%20strict'%3B(()=%3E%7Bconst%20t=new%20URL(document.location.href)%3Bif(11%3Et.search.length)return%3Bconst%20e=new%20URLSearchParams(t.search)%2Cn=%5B'url'%2C'destination'%2C'redirect'%2C'target'%2C'goto'%2C'u'%2C'dest'%2C'link'%2C'out'%5D.filter(t=%3Ee.has(t)).map(t=%3E%7Bconst%20n=e.get(t)%3Breturn%20n%3FdecodeURIComponent(n):''%7D).find(t=%3Et.match(%2F%5Ehttps:%2F))%3Bn%26%26window.location.replace(new%20URL(n))%7D)()%3Bvoid'1.2.0'
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@
"test": "npm run build && npm run verify-build",
"verify-build": "node scripts/verify-build.js"
},
"version": "4.0.2"
"version": "4.1.0"
}
12 changes: 3 additions & 9 deletions scripts/build-bookmarklet.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,9 @@ function buildBookmarklet(bookmarklet) {
// Read minified code from dist/ directory
let theCode = readFileOrFail(distPath);

// "unstrict" theCode in simplest cases
switch(bookmarklet.file) {
default:
break;
case 'delighter.bookmarklet':
case 'isitaws.bookmarklet':
case bookmarklet.file.startsWith('openin') ? bookmarklet.file : false :
case 'openurlparam.bookmarklet':
theCode = theCode.replace(/^'use strict';/,'');
// "unstrict" theCode in simplest cases (no vars or const in bookmarklet)
if (! /(const|let|var) /.test(theCode)) {
theCode = theCode.replace(/^'use strict';/,'');
}

// Append version string
Expand Down
17 changes: 5 additions & 12 deletions src/killStickyHeaders.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
// use querySelectorAll() to find & delete all fixed position elements of body
(() => {
const elements: NodeListOf<Element> = document.querySelectorAll('body *');
for (const element of Array.from(elements)) {
if (getComputedStyle(element).position === 'fixed') {
const parent: Node | null = element.parentNode;
if (parent) {
parent.removeChild(element);
}
}
}
})();
// find & delete all fixed/sticky position elements of body

Array.from(document.querySelectorAll('body *'))
.filter(el => ['fixed', 'sticky'].includes(getComputedStyle(el).position))
.forEach(el => el.remove());
2 changes: 1 addition & 1 deletion src/openinbrave.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// verify iOS UserAgent & then prefix URL with protocol of Brave iOS app
if (/iP(.d|hone)/.test(navigator.userAgent)) {
if (/iP(ad|hone)/.test(navigator.userAgent)) {
location.href = `brave://open-url?url=${encodeURIComponent(location.href)}`;
}
2 changes: 1 addition & 1 deletion src/openinfirefox-focus.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// verify iOS UserAgent, prefix URL w/ Firefox Focus protocol, & add private suffix
if (/iP(.d|hone)/.test(navigator.userAgent)) {
if (/iP(ad|hone)/.test(navigator.userAgent)) {
location.href = `firefox-focus://open-url?url=${encodeURIComponent(location.href)}&private=true`;
}
2 changes: 1 addition & 1 deletion src/openinfirefox-private.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// verify iOS UserAgent, prefix URL w/ Firefox iOS protocol, & add private suffix
if (/iP(.d|hone)/.test(navigator.userAgent)) {
if (/iP(ad|hone)/.test(navigator.userAgent)) {
location.href = `firefox://open-url?url=${encodeURIComponent(location.href)}&private=true`;
}
2 changes: 1 addition & 1 deletion src/openinfirefox.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// verify iOS UserAgent & then prefix URL with protocol of Firefox iOS app
if (/iP(.d|hone)/.test(navigator.userAgent)) {
if (/iP(ad|hone)/.test(navigator.userAgent)) {
location.href = `firefox://open-url?url=${encodeURIComponent(location.href)}`;
}
2 changes: 1 addition & 1 deletion src/openingoodreader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// verify iOS UserAgent *and* file is PDF
// then prefix URL with protocol of GoodReader iOS app
if (/iP(.d|hone)/.test(navigator.userAgent) &&
if (/iP(ad|hone)/.test(navigator.userAgent) &&
/\.pdf($|\?)/.test(location.href)) {
location.href = `gr${location.href}`;
}
2 changes: 1 addition & 1 deletion src/openintextastic.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// verify on an iOS device, then swap in URL protocol of Textastic iOS app
if (/iP(.d|hone)/.test(navigator.userAgent)) {
if (/iP(ad|hone)/.test(navigator.userAgent)) {
location.href = location.href.replace(/^https?/, 'textastic');
}
2 changes: 1 addition & 1 deletion src/openinworkingcopy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// verify host is 'github.com' (or 'bitbucket.org') & on an iOS device
// then use URL protocol of Working Copy with "show" and top-level repo URL
// Working Copy "show" will open to the repo, performing a clone if needed
if (/iP(.d|hone)/.test(navigator.userAgent) &&
if (/iP(ad|hone)/.test(navigator.userAgent) &&
(location.host === 'bitbucket.org' || location.host === 'github.com')) {
location.href = `working-copy://show?remote=${encodeURIComponent(location.href.split('/').slice(0, 5).join('/'))}.git`;
}
54 changes: 29 additions & 25 deletions src/openurlparam.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
// grab the URL param from the current URL query string (location.search)
const u: number = location.search.search("url=");
if (u > -1) {
let t: string = location.search.slice(4 + u);
// check if there are params after it (i.e., an "&")
const p: number = t.indexOf("&");
// lop off trailing params
if (p > -1) {
t = t.slice(0, p);
}
if (t.length > 5) {
// decode URL and validate it before navigating
const decodedUrl: string = decodeURIComponent(t);
try {
// Parse URL to validate it's well-formed
const urlObj: URL = new URL(decodedUrl, location.href);
// Only allow https scheme to prevent XSS and enforce secure connections
if (urlObj.protocol === "https:") {
location.replace(urlObj.href);
}
} catch {
// Invalid URL - do nothing
}
}
}
// grab the (target) "url" param from the current URL query string (location.search)

(() => {
// default to getting the current address & making it a URL object to work with
const origUrl: URL = new URL(document.location.href);

// exit if the current URL object searchParam is less than 11 chars ('https://x.x)
if (origUrl.search.length < 11) {
return;
}

// create array of common param keys used for URLs (in priority order)
const urlKey: string[] = ['url', 'destination', 'redirect', 'target', 'goto', 'u', 'dest', 'link', 'out'],
origParams: URLSearchParams = new URLSearchParams(origUrl.search);

// find 1st param key match that's a valid looking URL, starting w/ 'https:'
const urlCandidate: string | undefined = urlKey
.filter((param: string) => origParams.has(param))
.map((param: string) => {
const value: string | null = origParams.get(param);
return value ? decodeURIComponent(value) : '';
})
.find((url: string) => url.match(/^https:/));

// navigate to new URL if found
if (urlCandidate) {
window.location.replace(new URL(urlCandidate));
}
})();
69 changes: 34 additions & 35 deletions src/unskim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,39 @@
// wrap everything in an anon function for isolation

(() => {

// default to getting the current address & making it a URL object to work with
let origUrl: URL = new URL(document.location.href);

// handle special case of Safari error page (DNS block of redirection service)
if (origUrl.href === 'safari-resource:/ErrorPage.html') {
// DO NOT "UNCURL" the apostrophe or quotes in the match regex, that formatting IS CRITICAL
const urlStr: string | undefined = document.querySelector('p.error-message')?.textContent?.match(/Safari can't open the page "(https?:[^"]+)"/)?.[1];
if (urlStr) {
origUrl = new URL(urlStr);
}
}

// if the current URL object doesn't even have a searchParam, exit now
if (origUrl.search === '') {
return;
}

// create array of common param keys used for URLs (in priority order)
const urlKey: string[] = ['url', 'destination', 'redirect', 'target', 'goto', 'u', 'dest', 'link', 'out'],
origParams: URLSearchParams = new URLSearchParams(origUrl.search);

// find 1st param key match that's a valid looking URL
const urlCandidate: string | undefined = urlKey
.filter((param: string) => origParams.has(param))
.map((param: string) => {
const value: string | null = origParams.get(param);
return value ? decodeURIComponent(value) : '';
})
.find((url: string) => url.match(/^https?:/));

// navigate to new URL if found
if (urlCandidate) {
window.location.replace(new URL(urlCandidate));
}
// default to getting the current address & making it a URL object to work with
let origUrl: URL = new URL(document.location.href);

// handle special case of Safari error page (DNS block of redirection service)
if (origUrl.href === 'safari-resource:/ErrorPage.html') {
// DO NOT "UNCURL" the apostrophe or quotes in the match regex, that formatting IS CRITICAL
const urlStr: string | undefined = document.querySelector('p.error-message')?.textContent?.match(/Safari can't open the page "(https?:[^"]+)"/)?.[1];
if (urlStr) {
origUrl = new URL(urlStr);
}
}

// if the current URL object doesn't even have a searchParam, exit now
if (origUrl.search === '') {
return;
}

// create array of common param keys used for URLs (in priority order)
const urlKey: string[] = ['url', 'destination', 'redirect', 'target', 'goto', 'u', 'dest', 'link', 'out'],
origParams: URLSearchParams = new URLSearchParams(origUrl.search);

// find 1st param key match that's a valid looking URL
const urlCandidate: string | undefined = urlKey
.filter((param: string) => origParams.has(param))
.map((param: string) => {
const value: string | null = origParams.get(param);
return value ? decodeURIComponent(value) : '';
})
.find((url: string) => url.match(/^https?:/));

// navigate to new URL if found
if (urlCandidate) {
window.location.replace(new URL(urlCandidate));
}

})();
Loading