├── .gitignore ├── LICENSE ├── Pinlet.png ├── Pinlet.safariextension ├── Info.plist ├── Settings.plist ├── global.html ├── popover │ ├── popover.css │ ├── popover.html │ └── popover.js ├── toolbar.png └── toolbar@2x.png └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Abdullah Aloğlu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Pinlet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aloglu/pinlet/57d76edcfe6b8978f48c1f31e39140612ced3373/Pinlet.png -------------------------------------------------------------------------------- /Pinlet.safariextension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Author 6 | Abdullah Aloğlu 7 | Builder Version 8 | 12603.2.4 9 | CFBundleDisplayName 10 | Pinlet 11 | CFBundleIdentifier 12 | com.pinboard.pinlet 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleVersion 18 | 1 19 | Chrome 20 | 21 | Global Page 22 | global.html 23 | Popovers 24 | 25 | 26 | Filename 27 | popover/popover.html 28 | Height 29 | 350 30 | Identifier 31 | PinletPop 32 | Width 33 | 350 34 | 35 | 36 | Toolbar Items 37 | 38 | 39 | Command 40 | Pinlet 41 | Identifier 42 | Pinlet 43 | Image 44 | toolbar@2x.png 45 | Include By Default 46 | 47 | Label 48 | Pinlet 49 | Palette Label 50 | Pinlet 51 | Popover 52 | PinletPop 53 | Tool Tip 54 | Pinlet 55 | 56 | 57 | 58 | DeveloperIdentifier 59 | VE6CSLGJ83 60 | ExtensionInfoDictionaryVersion 61 | 1.0 62 | Permissions 63 | 64 | Website Access 65 | 66 | Include Secure Pages 67 | 68 | Level 69 | All 70 | 71 | 72 | Website 73 | https://alog.lu 74 | 75 | 76 | -------------------------------------------------------------------------------- /Pinlet.safariextension/Settings.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Key 7 | APIToken 8 | Secure 9 | 10 | Title 11 | API Token 12 | Type 13 | TextField 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Pinlet.safariextension/global.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Pinlet.safariextension/popover/popover.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-box-sizing: border-box; 3 | } 4 | 5 | html { 6 | height: 100%; 7 | -webkit-user-select: none; 8 | } 9 | 10 | body { 11 | height: 100%; 12 | margin: 0; 13 | padding: .5em; 14 | font-family: "Helvetica Neue"; 15 | font-size: 13px; 16 | line-height: 1em; 17 | } 18 | 19 | form { 20 | height: 100%; 21 | display: flex; 22 | flex-direction: column; 23 | } 24 | 25 | label { 26 | display: block; 27 | } 28 | 29 | label + label { 30 | margin-top: .5em; 31 | } 32 | 33 | input[type="text"], textarea, button { 34 | display: block; 35 | font-size: inherit; 36 | margin: 0; 37 | } 38 | 39 | input[type="text"], textarea { 40 | width: 100%; 41 | margin-top: .25em; 42 | } 43 | 44 | textarea { 45 | resize: vertical; 46 | } 47 | 48 | main { 49 | flex: 1; 50 | } 51 | 52 | footer { 53 | flex: none; 54 | display: flex; 55 | flex-direction: row; 56 | justify-content: space-between; 57 | } 58 | 59 | button { 60 | flex: none; 61 | } -------------------------------------------------------------------------------- /Pinlet.safariextension/popover/popover.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 | 14 | 18 | 22 | 26 | 30 | 34 |
35 | 39 |
40 | 41 | -------------------------------------------------------------------------------- /Pinlet.safariextension/popover/popover.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var form, 3 | request; 4 | 5 | function start() { 6 | form = document.forms[ 0 ]; 7 | list = document.getElementById( "list" ); 8 | newLink = document.getElementById( "new" ); 9 | editLink = document.getElementById( "edit" ); 10 | 11 | form.cancel.addEventListener( "click", cancel, false ); 12 | form.add.addEventListener( "click", addPin, false ); 13 | form.addEventListener( "submit", formSubmit, false ); 14 | } 15 | 16 | window.populateForm = function( page ) { 17 | form.url.value = page.url; 18 | form.title.value = page.title; 19 | }; 20 | 21 | function addPin( event ) { 22 | if( request !== undefined ) { 23 | return; 24 | } 25 | 26 | var url = "https://api.pinboard.in/v1/posts/add?auth_token=" + safari.extension.secureSettings.APIToken + "&format=json"; 27 | 28 | url += "&url=" + encodeURIComponent( form.url.value ); 29 | url += "&description=" + encodeURIComponent( form.title.value ); 30 | url += "&extended=" + encodeURIComponent( form.description.value ); 31 | url += "&tags=" + encodeURIComponent( form.tags.value ); 32 | url += "&shared=" + encodeBoolean( !form.isPrivate.checked ); 33 | url += "&toread=" + encodeBoolean( form.isReadLater.checked ); 34 | 35 | request = new XMLHttpRequest(); 36 | request.responseType = "json"; 37 | request.addEventListener( "load", addPinResponseHandler, false ); 38 | request.open( "POST", url, true ); 39 | request.send(); 40 | } 41 | 42 | function addPinResponseHandler( event ) { 43 | cancel(); 44 | } 45 | 46 | function formSubmit( event ) { 47 | // Don't refresh the page 48 | event.preventDefault(); 49 | return false; 50 | } 51 | 52 | function cancel() { 53 | safari.self.hide(); 54 | clear(); 55 | } 56 | 57 | function encodeBoolean( bool ) { 58 | return bool ? "yes" : "no"; 59 | } 60 | 61 | function clear() { 62 | request = undefined; 63 | 64 | form.url.value = ""; 65 | form.title.value = ""; 66 | form.description.value = ""; 67 | form.tags.value = ""; 68 | form.isPrivate.checked = false; 69 | form.isReadLater.checked = false; 70 | } 71 | 72 | window.addEventListener( "DOMContentLoaded", start, false ); 73 | window.addEventListener( "blur", clear, false ); 74 | })(); 75 | -------------------------------------------------------------------------------- /Pinlet.safariextension/toolbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aloglu/pinlet/57d76edcfe6b8978f48c1f31e39140612ced3373/Pinlet.safariextension/toolbar.png -------------------------------------------------------------------------------- /Pinlet.safariextension/toolbar@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aloglu/pinlet/57d76edcfe6b8978f48c1f31e39140612ced3373/Pinlet.safariextension/toolbar@2x.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pinlet 2 | 3 | ![Pinlet](https://raw.githubusercontent.com/aloglu/Pinlet/master/Pinlet.png) 4 | 5 | Pinlet is a Safari extension for the bookmarking service Pinboard. 6 | 7 | # Installation 8 | 9 | I don't have a developer account with Apple, so I wasn't able to build this extension properly¹. That being said, the process is still somewhat straightforward, especially for someone who's savvy enough to look for Pinboard extensions on GitHub. Here's the step by step guide: 10 | 11 | 1. Clone the repository or download it as .zip 12 | 2. Enable the [Develop Menu](https://support.apple.com/guide/safari-developer/develop-menu-dev39df999c1/mac) in Safari 13 | 3. From the menu, click on `Show Extension Builder` 14 | 4. Click on `+`, then `Add Extension...` 15 | 5. Locate the folder of the repository, then click on `Select` 16 | 6. Click on "Install" and enter your password 17 | 7. Once you've installed the extension, go to the `Extensions` tab in `Preferences` and enter your Pinboard API token, which can be found [here](https://pinboard.in/settings/password) 18 | 19 | **Note:** You'll need to reload your open tabs to make the extension work. 20 | 21 | *¹ This also means you have to reinstall the extension every time you relaunch Safari. This is a non-issue for me but I recognize that it'd be a deal breaker for most people. Unfortunately, I can't fix this unless I [pay Apple $100 annually](https://www.macrumors.com/2015/06/10/new-safari-extensions-gallery-fee/).* 22 | 23 | # Acknowledgements 24 | 25 | GitHub users [ArthurHammer](https://github.com/arthurhammer) & [tsbehlman](https://github.com/tsbehlman) have been extremely helpful. My thanks to them, as well as other random strangers on the internet whose code I've used. 26 | --------------------------------------------------------------------------------