├── .github ├── pull_request_template.md └── workflows │ └── main.yml ├── .gitignore ├── Parse Packages.command ├── README.md ├── images └── Screenshot.png ├── packages.plist └── test.py /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | > **Note**: Please add new plugins and scripts at the end of the `plugins = ( ... )` or `scripts = ( ... )` lists. 2 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - glyphs3 7 | - master 8 | pull_request: 9 | branches: 10 | - glyphs3 11 | - master 12 | workflow_dispatch: 13 | 14 | jobs: 15 | build: 16 | name: Validation 17 | runs-on: macos-latest 18 | steps: 19 | - uses: actions/checkout@v2 20 | - name: Lint Property List 21 | run: plutil -lint packages.plist 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /Parse Packages.command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "`dirname "$0"`" 3 | pwd 4 | echo 5 | echo PARSING PACKAGES.PLIST... 6 | plutil -lint packages.plist 7 | echo 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Glyphs Packages 2 | 3 | Welcome to the Glyphs packages repository! 4 | This repository contains the index of plug-ins and scrips for the Plugin Manager. 5 | In Glyphs, open the Plugin Manager with *Window > Plugin Manager*. 6 | 7 | Screenshot of the Plugin Manager window 8 | 9 | See the Glyphs Handbook for details on the [Plugin Manager](https://handbook.glyphsapp.com/plugin-manager/) and learn more about extensions in the [“Extending Glyphs” tutorial](https://glyphsapp.com/learn/extending-glyphs) ([Español](https://glyphsapp.com/es/learn/extending-glyphs), [Français](https://glyphsapp.com/fr/learn/extending-glyphs), [中文](https://glyphsapp.com/zh/learn/extending-glyphs)). 10 | 11 | If you have a plug-in or collection of scripts you want to share with the community, consider adding it to the `packages.plist` file in this repository and submitting a pull request. 12 | Feel free to ask on the [Glyphs Forum](https://forum.glyphsapp.com) if you have any questions. 13 | 14 | ## Adding Plug-ins and Script Collections 15 | 16 | The index of plug-ins and scripts is stored in the `packages.plist` file. 17 | Add new plug-ins at the end of the `plugins = ( ... )` list and new script collections at the end of the `scripts = ( ... )` list. 18 | The entry is a “dictionary”, a list of key-value pairs. 19 | The required and optional keys are described below in detail. 20 | Place a comma (`,`) after your entry. 21 | Here is an example: 22 | 23 | ``` 24 | { 25 | titles = { 26 | en = "Some Plug-in"; 27 | }; 28 | url = "https://github.com/example/some-plugin"; 29 | path = "SomePlugin.glyphsPlugin"; 30 | descriptions = { 31 | en = "Some short description."; 32 | }; 33 | }, 34 | ``` 35 | 36 | ### `url` (string, required) 37 | 38 | The URL points to the Git repository of your package. 39 | For a repository on GitHub, this URL looks like this: `"https://github.com/YOUR_USER_NAME/YOUR_REPOSITORY_NAME"`, for example: `"https://github.com/example/some-plugin"` (with no slash `/` at the end). 40 | 41 | ### `titles` (dictionary of strings, required) 42 | 43 | The title of your extension. 44 | This is a dictionary where the keys are locale identifiers from the list below, and the values are the title in that language. 45 | For example: 46 | 47 | ``` 48 | titles = { 49 | de = "Beispiel"; 50 | en = "Example"; 51 | }; 52 | ``` 53 | 54 | The following locale identifiers are supported: 55 | 56 | - `ar`: Arabic 57 | - `cs`: Czech 58 | - `de`: German 59 | - `en`: English 60 | - `es`: Spanish 61 | - `fr`: French 62 | - `it`: Italian 63 | - `ja`: Japanese 64 | - `ko`: Korean 65 | - `pt`: Portuguese 66 | - `ru`: Russian 67 | - `tr`: Turkish 68 | - `zh-Hans`: Chinese (simplified) 69 | - `zh-Hant`: Chinese (traditional) 70 | 71 | ### `descriptions` (dictionary of strings, required) 72 | 73 | The description can be written in multiple languages, just like the `title`. 74 | Briefly describe what your extension does and how it can be accessed. 75 | For example, for a reporter plug-in, write a description like: 76 | 77 | ``` 78 | descriptions = { 79 | en = "*View > Some Reporter* draws something useful."; 80 | }; 81 | ``` 82 | 83 | You can use basic Markdown formatting in the description: 84 | 85 | - `*italic*` (for text that appears in the user interface) 86 | - `**bold**` 87 | - `` `code` `` 88 | - `[link text](https://example.com)` 89 | 90 | Write the description for a language on a single line. 91 | Insert a line break by writing `\n` or an empty separator line with `\n\n`. 92 | 93 | ### `path` (string, only required for plug-ins) 94 | 95 | The path points to the plug-in bundle in your repository. 96 | The bundle is the file with a name like `*.glyphPlugin`, `*.glyphReporter`, … 97 | 98 | ``` 99 | path = "SomePlugin.glyphsPlugin"; 100 | ``` 101 | 102 | If the bundle is in a folder, include the full path with slashes: 103 | 104 | ``` 105 | path = "Plugin/SomePlugin.glyphsPlugin"; 106 | ``` 107 | 108 | ### `installName` (string, only required for scripts) 109 | 110 | The name of the script collection in the *Script* menu in Glyphs. 111 | This is also the name of the folder in which the script collection will be installed in Glyphs “Scripts” folder, which you can view by choosing *Script > Open Scripts Folder*. 112 | 113 | Make sure no other script collection is using the same `installName`. 114 | Typically, this is done by using your name or the name of your company: 115 | 116 | ``` 117 | installName = "Some Name"; 118 | ``` 119 | 120 | ### `screenshot` (string, optional) 121 | 122 | A URL to an image illustrating the use case of the extension. 123 | 124 | ### `branch` (string, optional) 125 | 126 | The name of the branch in your Git repository. 127 | If unset, the default branch is used. 128 | 129 | ### `donationURL` (string, optional) 130 | 131 | A URL to a micropayment site. 132 | The Plugin Manager will present a donation link next to your package entry. 133 | 134 | ### `minVersion` & `maxVersion` (string, optional) 135 | 136 | The minimum and maximum version of Glyphs with which your extension is compatible. 137 | You can set one of the two, both, or none. 138 | The value is the build number of Glyphs which is written in parentheses in *Glyphs > About Glyphs*, for example, `"3306"`. 139 | Users running a version of Glyphs that does not match these min/max values will not see the extension in the Plugin Manager. 140 | 141 | ### `minGlyphsVersion` & `maxGlyphsVersion` (string, optional) 142 | 143 | The same as `minVersion` and `maxVersion`, but using the major.minor.patch notation. 144 | For example: `"3.2.1"`. 145 | 146 | ### `minSystemVersion` & `maxSystemVersion` (string, optional) 147 | 148 | The same as `minGlyphsVersion` and `maxGlyphsVersion`, but for the version of macOS. 149 | For example: `"12.0"`. 150 | 151 | ### `dependencies` (list of strings, optional) 152 | 153 | The `identifier` values for the modules that an extension depends on are listed in the `dependencies`. 154 | For example, `dependencies = (vanilla, fontTools);`. 155 | See the end of the `packages.plist` for a list of available modules. 156 | 157 | If you have a dependency for which there is currently no module, open a new issue on this repository or contact us on the [Glyphs Forum](https://forum.glyphsapp.com). 158 | 159 | You can also create your own module and depend on it from a plug-in or script collection. 160 | This is useful if you share code across plug-ins or if you want to offer a Python module as part of your extension. 161 | 162 | ### `identifier` (string, optional) 163 | 164 | The internal identifier that Glyphs uses. 165 | It may not contain the characters `<`, `>`, or `/` and must be less than 50 characters in length. 166 | In general, it is best to just use the characters `a`-`z`, `A`-`Z`, `0`-`9`, `-`, and `_`. 167 | 168 | This is mostly used by modules so that they can be included as dependencies. 169 | The identifier is also useful for plug-ins to provide a short ID that can be used for Glyph’s deep links: 170 | 171 | 172 | ``` 173 | glyphsapp3://showplugin/some-identifier 174 | ``` 175 | 176 | which opens Glyphs and shows the plug-in in the Plugin Manager. 177 | Or: 178 | 179 | ``` 180 | glyphsapp3://installplugin/some-identifier 181 | ``` 182 | 183 | which does the same, but also prompts the user to install the plug-in. 184 | If no `identifier` is set, the deep links use the URL-encoded `"en"` title instead. 185 | 186 | ### `archs` (list of strings, optional) 187 | 188 | If the extension works only with ARM (Apple Silicon: M1, M2, …) or Intel (x86) processors, specify either `arm` or `intel`: 189 | 190 | ``` 191 | archs = (arm); 192 | ``` 193 | 194 | ### `hidden` (string, optional) 195 | 196 | Hides the extension from the Plugin Manager by setting it to `"1"`. 197 | Useful for modules that should not be installed by users directly, but only as part of the `dependencies` system. 198 | 199 | ## Validating the Package Index 200 | 201 | After editing the `packages.plist` file, double-click the file `Parse Packages.command`. 202 | This will validate the `packages.plist` to make sure you did not add any errors. 203 | A window will appear. 204 | If the file is valid, the following message will appear: 205 | 206 | ``` 207 | PARSING PACKAGES.PLIST... 208 | packages.plist: OK 209 | ``` 210 | 211 | If there is an error, you might get an error message that points you to the location in the file that is invalid. 212 | If you need help, feel free to contact us on the [Glyphs Forum](https://forum.glyphsapp.com). 213 | 214 | ## Examples 215 | 216 | Plug-in: 217 | 218 | { 219 | titles = { 220 | en = "Noodler"; 221 | }; 222 | url = "https://github.com/mekkablue/Noodler"; 223 | descriptions = { 224 | en = "*Filter > Noodler* turns monolines of all selected glyphs into noodles."; 225 | }; 226 | path = "Noodler.glyphsFilter"; 227 | screenshot = "https://raw.githubusercontent.com/mekkablue/Noodler/master/Noodler.png"; 228 | minVersion = 895; 229 | }, 230 | 231 | Outdated plug-in that is only shown in older versions of Glyphs: 232 | 233 | { 234 | titles = { 235 | de = "Nudler (veraltete Version)"; 236 | en = "Noodler (outdated version)"; 237 | } 238 | url = "https://github.com/mekkablue/Noodler"; 239 | descriptions = { 240 | de = "Diese Version von Nudler ist veraltet. Bitte aktualisieren Sie Glyphs, umd die neueste Version nutzen zu können."; 241 | en = "This is an old version of Noodler. Consider updating Glyphs to use the latest version of the plug-in."; 242 | }; 243 | path = "Noodler_OLD.glyphsFilter"; 244 | branch = "deprecated"; 245 | screenshot = "https://raw.githubusercontent.com/mekkablue/Noodler/master/Noodler.png"; 246 | maxVersion = 894; 247 | }, 248 | 249 | Script collection: 250 | 251 | { 252 | descriptions = { 253 | en = "Some Name’s collection of Glyphs scripts."; 254 | }; 255 | installName = "Some Name"; 256 | titles = { 257 | en = "Some Name’s Scripts"; 258 | }; 259 | url = "https://github.com/example/Glyphs-Scripts"; 260 | }, 261 | -------------------------------------------------------------------------------- /images/Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schriftgestalt/glyphs-packages/3b3f8817dbd0f0a4f9d2e7b822937fb7620e6673/images/Screenshot.png -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | 4 | import sys 5 | try: 6 | from Foundation import NSDictionary 7 | z = NSDictionary.dictionaryWithContentsOfFile_("packages.plist") 8 | except: 9 | from pbPlist import pbPlist 10 | z = pbPlist.PBPlist("packages.plist") 11 | 12 | #print(type(z["packages"])) 13 | packageDict = z["packages"] 14 | for packageType in packageDict.keys(): 15 | packages = packageDict[packageType] 16 | for package in packages: 17 | if not (package.get("title", None) or package.get("titles", None)): 18 | print(f"missing title in {package}") 19 | if not package.get("url", None): 20 | print(f"missing url in {package}") 21 | if not package.get("path", None) and packageType == "plugins": 22 | print(f"missing path in {package}") 23 | --------------------------------------------------------------------------------