Skip to content

Commit

Permalink
fix: manifest schema validation (#28)
Browse files Browse the repository at this point in the history
* fix: layout could be empty, and could not end with .json

* fix: .gif should only be allowed for state image

* fix: align error messages

* fix: re-add plugin UUID to manifest and schema

* feat: add image dimensions to schema

---------

Co-authored-by: Richard Herman <[email protected]>
  • Loading branch information
GeekyEggo and GeekyEggo authored Jan 29, 2024
1 parent 0cfc804 commit ea2c3f7
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 48 deletions.
84 changes: 58 additions & 26 deletions schemas/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,18 @@
"description": "Path to the image, with the **file extension omitted**, that will be displayed in the Stream Deck application in the circular canvas that represents the dial of the action. The image must fulfill the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 72x72 px and 144x144 px (@2x).\n\nNB: Can be overridden by the user in the Stream Deck application.\n\n**Examples:**\n- assets/actions/mute/encoder-icon\n- imgs/join-voice-chat-encoder",
"filePath": {
"extensions": [
".gif",
".svg",
".png"
],
"includeExtension": false
},
"imageDimensions": [
72,
72
],
"markdownDescription": "Path to the image, with the **file extension omitted**, that will be displayed in the Stream Deck application in the circular canvas that represents the dial of the action. The image must fulfill the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 72x72 px and 144x144 px (@2x).\n\nNB: Can be overridden by the user in the Stream Deck application.\n\n**Examples:**\n- assets/actions/mute/encoder-icon\n- imgs/join-voice-chat-encoder",
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Gg][Ii][Ff])|([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$",
"errorMessage": "String must be a .gif, .svg, or .png file located within the plugin's directory, with the file extension omitted"
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$",
"errorMessage": "String must reference .svg, or .png file in the plugin directory, with the file extension omitted."
},
"StackColor": {
"type": "string",
Expand Down Expand Up @@ -98,6 +101,10 @@
"background": {
"type": "string",
"description": "Path to the image, with the **file extension omitted**, that will be displayed on the touchscreen behind the action's layout. The image must fulfill the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 200x100 px and 400x200 px (@2x).\n\nNB: Can be overridden by the user in the Stream Deck application.\n\n**Examples:**\n- assets/backgrounds/main\n- imgs/bright-blue-bg",
"imageDimensions": [
200,
100
],
"filePath": {
"extensions": [
".png",
Expand All @@ -107,7 +114,7 @@
},
"markdownDescription": "Path to the image, with the **file extension omitted**, that will be displayed on the touchscreen behind the action's layout. The image must fulfill the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 200x100 px and 400x200 px (@2x).\n\nNB: Can be overridden by the user in the Stream Deck application.\n\n**Examples:**\n- assets/backgrounds/main\n- imgs/bright-blue-bg",
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Pp][Nn][Gg])|([Ss][Vv][Gg]))$).*$",
"errorMessage": "String must be a .png, or .svg file located within the plugin's directory, with the file extension omitted"
"errorMessage": "String must reference .png, or .svg file in the plugin directory, with the file extension omitted."
},
"layout": {
"type": "string",
Expand All @@ -121,8 +128,8 @@
"$C1",
"custom.json"
],
"pattern": "^((?![\\.]*[\\\\\\/]+).*\\.([Jj][Ss][Oo][Nn]))|(\\$(X1|A0|A1|B1|B2|C1))$",
"errorMessage": "String must be a pre-defined layout, or a .json file located within the plugin's directory",
"pattern": "^(^(?![\\.]*[\\\\\\/]+).+\\.([Jj][Ss][Oo][Nn])$)|(\\$(X1|A0|A1|B1|B2|C1))$",
"errorMessage": "String must reference .json file in the plugin directory, or a pre-defined layout.",
"markdownDescription": "Name of a pre-defined layout, or the path to a JSON file that details a custom layout and its components, to be rendered on the action's touchscreen canvas.\n\n**Pre-defined Layouts:**\n- `$X1`, layout with the title at the top and the icon beneath it in the center.\n- `$A0`, layout with the title at the top and a full-width image canvas beneath it in the center.\n- `$A1`, layout with the title at the top, the icon on the left, and text value on the right.\n- `$B1`, layout with the title at the top, the icon on the left, and a text value on the right with a progress bar beneath it.\n- `$B2`, layout with the title at the top, the icon on the left, and a text value on the right with a gradient progress bar beneath it.\n- `$C1`, layout with the title at the top, and two rows that display an icon on the left and progress bar on the right (i.e. a double progress bar layout).\n\n**Examples:**\n- $A1\n- layouts/my-custom-layout.json"
}
},
Expand All @@ -135,15 +142,18 @@
"description": "Path to the image, with the **file extension omitted**, that will be displayed next to the action in the Stream Deck application's action list. The image must adhere to the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 20x20 px and 40x40 px (@2x).\n- Be monochromatic, with foreground color of #EFEFEF and a transparent background.\n\n**Examples:**\n- assets/counter\n- imgs/actions/mute",
"filePath": {
"extensions": [
".gif",
".svg",
".png"
],
"includeExtension": false
},
"imageDimensions": [
20,
20
],
"markdownDescription": "Path to the image, with the **file extension omitted**, that will be displayed next to the action in the Stream Deck application's action list. The image must adhere to the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 20x20 px and 40x40 px (@2x).\n- Be monochromatic, with foreground color of #EFEFEF and a transparent background.\n\n**Examples:**\n- assets/counter\n- imgs/actions/mute",
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Gg][Ii][Ff])|([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$",
"errorMessage": "String must be a .gif, .svg, or .png file located within the plugin's directory, with the file extension omitted"
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$",
"errorMessage": "String must reference .svg, or .png file in the plugin directory, with the file extension omitted."
},
"Name": {
"type": "string",
Expand All @@ -162,7 +172,7 @@
},
"markdownDescription": "Optional path to the HTML file that represents the property inspector for this action; this is displayed to the user in the Stream Deck application when they add the action, allowing them to configure the action's settings. When `undefined`, the manifest's top-level `PropertyInspectorPath` is used, otherwise none.\n\nNB: Path should be relative to the root of the plugin's folder, with no leading slash.\n\n**Examples:**\n- mute.html\n- actions/join-voice-chat/settings.html",
"pattern": "^(?![~\\.]*[\\\\\\/]+).*\\.(([Hh][Tt][Mm])|([Hh][Tt][Mm][Ll]))$",
"errorMessage": "String must be a .htm, or .html file located within the plugin's directory"
"errorMessage": "String must reference .htm, or .html file in the plugin directory."
},
"States": {
"type": "array",
Expand Down Expand Up @@ -198,7 +208,7 @@
},
"Image": {
"type": "string",
"description": "Path to the image, with the **file extension omitted**, that will be displayed on the Stream Deck when this action's state is active. The image must adhere to the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 72x72 px and 144x144 px (@2x).\n\nNB: Can be overridden by the user in the Stream Deck application.\n\n**Examples:**\n- assets/counter-key\n- assets/icons/mute",
"description": "Path to the image, with the **file extension omitted**, that will be displayed on the Stream Deck when this action's state is active. The image must adhere to the following style guidelines.\n- Be in .GIF, .PNG or .SVG format.\n- Be provided in two sizes, 72x72 px and 144x144 px (@2x).\n\nNB: Can be overridden by the user in the Stream Deck application.\n\n**Examples:**\n- assets/counter-key\n- assets/icons/mute",
"filePath": {
"extensions": [
".gif",
Expand All @@ -207,24 +217,31 @@
],
"includeExtension": false
},
"markdownDescription": "Path to the image, with the **file extension omitted**, that will be displayed on the Stream Deck when this action's state is active. The image must adhere to the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 72x72 px and 144x144 px (@2x).\n\nNB: Can be overridden by the user in the Stream Deck application.\n\n**Examples:**\n- assets/counter-key\n- assets/icons/mute",
"imageDimensions": [
72,
72
],
"markdownDescription": "Path to the image, with the **file extension omitted**, that will be displayed on the Stream Deck when this action's state is active. The image must adhere to the following style guidelines.\n- Be in .GIF, .PNG or .SVG format.\n- Be provided in two sizes, 72x72 px and 144x144 px (@2x).\n\nNB: Can be overridden by the user in the Stream Deck application.\n\n**Examples:**\n- assets/counter-key\n- assets/icons/mute",
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Gg][Ii][Ff])|([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$",
"errorMessage": "String must be a .gif, .svg, or .png file located within the plugin's directory, with the file extension omitted"
"errorMessage": "String must reference .gif, .svg, or .png file in the plugin directory, with the file extension omitted."
},
"MultiActionImage": {
"type": "string",
"description": "Path to the image, with the **file extension omitted**, that will be displayed when the action is being viewed as part of a multi-action. The image must adhere to the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 72x72 px and 144x144 px (@2x).\n\nNB: Can be overridden by the user in the Stream Deck application.\n\n**Examples:**\n- assets/counter-key\n- assets/icons/mute",
"filePath": {
"extensions": [
".gif",
".svg",
".png"
],
"includeExtension": false
},
"imageDimensions": [
72,
72
],
"markdownDescription": "Path to the image, with the **file extension omitted**, that will be displayed when the action is being viewed as part of a multi-action. The image must adhere to the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 72x72 px and 144x144 px (@2x).\n\nNB: Can be overridden by the user in the Stream Deck application.\n\n**Examples:**\n- assets/counter-key\n- assets/icons/mute",
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Gg][Ii][Ff])|([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$",
"errorMessage": "String must be a .gif, .svg, or .png file located within the plugin's directory, with the file extension omitted"
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$",
"errorMessage": "String must reference .svg, or .png file in the plugin directory, with the file extension omitted."
},
"Name": {
"type": "string",
Expand Down Expand Up @@ -354,33 +371,37 @@
],
"includeExtension": false
},
"imageDimensions": [
28,
28
],
"markdownDescription": "Path to the image, with the **file extension omitted**, that will be displayed next to the action list group within the Stream Deck application. The icon should accurately represent the plugin, and enable users to quickly identify the plugin. The icon must adhere to the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 28x28 px and 56x56 px (@2x).\n- Be monochromatic, with foreground color of #DFDFDF and a transparent background.\n\n**Examples**:\n- assets/category-icon\n- imgs/category",
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$",
"errorMessage": "String must be a .svg, or .png file located within the plugin's directory, with the file extension omitted"
"errorMessage": "String must reference .svg, or .png file in the plugin directory, with the file extension omitted."
},
"CodePath": {
"type": "string",
"description": "Path to the plugin's main entry point; this is executed when the Stream Deck application starts the plugin.\n\n**Examples**:\n- index.js\n- Counter\n- Counter.exe",
"filePath": true,
"markdownDescription": "Path to the plugin's main entry point; this is executed when the Stream Deck application starts the plugin.\n\n**Examples**:\n- index.js\n- Counter\n- Counter.exe",
"pattern": "^(?![~\\.]*[\\\\\\/]+).*$",
"errorMessage": "String must be a file located within the plugins's directory"
"errorMessage": "String must reference file in the plugin directory."
},
"CodePathMac": {
"type": "string",
"description": "Path to the plugin's entry point specific to macOS; this is executed when the Stream Deck application starts the plugin on macOS.\n\n**Examples:**\n- index.js\n- Counter",
"filePath": true,
"markdownDescription": "Path to the plugin's entry point specific to macOS; this is executed when the Stream Deck application starts the plugin on macOS.\n\n**Examples:**\n- index.js\n- Counter",
"pattern": "^(?![~\\.]*[\\\\\\/]+).*$",
"errorMessage": "String must be a file located within the plugins's directory"
"errorMessage": "String must reference file in the plugin directory."
},
"CodePathWin": {
"type": "string",
"description": "Path to the plugin's entry point specific to Windows; this is executed when the Stream Deck application starts the plugin on Windows.\n\n**Examples:**\n- index.js\n- Counter.exe",
"filePath": true,
"markdownDescription": "Path to the plugin's entry point specific to Windows; this is executed when the Stream Deck application starts the plugin on Windows.\n\n**Examples:**\n- index.js\n- Counter.exe",
"pattern": "^(?![~\\.]*[\\\\\\/]+).*$",
"errorMessage": "String must be a file located within the plugins's directory"
"errorMessage": "String must reference file in the plugin directory."
},
"DefaultWindowSize": {
"type": "array",
Expand Down Expand Up @@ -408,15 +429,18 @@
"description": "Path to the image, with the **file extension omitted**, that will be displayed on the Marketplace. The icon should accurately represent the plugin, stand out, and enable users to quickly identify the plugin. The icon must adhere to the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 288x288 px and 512x512 px (@2x).\n\n**Examples**: assets/plugin-icon imgs/plugin",
"filePath": {
"extensions": [
".gif",
".svg",
".png"
],
"includeExtension": false
},
"imageDimensions": [
288,
288
],
"markdownDescription": "Path to the image, with the **file extension omitted**, that will be displayed on the Marketplace. The icon should accurately represent the plugin, stand out, and enable users to quickly identify the plugin. The icon must adhere to the following style guidelines.\n- Be in .PNG or .SVG format.\n- Be provided in two sizes, 288x288 px and 512x512 px (@2x).\n\n**Examples**: assets/plugin-icon imgs/plugin",
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Gg][Ii][Ff])|([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$",
"errorMessage": "String must be a .gif, .svg, or .png file located within the plugin's directory, with the file extension omitted"
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Ss][Vv][Gg])|([Pp][Nn][Gg]))$).*$",
"errorMessage": "String must reference .svg, or .png file in the plugin directory, with the file extension omitted."
},
"Name": {
"type": "string",
Expand Down Expand Up @@ -523,7 +547,7 @@
},
"markdownDescription": "Path to the `.streamDeckProfile`, with the **file extension omitted**, that contains the profiles layout and action settings.\n\n**Examples:**\n- assets/main-profile\n- profiles/super-cool-profile",
"pattern": "^(?![~\\.]*[\\\\\\/]+)(?!.*\\.(([Ss][Tt][Rr][Ee][Aa][Mm][Dd][Ee][Cc][Kk][Pp][Rr][Oo][Ff][Ii][Ll][Ee]))$).*$",
"errorMessage": "String must be a .streamDeckProfile file located within the plugin's directory, with the file extension omitted"
"errorMessage": "String must reference .streamDeckProfile file in the plugin directory, with the file extension omitted."
},
"Readonly": {
"type": "boolean",
Expand Down Expand Up @@ -552,7 +576,7 @@
},
"markdownDescription": "Optional path to the HTML file that represents the property inspector for all actions; this is displayed to the user in the Stream Deck application when they add an action, allowing them to configure the action's settings.\n\nNB: Path should be relative to the root of the plugin's folder, with no leading slash.\n\n **Examples:**\n- mute.html\n- actions/join-voice-chat/settings.html\n\n**Also see:**\n- `streamDeck.ui.onSendToPlugin(...)`",
"pattern": "^(?![~\\.]*[\\\\\\/]+).*\\.(([Hh][Tt][Mm])|([Hh][Tt][Mm][Ll]))$",
"errorMessage": "String must be a .htm, or .html file located within the plugin's directory"
"errorMessage": "String must reference .htm, or .html file in the plugin directory."
},
"SDKVersion": {
"type": "number",
Expand Down Expand Up @@ -585,14 +609,21 @@
"description": "Link to the plugin's website.\n\n**Examples**:\n- https://elgato.com\n- https://corsair.com",
"markdownDescription": "Link to the plugin's website.\n\n**Examples**:\n- https://elgato.com\n- https://corsair.com"
},
"UUID": {
"type": "string",
"description": "Unique identifier of the plugin, represented in reverse-DNS format.\n\n**Allowed characters:**\n- Lowercase alphanumeric characters (a-z, 0-9)\n- Hyphens (-)\n- Underscores (_)\n- Periods (.)\n\n**Examples:**\n- com.elgato.wavelink\n- com.elgato.discord\n- tv.twitch",
"pattern": "^([a-z0-9\\-_]+)(\\.[a-z0-9\\-_]+)+$",
"errorMessage": "String must use reverse DNS format, and must only contain lowercase alphanumeric characters (a-z, 0-9), hyphens (-), underscores (_), and periods (.)",
"markdownDescription": "Unique identifier of the plugin, represented in reverse-DNS format.\n\n**Allowed characters:**\n- Lowercase alphanumeric characters (a-z, 0-9)\n- Hyphens (-)\n- Underscores (_)\n- Periods (.)\n\n**Examples:**\n- com.elgato.wavelink\n- com.elgato.discord\n- tv.twitch"
},
"Version": {
"type": "string",
"description": "Version of the plugin, represented as a semantic version, excluding pre-release values (https://semver.org). The version can also include an optional build number.\n\n**Examples:**\n- 1.0.3 ✅\n- 0.0.99.123 ✅\n- 2.1.9-beta1 ❌",
"examples": [
"1.0.0"
],
"pattern": "^\\d+(\\.\\d+){2,3}$",
"errorMessage": "String must be a semantic version (pre-releases are not permitted)",
"errorMessage": "String must be semantic version (pre-releases are not permitted)",
"markdownDescription": "Version of the plugin, represented as a semantic version, excluding pre-release values (https://semver.org). The version can also include an optional build number.\n\n**Examples:**\n- 1.0.3 ✅\n- 0.0.99.123 ✅\n- 2.1.9-beta1 ❌"
}
},
Expand All @@ -606,6 +637,7 @@
"OS",
"SDKVersion",
"Software",
"UUID",
"Version"
],
"additionalProperties": false,
Expand Down
Loading

0 comments on commit ea2c3f7

Please sign in to comment.