├── .gitignore ├── media ├── icon.png └── demo-video.gif ├── .gitattributes ├── .vscodeignore ├── snippets ├── groq.code-snippets ├── structure.code-snippets └── schema.code-snippets ├── .vscode └── launch.json ├── generateDocumentation.js ├── CHANGELOG.md ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.vsix 3 | documented.md 4 | test-yo -------------------------------------------------------------------------------- /media/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hdoro/sanity-snippets/HEAD/media/icon.png -------------------------------------------------------------------------------- /media/demo-video.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hdoro/sanity-snippets/HEAD/media/demo-video.gif -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to automatically normalize line endings. 2 | * text=auto 3 | 4 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | .gitignore 4 | vsc-extension-quickstart.md 5 | documented.md 6 | media/demo-video.gif -------------------------------------------------------------------------------- /snippets/groq.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "GROQ block drafts constraint": { 3 | "scope": "javascript,typescript", 4 | "description": "Constraint for groq queries to prevent or limit to drafted documents", 5 | "prefix": "groqDraftConstraint", 6 | "body": [ 7 | "!(_id in path(\"drafts.**\"))" 8 | ] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ] 15 | } 16 | ] 17 | } -------------------------------------------------------------------------------- /snippets/structure.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "Component document view": { 3 | "scope": "javascript,typescript", 4 | "description": "Add a view to a document with a React component", 5 | "prefix": "sanityViewComponent", 6 | "body": [ 7 | "S.view", 8 | "\t.component(${1:Component})", 9 | "\t.title(${2:\"My component view\"})", 10 | "\t.icon(${3:FiEdit})" 11 | ] 12 | }, 13 | "Structure document list": { 14 | "scope": "javascript,typescript", 15 | "description": "Adds a listItem in your desk structure for custom document list. Perfect for filtering by document values or adding docs from multiple types", 16 | "prefix": "sanityDocList", 17 | "body": [ 18 | "S.listItem()", 19 | "\t.title(${1:\"Authors and contributors\"})", 20 | "\t.icon(${2:FiEdit})", 21 | "\t.child(", 22 | "\t\tS.documentList()", 23 | "\t\t\t.title(${1})", 24 | "\t\t\t.filter(${3:'_type in $types'})", 25 | "\t\t\t.params(${4:{ types: ['author', 'contributor'] \\}})", 26 | "\t\t\t.menuItems(...S.documentTypeList(${5:'menuSchemaType'}).getMenuItems())", 27 | "\t)," 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /generateDocumentation.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | 3 | /** 4 | * Transforms .code-snippets files in JSON objects. If it breaks, make sure we don't have any dangling commas. 5 | */ 6 | function getSnippets(path) { 7 | const textContent = fs.readFileSync(path, { encoding: 'utf-8' }) 8 | // Remove comments from text 9 | const commentsRegEx = new RegExp(" *\/\/[^\n]*", 'g') 10 | return JSON.parse(textContent.replace(commentsRegEx, '')) 11 | } 12 | 13 | const schemaSnippets = getSnippets('./snippets/schema.code-snippets') 14 | const groqSnippets = getSnippets('./snippets/groq.code-snippets') 15 | const structureSnippets = getSnippets('./snippets/structure.code-snippets') 16 | const allSnippets = {...schemaSnippets, ...groqSnippets, ...structureSnippets} 17 | 18 | function generateSnippetDocumentation(key) { 19 | const snippet = allSnippets[key] 20 | return `- **${key}** (\`${snippet.prefix}\`): ${snippet.description}` 21 | } 22 | 23 | const documented = Object.keys(allSnippets).map(generateSnippetDocumentation).join('\n') 24 | 25 | fs.writeFileSync('./documented.md', documented, { encoding: 'utf-8'}) 26 | 27 | console.log("Snippets list generated!\n\n👉 Now copy documented.md into README.md") -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [1.0.0] - 2021-07-09 9 | - Changed `sanitySchema` to not include a field by default. Instead, users can use `sanityFld`, `sanityArrFld` and other to create their own fields when they're done with the basic properties of a new schema. 10 | - Added a select box to `sanityFld`'s type property to make it easier and faster to build with default types, [as suggested by Surjith](https://github.com/hdoro/sanity-snippets/issues/7). 11 | 12 | **Why v1?** Well, people have been using this plugin for a while and it's battle-tested enough. Also, this version introduces the first "breaking" change, so there we go! 13 | 14 | ## [0.2.0] - 2021-06-24 15 | - New `sanityListArray` snippet for adding a list of values to a string/number/array field 16 | - Changed `sanitySchema` default type to `document` [as proposed by Simeon Griggs](https://github.com/hdoro/sanity-snippets/pull/6) 17 | - Automatic casing/formatting of name/title pairs [as proposed by Alejandro Rojas](https://github.com/hdoro/sanity-snippets/issues/4) 18 | 19 | ## [0.1.5] - 2020-11-17 20 | 21 | ### Added 22 | - New snippets by [Arjen](https://github.com/Aratramba) 23 | - `sanityPreviewSelect` 24 | - `sanityPreviewSelectPrepare` 25 | - `sanitySelect` 26 | - `sanityPrepare`; 27 | - and `sanityObjFld` 28 | 29 | ## [0.1.4] - 2020-10-23 30 | 31 | ### Fixed 32 | - Typo in the `sanityCollapse` snippet - [Jayne Mast](https://github.com/jayne-mast) 33 | 34 | ## [0.1.0] - 2020-10-23 35 | 36 | - Initial release with a small set of snippets 🎉 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sanity-snippets", 3 | "displayName": "Sanity.io snippets", 4 | "publisher": "hdoro", 5 | "description": "Speed up your Sanity.io development with snippets tailored for building schemas and desk structures ✨", 6 | "version": "1.0.0", 7 | "author": { 8 | "email": "opensource@hdoro.dev", 9 | "name": "Henrique Doro", 10 | "url": "https://hdoro.dev" 11 | }, 12 | "repository": "https://github.com/hdoro/sanity-snippets", 13 | "icon": "media/icon.png", 14 | "badges": [ 15 | { 16 | "description": "Install on VS Code Marketplace", 17 | "url": "https://vsmarketplacebadge.apphb.com/version-short/hdoro.sanity-snippets.svg?style=flat-square", 18 | "href": "https://marketplace.visualstudio.com/items?itemName=hdoro.sanity-snippets" 19 | } 20 | ], 21 | "engines": { 22 | "vscode": "^1.50.0" 23 | }, 24 | "categories": [ 25 | "Snippets" 26 | ], 27 | "keywords": [ 28 | "Sanity.io", 29 | "Headless CMS", 30 | "Snippets" 31 | ], 32 | "contributes": { 33 | "snippets": [ 34 | { 35 | "language": "javascript", 36 | "path": "./snippets/schema.code-snippets" 37 | }, 38 | { 39 | "language": "typescript", 40 | "path": "./snippets/schema.code-snippets" 41 | }, 42 | { 43 | "language": "javascript", 44 | "path": "./snippets/structure.code-snippets" 45 | }, 46 | { 47 | "language": "typescript", 48 | "path": "./snippets/structure.code-snippets" 49 | }, 50 | { 51 | "language": "javascript", 52 | "path": "./snippets/groq.code-snippets" 53 | }, 54 | { 55 | "language": "typescript", 56 | "path": "./snippets/groq.code-snippets" 57 | }, 58 | { 59 | "language": "groq", 60 | "path": "./snippets/groq.code-snippets" 61 | } 62 | ] 63 | }, 64 | "scripts": { 65 | "packageAndPublish": "vsce package && vsce publish" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sanity.io VS Code snippets 2 | 3 | [![Download it at the Visual Studio Marketplace](https://vsmarketplacebadge.apphb.com/version-short/hdoro.sanity-snippets.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=hdoro.sanity-snippets) 4 | 5 | A set of useful snippets to speed up your Sanity.io development. I've been using some of these snippets for over 3 years now, and they drastically increase my capacity to deliver fast and precisely, hope you enjoy 😊 6 | 7 | ![GIF showing a demo of the snippets in action - it creates an article schema in ~40s](https://raw.githubusercontent.com/hdoro/sanity-snippets/main/media/demo-video.gif) 8 | 9 | ## The snippets available 10 | 11 | Every snippets starts with either `sanity(...)` or `groq(...)`, so you know they won't collide with your other snippets. They are enabled for Javascript & Typescript files, reach out if you need to enable them for other extensions. 12 | 13 | - **Sanity Schema** (`sanitySchema`): Create a simple schema for the CMS (document, object or image) 14 | - **Sanity Field** (`sanityFld`): Add a field to a sanity object / document 15 | - **Sanity Custom Description** (`sanityDesc`): Add a custom description to a field, document or object 16 | - **Sanity Optional** (`sanityOptional`): Add a cue that a field is optional 17 | - **Sanity Optional Encouraged** (`sanityOptionalEncouraged`): Add a cue that a field is optional, but encourage writing it 18 | - **Sanity Tip description** (`sanityTip`): Add a tip as a field's description 19 | - **Sanity Fieldset** (`sanityFieldset`): Add fieldsets to a sanity object / document 20 | - **Sanity Collapse Field** (`sanityCollapse`): Make a given object field collapsible to help editors scroll less through the document 21 | - **Sanity Required** (`sanityRequired`): Make a given field required 22 | - **Sanity Array Validation (min & max)** (`sanityArrValidation`): Validate an array field based on its length 23 | - **Sanity Basic Array** (`sanityArrFld`): Create a basic array field in Sanity 24 | - **Sanity Reference Field** (`sanityRefFld`): Create a basic reference field in Sanity 25 | - **Sanity Preview with Select** (`sanityPreviewSelect`): Add a basic preview with selection object in Sanity 26 | - **Sanity Select Object** (`sanitySelect`): Add a basic selection object for preview in Sanity 27 | - **Sanity Prepare Function** (`sanityPrepare`): Add a prepare function for preview in Sanity 28 | - **Sanity Preview with Select and Prepare*** (`sanityPreviewSelectPrepare`): Add a preview with selection object and prepare function in Sanity 29 | - **Sanity Object Field** (`sanityObjFld`): Create a basic object field in Sanity 30 | - **Sanity list of options** (`sanityListArray`): Add a list array to string/number/array types to render specific options to users. 31 | 🚨 For arrays, this only works if it's an array of strings, in which case it'll render checkboxes 32 | - **GROQ block drafts constraint** (`groqDraftConstraint`): Constraint for groq queries to prevent or limit to drafted documents 33 | - **Component document view** (`sanityViewComponent`): Add a view to a document with a React component 34 | - **Structure document list** (`sanityDocList`): Adds a listItem in your desk structure for custom document list. Perfect for filtering by document values or adding docs from multiple types 35 | 36 | Feel free to contribute your snippets! 37 | 38 | ## This is a work in progress 39 | 40 | Your feedback is very much appreciated as long as it's respectful and inclusive :) 41 | -------------------------------------------------------------------------------- /snippets/schema.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "Sanity Schema": { 3 | "description": "Create a simple schema for the CMS (document, object or image)", 4 | "prefix": "sanitySchema", 5 | "body": [ 6 | "export default {", 7 | "\tname: '${2:$TM_FILENAME_BASE}',", 8 | "\ttitle: '${3:${TM_FILENAME_BASE/(^.)|([A-Z](?=[a-z]))/${1:/upcase}${2:+ }${2:/downcase}/g}}',", 9 | "\ttype: '${1|document,object,image|}',", 10 | "\tfields: [", 11 | "\t\t$0", 12 | "\t],", 13 | "}" 14 | ] 15 | }, 16 | "Sanity Field": { 17 | "description": "Add a field to a sanity object / document", 18 | "prefix": "sanityFld", 19 | "body": [ 20 | "{", 21 | "\tname: '${1:name}',", 22 | "\ttitle: '${2:${1/(^.)|([A-Z](?=[a-z]))/${1:/upcase}${2:+ }${2:/downcase}/g}}',", 23 | "\ttype: '${3|block,boolean,date,datetime,file,geopoint,image,number,slug,string,text,url,yourOwnType™|}',", 24 | "}," 25 | ] 26 | }, 27 | "Sanity Custom Description": { 28 | "description": "Add a custom description to a field, document or object", 29 | "prefix": "sanityDesc", 30 | "body": ["description: '${1:description}',"] 31 | }, 32 | "Sanity Optional": { 33 | "description": "Add a cue that a field is optional", 34 | "prefix": "sanityOptional", 35 | "body": ["description: '${1:❓ Optional}${0}',"] 36 | }, 37 | "Sanity Optional Encouraged": { 38 | "description": "Add a cue that a field is optional, but encourage writing it", 39 | "prefix": "sanityOptionalEncouraged", 40 | "body": ["description: '${1:⚡ Optional but highly encouraged}${0}',"] 41 | }, 42 | "Sanity Tip description": { 43 | "description": "Add a tip as a field's description", 44 | "prefix": "sanityTip", 45 | "body": ["description: '💡 ${1:tip here}',"] 46 | }, 47 | "Sanity Fieldset": { 48 | "description": "Add fieldsets to a sanity object / document", 49 | "prefix": "sanityFieldset", 50 | "body": [ 51 | "fieldsets: [", 52 | "\t{", 53 | "\t\tname: '${1:name}',", 54 | "\t\ttitle: '${2:${1/(^.)|([A-Z](?=[a-z]))/${1:/upcase}${2:+ }${2:/downcase}/g}}',", 55 | "\t\t${0:options: { collapsible: true, collapsed: true }},", 56 | "\t},", 57 | "]," 58 | ] 59 | }, 60 | "Sanity Collapse Field": { 61 | "description": "Make a given object field collapsible to help editors scroll less through the document", 62 | "prefix": "sanityCollapse", 63 | "body": ["options: { collapsible: true, ${0:collapsed: false,}},"] 64 | }, 65 | "Sanity Required": { 66 | "description": "Make a given field required", 67 | "prefix": "sanityRequired", 68 | "body": ["validation: Rule => Rule.required(),"] 69 | }, 70 | "Sanity Array Validation (min & max)": { 71 | "description": "Validate an array field based on its length", 72 | "prefix": "sanityArrValidation", 73 | "body": [ 74 | "validation: Rule => [", 75 | "\tRule.required()", 76 | "\t\t.min(${1:1})", 77 | "\t\t.max(${2:2})", 78 | "\t\t.${4:error}('Required field with at least ${1:1} and at most ${2:2} ${3:entries}.'),", 79 | "\t${0:Rule.unique()}", 80 | "]" 81 | ] 82 | }, 83 | "Sanity Basic Array": { 84 | "description": "Create a basic array field in Sanity", 85 | "prefix": "sanityArrFld", 86 | "body": [ 87 | "{", 88 | "\tname: '${1:name}',", 89 | "\ttitle: '${2:${1/(^.)|([A-Z](?=[a-z]))/${1:/upcase}${2:+ }${2:/downcase}/g}}',", 90 | "\ttype: 'array',", 91 | "\tof: [{ type: '${3:string}' }],", 92 | "}," 93 | ] 94 | }, 95 | "Sanity Reference Field": { 96 | "description": "Create a basic reference field in Sanity", 97 | "prefix": "sanityRefFld", 98 | "body": [ 99 | "{", 100 | "\tname: '${1:name}',", 101 | "\ttitle: '${2:${1/(^.)|([A-Z](?=[a-z]))/${1:/upcase}${2:+ }${2:/downcase}/g}}',", 102 | "\ttype: 'reference',", 103 | "\tto: [{ type: '${3:author}' }],", 104 | "}," 105 | ] 106 | }, 107 | "Sanity Preview with Select": { 108 | "description": "Add a basic preview with selection object in Sanity", 109 | "prefix": "sanityPreviewSelect", 110 | "body": [ 111 | "preview: {", 112 | "\tselect: {", 113 | "\t\ttitle: '${1:title}',", 114 | "\t\tsubtitle: '${2:subtitle}',", 115 | "\t\tmedia: '${3:image}',", 116 | "\t},", 117 | "}," 118 | ] 119 | }, 120 | "Sanity Select Object": { 121 | "description": "Add a basic selection object for preview in Sanity", 122 | "prefix": "sanitySelect", 123 | "body": [ 124 | "\tselect: {", 125 | "\t\ttitle: '${1:title}',", 126 | "\t\tsubtitle: '${2:subtitle}',", 127 | "\t\tmedia: '${3:image}',", 128 | "\t}," 129 | ] 130 | }, 131 | "Sanity Prepare Function": { 132 | "description": "Add a prepare function for preview in Sanity", 133 | "prefix": "sanityPrepare", 134 | "body": [ 135 | "prepare({ title, subtitle, media }) {", 136 | "\treturn {", 137 | "\t\ttitle: `${1:${title\\}}`,", 138 | "\t\tsubtitle: `${2:${subtitle\\}}`,", 139 | "\t\tmedia,", 140 | "\t};", 141 | "}," 142 | ] 143 | }, 144 | "Sanity Preview with Select and Prepare": { 145 | "description": "Add a preview with selection object and prepare function in Sanity", 146 | "prefix": "sanityPreviewSelectPrepare", 147 | "body": [ 148 | "preview: {", 149 | "\tselect: {", 150 | "\t\ttitle: '${1:title}',", 151 | "\t\tsubtitle: '${2:subtitle}',", 152 | "\t\tmedia: '${3:image}',", 153 | "\t},", 154 | "\tprepare({ title, subtitle, media }) {", 155 | "\t\treturn {", 156 | "\t\t\ttitle: `${4:\\${title\\}}`,", 157 | "\t\t\tsubtitle: `${5:\\${subtitle\\}}`,", 158 | "\t\t\tmedia,", 159 | "\t\t};", 160 | "\t},", 161 | "}," 162 | ] 163 | }, 164 | "Sanity Object Field": { 165 | "description": "Create a basic object field in Sanity", 166 | "prefix": "sanityObjFld", 167 | "body": [ 168 | "{", 169 | "\tname: '${1:name}',", 170 | "\ttitle: '${2:title}',", 171 | "\ttype: 'object',", 172 | "\tfields: [", 173 | "\t\t$3", 174 | "\t],", 175 | "}," 176 | ] 177 | }, 178 | "Sanity list of options": { 179 | "description": "Add a list array to string/number/array types to render specific options to users.\n🚨 For arrays, this only works if it's an array of strings, in which case it'll render checkboxes", 180 | "prefix": "sanityListArray", 181 | "body": [ 182 | "options: {", 183 | "\tlayout: '${3|radio,select|}',", 184 | "\tlist: [", 185 | "\t\t{ value: '${1:option1}', title: '${2:${1/(^.)|([A-Z](?=[a-z]))/${1:/upcase}${2:+ }${2:/downcase}/g}}' },", 186 | "\t],", 187 | "}," 188 | ] 189 | } 190 | } 191 | --------------------------------------------------------------------------------