├── .gitignore ├── README.md ├── _headers ├── build.py ├── extensions ├── action-bar.toml ├── advanced-markdown-editor.toml ├── autobiography-theme.toml ├── autocomplete-tags.toml ├── bold-editor.toml ├── code-editor.toml ├── dynamic-theme.toml ├── fancy-markdown-editor.toml ├── file-safe.toml ├── focus-theme.toml ├── folders-component.toml ├── futura-theme.toml ├── github-push.toml ├── mfa-link.toml ├── midnight-theme.toml ├── minimal-markdown-editor.toml ├── no-distraction-theme.toml ├── plus-editor.toml ├── secure-spreadsheets.toml ├── simple-markdown-editor.toml ├── simple-task-editor.toml ├── solarized-dark-theme.toml ├── titanium-theme.toml ├── token-vault.toml └── vim-editor.toml ├── netlify.toml ├── requirements.txt ├── runtime.txt └── update.py /.gitignore: -------------------------------------------------------------------------------- 1 | public 2 | package-lock.json 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # snextensions 2 | 3 | [![Netlify Status](https://api.netlify.com/api/v1/badges/53e5f0b7-02c9-400d-8590-159860892cdc/deploy-status)](https://app.netlify.com/sites/snext/deploys) 4 | 5 | A set of open source extensions for StandardNotes. 6 | 7 | # Usage 8 | 9 | Paste `https://snext.netlify.app/index.json` into `Extended Code` in StandardNotes. 10 | 11 | # Notice 12 | 13 | **2023-03-01 Update** 14 | 15 | I've not used StandardNotes for a long time, so it's impractical for me to keep an eye for all the extension updates. 16 | For this reason I'm archiving this repository. You can still use the code as is, or fork and modify to suit your own needs. 17 | Happy hacking! 18 | 19 | Previously (last year) the URL was `https://snext.netlify.com/index.json`. 20 | But early this year Netlify decided to change the domain used by hosted apps. 21 | 22 | If you've been experiencing empty editor UI, there's a chance that you're using 23 | the old URL. Netlify is taking care of redirections but they are missing some 24 | headers. You should migrate to the new URL. 25 | 26 | These steps are required to migrate: 27 | 28 | - Look for the "Repository" options in the "Extensions" menu (on the bottom) 29 | - Delete the repository 30 | - Uninstall all installed themes and editors 31 | - Re-enter the new URL into `Extended Code` 32 | - Re-install all the themes and editors you use 33 | 34 | # Contribution 35 | 36 | If you'd like an extension to be included in this repository, feel free to open an issue. 37 | 38 | # Self-hosting 39 | 40 | ## With Netlify 41 | 42 | In case if you'd like to host your own site other than using ours, you can do so with Netlify: 43 | 44 | - Fork this repository; 45 | - Create a Netlify account if you don't have one already; 46 | - In Netlify app, Use "New site from Git" to create a site from your forked GitHub repository; 47 | - Wait for the build to finish; 48 | - After that you can use `YOUR_SITE_URL/index.json` as an `Extended Code`; 49 | - Optionally you can set a human-readable site name (a subdomain of `netlify.app`) from the `Site settings` page. 50 | **Notice: You need to manually trigger a new deploy via Netlify web UI after changing the site name.** 51 | 52 | ## Without Netlify 53 | 54 | It's easy and recommended to host with Netlify. However if you insist not to use it, it is also possible (notice: the following steps work on Linux or WSL): 55 | 56 | - Prepare your environment with `Python 3.7` with `pip`, as well as `Git`; 57 | - Make sure Python 3.7 can be called directly via `python` from the shell; 58 | - Make sure Git is installed and can be called directly via `git` from the shell; 59 | - `pip install -r requirements.txt` to install required Python libraries; 60 | - Run the build script `URL=my_url python build.py` where `my_url` is the full URL you would later host the resource files on. E.g. if you want to access the plugins via `https://example.com/index.json` then replace `my_url` with `https://example.com/`. 61 | - Verify that: 62 | - the `public` directory is generated; 63 | - there should be `public/index.json` containing information of all extensions; 64 | - all extensions should exists in `public` as sub-directories; 65 | - Host the `public` directory like you would do with any static resources, using nginx, caddy, etc. 66 | - You need to enable CORS headers on your reverse proxy (nginx / caddy / traefik). With nginx these rules will be enough: 67 | ```nginx 68 | add_header 'Access-Control-Allow-Origin' '*'; 69 | add_header 'Access-Control-Allow-Headers' 'content-type'; 70 | ``` 71 | 72 | -------------------------------------------------------------------------------- /_headers: -------------------------------------------------------------------------------- 1 | /* 2 | X-XSS-Protection: 1; mode=block 3 | X-Content-Type-Options: nosniff 4 | Access-Control-Allow-Origin: * 5 | Access-Control-Allow-Headers: content-type 6 | -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | ''' 3 | Parse extensions/*.toml files, output a static site with following structure: 4 | public/ 5 | |-my-extension-1/ 6 | | |-index.json <- extension info 7 | | |-index.html <- extension entrance (component) 8 | | |-dist <- extension resources 9 | | |-... <- other files 10 | | 11 | |-index.json <- repo info, contain all extensions' info 12 | ''' 13 | import glob 14 | import json 15 | import os 16 | import shutil 17 | from subprocess import run 18 | 19 | import toml 20 | 21 | def onerror(func, path, exc_info): 22 | """ 23 | Error handler for ``shutil.rmtree``. 24 | 25 | If the error is due to an access error (read only file) 26 | it attempts to add write permission and then retries. 27 | 28 | If the error is for another reason it re-raises the error. 29 | 30 | Usage : ``shutil.rmtree(path, onerror=onerror)`` 31 | """ 32 | import stat 33 | if not os.access(path, os.W_OK): 34 | # Is the error an access error ? 35 | os.chmod(path, stat.S_IWUSR) 36 | func(path) 37 | else: 38 | raise 39 | 40 | def main(base_url): 41 | while base_url.endswith('/'): 42 | base_url = base_url[:-1] 43 | 44 | print('Fetching extensions...') 45 | base_dir = os.path.dirname(os.path.abspath(__file__)) 46 | extension_dir = os.path.join(base_dir, 'extensions') 47 | public_dir = os.path.join(base_dir, 'public') 48 | 49 | if os.path.exists(public_dir): 50 | shutil.rmtree(public_dir, ignore_errors=False, onerror=onerror) 51 | 52 | os.makedirs(public_dir) 53 | os.chdir(public_dir) 54 | 55 | extensions = [] 56 | 57 | # Read and parse all extension info 58 | for fname in os.listdir(extension_dir): 59 | if not fname.endswith('.toml'): 60 | continue 61 | 62 | with open(os.path.join(extension_dir, fname)) as rf: 63 | ext = toml.load(rf) 64 | 65 | # Build extension info 66 | repo_name = ext['github'].split('/')[-1] 67 | # https://example.com/my-extension/index.html 68 | extension_url = '/'.join([base_url, repo_name, ext['main']]) 69 | # https://example.com/my-extension/index.json 70 | extension_info_url = '/'.join([base_url, repo_name, 'index.json']) 71 | extension = dict( 72 | identifier=ext['id'], 73 | name=ext['name'], 74 | content_type=ext['content_type'], 75 | area=ext.get('area', None), 76 | version=ext['version'], 77 | description=ext.get('description', None), 78 | marketing_url=ext.get('marketing_url', None), 79 | thumbnail_url=ext.get('thumbnail_url', None), 80 | valid_until='2030-05-16T18:35:33.000Z', 81 | url=extension_url, 82 | download_url='https://github.com/{github}/archive/{version}.zip'.format(**ext), 83 | latest_url=extension_info_url, 84 | flags=ext.get('flags', []), 85 | dock_icon=ext.get('dock_icon', {}), 86 | layerable=ext.get('layerable', None), 87 | deletion_warning=ext.get('deletion_warning', None), 88 | ) 89 | 90 | # mfa-link (2FA manager) has no expiration 91 | if ext.get('no_expire', False): 92 | extension.pop('valid_until', None) 93 | 94 | # Strip empty values 95 | extension = {k: v for k, v in extension.items() if v} 96 | 97 | # That is very strange, StandardNotes does not upload some npm packages 98 | # when extensions get updated. We'll have to handle them by git. 99 | # git clone --branch {version} --depth 1 {github_url} 100 | run([ 101 | 'git', '-c', 'advice.detachedHead=false', 102 | 'clone', 103 | '--branch', ext['version'], 104 | '--depth', '1', 105 | 'https://github.com/{github}.git'.format(**ext), 106 | ]) 107 | shutil.rmtree(os.path.join(public_dir, repo_name, '.git'), ignore_errors=False, onerror=onerror) 108 | 109 | # Generate JSON file for each extension 110 | with open(os.path.join(public_dir, repo_name, 'index.json'), 'w') as wf: 111 | json.dump(extension, wf) 112 | 113 | extensions.append(extension) 114 | print('Loaded extension: {}'.format(ext['name'])) 115 | 116 | os.chdir('..') 117 | 118 | # Generate the index JSON file 119 | with open(os.path.join(public_dir, 'index.json'), 'w') as wf: 120 | json.dump( 121 | dict( 122 | content_type='SN|Repo', 123 | valid_until='2030-05-16T18:35:33.000Z', 124 | packages=extensions, 125 | ), 126 | wf, 127 | ) 128 | 129 | # Cleanup unnecessary files 130 | print('Cleaning up...') 131 | for filename in ['README.md', 'Gruntfile.js', '.babelrc', 'package.json', '*.map', 'src', 'vendor']: 132 | for matched_fpath in glob.glob(f'public/*/{filename}'): 133 | if os.path.isdir(matched_fpath): 134 | shutil.rmtree(matched_fpath, ignore_errors=False, onerror=onerror) 135 | elif os.path.isfile(matched_fpath): 136 | os.remove(matched_fpath) 137 | else: 138 | continue 139 | 140 | print(f'> Removed {matched_fpath}') 141 | 142 | # Distribute header rules for Netlify 143 | shutil.copyfile('_headers', os.path.join(public_dir, '_headers')) 144 | 145 | print('Build finished') 146 | 147 | 148 | if __name__ == '__main__': 149 | main(os.getenv('URL', 'https://snext.netlify.app/')) 150 | 151 | -------------------------------------------------------------------------------- /extensions/action-bar.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.action-bar" 2 | npm = "sn-action-bar" 3 | github = "sn-extensions/action-bar" 4 | main = "index.html" 5 | name = "Action Bar" 6 | content_type = "SN|Component" 7 | area = "editor-stack" 8 | version = "1.3.1" 9 | marketing_url = "https://standardnotes.org/extensions/action-bar" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/components/action-bar.jpg" 11 | description = "Useful utility bar with information about the current note as well as actions like duplicate, copy, and save." 12 | flags = [] 13 | -------------------------------------------------------------------------------- /extensions/advanced-markdown-editor.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.advanced-markdown-editor" 2 | npm = "sn-advanced-markdown-editor" 3 | github = "standardnotes/markdown-pro" 4 | main = "index.html" 5 | name = "Advanced Markdown Editor" 6 | content_type = "SN|Component" 7 | area = "editor-editor" 8 | version = "1.3.9" 9 | marketing_url = "https://standardnotes.org/extensions/advanced-markdown" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/editors/adv-markdown.jpg" 11 | description = "A fully featured Markdown editor that supports live preview, a styling toolbar, and split pane support." 12 | flags = [] 13 | -------------------------------------------------------------------------------- /extensions/autobiography-theme.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.theme-autobiography" 2 | npm = "sn-theme-autobiography" 3 | github = "sn-extensions/autobiography-theme" 4 | main = "dist/dist.css" 5 | 6 | name = "Autobiography" 7 | content_type = "SN|Theme" 8 | version = "1.0.0" 9 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/themes/autobiography.jpg" 10 | description = "A theme for writers and readers." 11 | 12 | [dock_icon] 13 | type = "circle" 14 | background_color = "#9D7441" 15 | foreground_color = "#ECE4DB" 16 | border_color = "#9D7441" 17 | -------------------------------------------------------------------------------- /extensions/autocomplete-tags.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.autocomplete-tags" 2 | npm = "sn-autocomplete-tags" 3 | github = "sn-extensions/autocomplete-tags" 4 | main = "index.html" 5 | name = "Quick Tags" 6 | content_type = "SN|Component" 7 | area = "note-tags" 8 | version = "1.3.2" 9 | marketing_url = "" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/components/autocomplete.jpg" 11 | description = "Work more efficiently by quickly selecting from a live list of tags while you type. Supports keyboard shortcuts and folders." 12 | flags = [] 13 | -------------------------------------------------------------------------------- /extensions/bold-editor.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.bold-editor" 2 | npm = "sn-bold-editor" 3 | github = "standardnotes/bold-editor" 4 | main = "dist/index.html" 5 | name = "Bold Editor" 6 | content_type = "SN|Component" 7 | area = "editor-editor" 8 | version = "1.1.0" 9 | marketing_url = "" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/editors/bold.jpg" 11 | description = "A simple and peaceful rich editor that helps you write and think clearly. Features FileSafe integration, so you can embed your encrypted images, videos, and audio recordings directly inline." 12 | flags = [] 13 | -------------------------------------------------------------------------------- /extensions/code-editor.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.code-editor" 2 | npm = "sn-code-editor" 3 | github = "sn-extensions/code-editor" 4 | main = "index.html" 5 | name = "Code Editor" 6 | content_type = "SN|Component" 7 | area = "editor-editor" 8 | version = "1.3.5" 9 | marketing_url = "https://standardnotes.org/extensions/code-editor" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/editors/code.jpg" 11 | description = "Syntax highlighting and convenient keyboard shortcuts for over 120 programming languages. Ideal for code snippets and procedures." 12 | -------------------------------------------------------------------------------- /extensions/dynamic-theme.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.theme-dynamic" 2 | npm = "sn-theme-dynamic" 3 | github = "sn-extensions/dynamic-theme" 4 | main = "dist/dist.css" 5 | 6 | name = "Dynamic" 7 | layerable = true 8 | content_type = "SN|Theme" 9 | version = "1.0.0" 10 | marketing_url = "https://standardnotes.org/extensions/dynamic" 11 | description = "A smart theme that minimizes the tags and notes panels when they are not in use." 12 | 13 | -------------------------------------------------------------------------------- /extensions/fancy-markdown-editor.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.fancy-markdown-editor" 2 | npm = "sn-fancy-markdown-editor" 3 | github = "sn-extensions/math-editor" 4 | main = "index.html" 5 | name = "Math Editor" 6 | content_type = "SN|Component" 7 | area = "editor-editor" 8 | version = "1.3.4" 9 | marketing_url = "https://standardnotes.org/extensions/math-editor" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/editors/fancy-markdown.jpg" 11 | description = "A beautiful split-pane Markdown editor with synced-scroll and LaTeX support. When LaTeX is detected, makes external render network request." 12 | -------------------------------------------------------------------------------- /extensions/file-safe.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.file-safe" 2 | npm = "sn-filesafe" 3 | github = "standardnotes/filesafe-bar" 4 | main = "dist/index.html" 5 | 6 | name = "FileSafe" 7 | content_type = "SN|Component" 8 | area = "editor-stack" 9 | version = "2.0.10" 10 | marketing_url = "https://standardnotes.org/extensions/filesafe" 11 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/FileSafe-banner.png" 12 | description = "Encrypted attachments for your notes using your Dropbox, Google Drive, or WebDAV server. Limited to 50MB per file." 13 | flags = [] 14 | -------------------------------------------------------------------------------- /extensions/focus-theme.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.theme-focus" 2 | npm = "sn-theme-focus" 3 | github = "sn-extensions/focus-theme" 4 | main = "dist/dist.css" 5 | 6 | name = "Focus" 7 | content_type = "SN|Theme" 8 | version = "1.2.3" 9 | marketing_url = "https://standardnotes.org/extensions/focused" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/themes/focus-with-mobile.jpg" 11 | description = "For when you need to go in." 12 | 13 | [dock_icon] 14 | type = "circle" 15 | background_color = "#a464c2" 16 | foreground_color = "#ffffff" 17 | border_color = "#a464c2" 18 | -------------------------------------------------------------------------------- /extensions/folders-component.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.folders-component" 2 | npm = "sn-folders-component" 3 | github = "sn-extensions/folders-component" 4 | main = "index.html" 5 | name = "Folders Component" 6 | content_type = "SN|Component" 7 | area = "tags-list" 8 | version = "1.3.5" 9 | marketing_url = "" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/components/folders.jpg" 11 | description = "Create nested folders from your tags with easy drag and drop. Folders also supports Smart Tags, which allow you to build custom filters for viewing your notes." 12 | flags = [] 13 | -------------------------------------------------------------------------------- /extensions/futura-theme.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.theme-futura" 2 | npm = "sn-futura-theme" 3 | github = "sn-extensions/futura-theme" 4 | main = "dist/dist.css" 5 | 6 | name = "Futura" 7 | content_type = "SN|Theme" 8 | version = "1.2.2" 9 | marketing_url = "https://standardnotes.org/extensions/futura" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/themes/futura-with-mobile.jpg" 11 | description = "Calm and relaxed. Take some time off." 12 | 13 | [dock_icon] 14 | type = "circle" 15 | background_color = "#fca429" 16 | foreground_color = "#ffffff" 17 | border_color = "#fca429" 18 | -------------------------------------------------------------------------------- /extensions/github-push.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.github-push" 2 | npm = "sn-github-push" 3 | github = "sn-extensions/github-push" 4 | main = "index.html" 5 | 6 | name = "GitHub Push" 7 | content_type = "SN|Component" 8 | area = "editor-stack" 9 | version = "1.2.1" 10 | marketing_url = "https://standardnotes.org/extensions/github-push" 11 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/components/github-push.jpg" 12 | description = "Push note changes to a public or private GitHub repository, with options for file extension and commit message." 13 | 14 | -------------------------------------------------------------------------------- /extensions/mfa-link.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.mfa-link" 2 | npm = "sn-mfa-link" 3 | github = "sn-extensions/mfa-link" 4 | main = "dist/index.html" 5 | name = "2FA Manager" 6 | content_type = "SN|Component" 7 | area = "modal" 8 | version = "1.2.2" 9 | description = "Configure two-factor authentication to add an extra level of security to your account." 10 | no_expire = true 11 | deletion_warning = "Deleting 2FA Manager will not disable 2FA from your account. To disable 2FA, first open 2FA Manager, then follow the prompts." 12 | -------------------------------------------------------------------------------- /extensions/midnight-theme.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.theme-midnight" 2 | npm = "sn-theme-midnight" 3 | github = "sn-extensions/midnight-theme" 4 | main = "dist/dist.css" 5 | 6 | name = "Midnight" 7 | content_type = "SN|Theme" 8 | version = "1.2.1" 9 | marketing_url = "https://standardnotes.org/extensions/midnight" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/themes/midnight-with-mobile.jpg" 11 | description = "Elegant utilitarianism." 12 | 13 | [dock_icon] 14 | type = "circle" 15 | background_color = "#086DD6" 16 | foreground_color = "#ffffff" 17 | border_color = "#086DD6" 18 | -------------------------------------------------------------------------------- /extensions/minimal-markdown-editor.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.minimal-markdown-editor" 2 | npm = "sn-minimal-markdown-editor" 3 | github = "sn-extensions/minimal-markdown-editor" 4 | main = "index.html" 5 | name = "Minimal Markdown Editor" 6 | content_type = "SN|Component" 7 | area = "editor-editor" 8 | version = "1.3.5" 9 | marketing_url = "https://standardnotes.org/extensions/minimal-markdown-editor" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/editors/min-markdown.jpg" 11 | description = "A minimal Markdown editor with live rendering and in-text search via Ctrl/Cmd + F" 12 | flags = [] 13 | -------------------------------------------------------------------------------- /extensions/no-distraction-theme.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.theme-no-distraction" 2 | npm = "sn-theme-no-distraction" 3 | github = "sn-extensions/no-distraction-theme" 4 | main = "dist/dist.css" 5 | 6 | name = "No Distraction" 7 | content_type = "SN|Theme" 8 | version = "1.2.2" 9 | layerable = true 10 | marketing_url = "https://standardnotes.org/extensions/no-distraction" 11 | description = "A theme for focusing on your writing." 12 | 13 | [dock_icon] 14 | type = "svg" 15 | source = "" 16 | -------------------------------------------------------------------------------- /extensions/plus-editor.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.plus-editor" 2 | npm = "sn-plus-editor" 3 | github = "sn-extensions/plus-editor" 4 | main = "index.html" 5 | name = "Plus Editor" 6 | content_type = "SN|Component" 7 | area = "editor-editor" 8 | version = "1.4.3" 9 | marketing_url = "https://standardnotes.org/extensions/plus-editor" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/editors/plus-editor.jpg" 11 | description = "From highlighting to custom font sizes and colors, to tables and lists, this editor is perfect for crafting any document." 12 | flags = [] 13 | -------------------------------------------------------------------------------- /extensions/secure-spreadsheets.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.standard-sheets" 2 | npm = "sn-spreadsheets" 3 | github = "standardnotes/secure-spreadsheets" 4 | main = "dist/index.html" 5 | name = "Secure Spreadsheets" 6 | content_type = "SN|Component" 7 | area = "editor-editor" 8 | version = "1.3.4" 9 | marketing_url = "" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/editors/spreadsheets.png" 11 | description = "A powerful spreadsheet editor with formatting and formula support. Not recommended for large data sets, as encryption of such data may decrease editor performance." 12 | flags = [] 13 | -------------------------------------------------------------------------------- /extensions/simple-markdown-editor.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.simple-markdown-editor" 2 | npm = "sn-simple-markdown-editor" 3 | github = "sn-extensions/markdown-basic" 4 | main = "dist/index.html" 5 | 6 | name = "Simple Markdown Editor" 7 | content_type = "SN|Component" 8 | area = "editor-editor" 9 | version = "1.3.6" 10 | marketing_url = "https://standardnotes.org/extensions/simple-markdown-editor" 11 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/editors/simple-markdown.jpg" 12 | description = "A Markdown editor with dynamic split-pane preview." 13 | flags = [] 14 | -------------------------------------------------------------------------------- /extensions/simple-task-editor.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.simple-task-editor" 2 | npm = "sn-simple-task-editor" 3 | github = "sn-extensions/simple-task-editor" 4 | main = "dist/index.html" 5 | name = "Simple Task Editor" 6 | content_type = "SN|Component" 7 | area = "editor-editor" 8 | version = "1.3.5" 9 | marketing_url = "https://standardnotes.org/extensions/simple-task-editor" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/editors/task-editor.jpg" 11 | description = "A great way to manage short-term and long-term to-do's. You can mark tasks as completed, change their order, and edit the text naturally in place." 12 | flags = [] 13 | -------------------------------------------------------------------------------- /extensions/solarized-dark-theme.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.theme-solarized-dark" 2 | npm = "sn-theme-solarized-dark" 3 | github = "sn-extensions/solarized-dark-theme" 4 | main = "dist/dist.css" 5 | 6 | name = "Solarized Dark" 7 | content_type = "SN|Theme" 8 | version = "1.2.1" 9 | marketing_url = "https://standardnotes.org/extensions/solarized-dark" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/themes/solarized-dark.jpg" 11 | description = "The perfect theme for any time." 12 | 13 | [dock_icon] 14 | type = "circle" 15 | background_color = "#2AA198" 16 | foreground_color = "#ffffff" 17 | border_color = "#2AA198" 18 | -------------------------------------------------------------------------------- /extensions/titanium-theme.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.theme-titanium" 2 | npm = "sn-theme-titanium" 3 | github = "sn-extensions/titanium-theme" 4 | main = "dist/dist.css" 5 | 6 | name = "Titanium" 7 | content_type = "SN|Theme" 8 | version = "1.2.2" 9 | marketing_url = "https://standardnotes.org/extensions/titanium" 10 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/themes/titanium-with-mobile.jpg" 11 | description = "Light on the eyes, heavy on the spirit." 12 | 13 | [dock_icon] 14 | type = "circle" 15 | background_color = "#6e2b9e" 16 | foreground_color = "#ffffff" 17 | border_color = "#6e2b9e" 18 | -------------------------------------------------------------------------------- /extensions/token-vault.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.token-vault" 2 | npm = "sn-token-vault" 3 | github = "sn-extensions/token-vault" 4 | main = "dist/index.html" 5 | name = "TokenVault" 6 | content_type = "SN|Component" 7 | area = "editor-editor" 8 | version = "1.0.5" 9 | thumbnail_url = "https://standard-notes.s3.amazonaws.com/screenshots/models/editors/token-vault.png" 10 | description = "Encrypt and protect your 2FA secrets for all your internet accounts. TokenVault handles your 2FA secrets so that you never lose them again, or have to start over when you get a new device." 11 | flags = [ "Beta",] 12 | -------------------------------------------------------------------------------- /extensions/vim-editor.toml: -------------------------------------------------------------------------------- 1 | id = "org.standardnotes.vim-editor" 2 | npm = "sn-vim-editor" 3 | github = "sn-extensions/vim-editor" 4 | main = "index.html" 5 | 6 | name = "Vim Editor" 7 | content_type = "SN|Component" 8 | area = "editor-editor" 9 | version = "1.3.2" 10 | marketing_url = "https://standardnotes.org/extensions/vim-editor" 11 | thumbnail_url = "https://s3.amazonaws.com/standard-notes/screenshots/models/editors/vim.jpg" 12 | description = "A code editor with Vim key bindings." 13 | flags = [] 14 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "python build.py" 3 | publish = "public" 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | toml==0.10.1 2 | requests==2.24.0 3 | -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | 3.7 2 | -------------------------------------------------------------------------------- /update.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | ''' 3 | Update all extensions to their latest release. 4 | This script only updates version numbers in .toml files, 5 | please remember to build again after the update. 6 | 7 | Caution: this script uses unauthenticated requests to call GitHub API, 8 | so it is limited by the same rate limit as unauthenticated users. 9 | Please don't run this script repeatedly in a short period. 10 | 11 | See https://developer.github.com/v3/#rate-limiting for more details. 12 | ''' 13 | import collections 14 | from http import HTTPStatus as hstatus 15 | import json 16 | import os 17 | 18 | import requests 19 | import toml 20 | 21 | 22 | def get_latest_version(repo): 23 | resp = requests.get( 24 | f'https://api.github.com/repos/{repo}/releases/latest', 25 | headers={ 26 | 'user-agent': 'snextensions-updater', 27 | }, 28 | ) 29 | if resp.status_code != hstatus.OK: 30 | raise Exception(f'Unexpected HTTP status: {resp.status_code}') 31 | 32 | return resp.json()['tag_name'] 33 | 34 | 35 | def main(): 36 | base_dir = os.path.dirname(os.path.abspath(__file__)) 37 | extension_dir = os.path.join(base_dir, 'extensions') 38 | 39 | # Read and parse all extension info 40 | for fname in os.listdir(extension_dir): 41 | if not fname.endswith('.toml'): 42 | continue 43 | 44 | with open(os.path.join(extension_dir, fname)) as rf: 45 | # Notice the `_dict`, this is to retain key order, 46 | # avoiding unnecessary diffs between commits 47 | ext = toml.load(rf, _dict=collections.OrderedDict) 48 | repo_name = ext['github'] 49 | version = ext['version'] 50 | 51 | try: 52 | latest_version = get_latest_version(repo_name) 53 | except Exception as e: 54 | print(f'❌ {repo_name} : Failed <{e}>') 55 | continue 56 | else: 57 | if latest_version == version: 58 | print(f'🟢 {repo_name} : {version} is already the latest version') 59 | continue 60 | 61 | with open(os.path.join(extension_dir, fname), 'w') as wf: 62 | ext['version'] = latest_version 63 | toml.dump(ext, wf) 64 | print(f'✅ {repo_name} : {version} => {latest_version}') 65 | 66 | 67 | if __name__ == '__main__': 68 | main() 69 | 70 | --------------------------------------------------------------------------------