├── .gitignore ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ └── release.yml ├── logo.png ├── .gitattributes ├── .vscodeignore ├── .vscode └── launch.json ├── snippets ├── jinja-snippets.json ├── django-snippets.json └── snippets.json ├── LICENSE ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.vsix 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: endlesstrax 2 | ko_fi: everydayronin -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EndlessTrax/python-template-snippets/HEAD/logo.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to automatically normalize line endings. 2 | * text=auto 3 | 4 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | .gitignore 4 | .gitattributes 5 | .git/** 6 | .github/** 7 | vsc-extension-quickstart.md 8 | **/*.map 9 | **/.DS_Store 10 | **/node_modules/** 11 | **/coverage/** 12 | **/test/** 13 | **/*.vsix 14 | -------------------------------------------------------------------------------- /.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 | "runtimeExecutable": "${execPath}", 13 | "args": [ 14 | "--extensionDevelopmentPath=${workspaceFolder}" 15 | ] 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | reviewers: 13 | - "endlesstrax" 14 | 15 | - package-ecosystem: "github-actions" 16 | directory: "/" 17 | schedule: 18 | interval: "weekly" 19 | reviewers: 20 | - "endlesstrax" 21 | -------------------------------------------------------------------------------- /snippets/jinja-snippets.json: -------------------------------------------------------------------------------- 1 | { 2 | "Jinja - Link Static File": { 3 | "scope": "html", 4 | "prefix": "ptj-url", 5 | "body": [ 6 | "{{ url_for('static', filename='$1') }}$0" 7 | ], 8 | "description": "Link static file with Jinja" 9 | }, 10 | 11 | "Jinja - Macros": { 12 | "scope": "html", 13 | "prefix": "ptj-mac", 14 | "body": [ 15 | "{% macro $1 %}", 16 | "\t$0", 17 | "{% endmacro %}" 18 | ], 19 | "description": "Adds macro tags" 20 | }, 21 | 22 | "Jinja - Comments": { 23 | "scope": "html", 24 | "prefix": "ptj-com", 25 | "body": [ 26 | "{# $0 #}" 27 | ], 28 | "description": "Adds Jinja comment" 29 | }, 30 | "Jinja - Set Variable": { 31 | "scope": "html", 32 | "prefix": "ptj-set", 33 | "body": [ 34 | "{% set $1 = $2 %}" 35 | ], 36 | "description": "Adds Jinja set variable" 37 | } 38 | } -------------------------------------------------------------------------------- /snippets/django-snippets.json: -------------------------------------------------------------------------------- 1 | { 2 | "Django - Url Tags": { 3 | "scope": "html", 4 | "prefix": "ptd-url", 5 | "body": ["{% url '$1' $2%}$0"], 6 | "description": "Adds Django URL block" 7 | }, 8 | 9 | "Django - Load Tags": { 10 | "scope": "html", 11 | "prefix": "ptd-load", 12 | "body": ["{% load $1 %}$0"], 13 | "description": "Adds Load Block" 14 | }, 15 | 16 | "Django - Static File": { 17 | "scope": "html", 18 | "prefix": "ptd-stat", 19 | "body": ["{% static '$1' %}$0"], 20 | "description": "Adds Static File Block" 21 | }, 22 | 23 | "Django - Include Tags": { 24 | "scope": "html", 25 | "prefix": "ptd-inc", 26 | "body": ["{% include '$1' %}$0"], 27 | "description": "Adds Include File Block" 28 | }, 29 | 30 | "Django - Firstof Tags": { 31 | "scope": "html", 32 | "prefix": "ptd-firstof", 33 | "body": ["{% firstof $1 $2 %}$0"], 34 | "description": "Adds Firstof Block" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ricky White 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 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Extension 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v4 17 | 18 | - name: Setup Node.js 19 | uses: actions/setup-node@v4 20 | with: 21 | node-version: '20' 22 | cache: 'npm' 23 | 24 | - name: Install dependencies 25 | run: npm install 26 | 27 | - name: Get version from tag 28 | id: get_version 29 | run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT 30 | 31 | - name: Verify version matches package.json 32 | run: | 33 | PACKAGE_VERSION=$(node -p "require('./package.json').version") 34 | TAG_VERSION="${{ steps.get_version.outputs.VERSION }}" 35 | if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then 36 | echo "Error: package.json version ($PACKAGE_VERSION) does not match tag version ($TAG_VERSION)" 37 | exit 1 38 | fi 39 | 40 | - name: Package extension 41 | run: npx vsce package 42 | 43 | - name: Publish to VS Code Marketplace 44 | run: npx vsce publish 45 | env: 46 | VSCE_PAT: ${{ secrets.MARKETPLACE_TOKEN }} 47 | 48 | - name: Create GitHub Release 49 | run: | 50 | gh release create ${{ github.ref_name }} \ 51 | --title "Release ${{ github.ref_name }}" \ 52 | --generate-notes \ 53 | *.vsix 54 | env: 55 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "python-template-snippets", 3 | "displayName": "Python Template Snippets", 4 | "description": "A snippet extension for Jinja and Django templating engines.", 5 | "keywords": [ 6 | "Python", 7 | "Snippets", 8 | "Django", 9 | "Jinja2", 10 | "Flask", 11 | "Web Development" 12 | ], 13 | "version": "1.4.1", 14 | "publisher": "RickyWhite", 15 | "license": "MIT", 16 | "engines": { 17 | "vscode": "^1.84.0" 18 | }, 19 | "categories": [ 20 | "Snippets" 21 | ], 22 | "galleryBanner": { 23 | "color": "#0d1117", 24 | "theme": "dark" 25 | }, 26 | "badges": [ 27 | { 28 | "url": "https://img.shields.io/github/stars/EndlessTrax/python-template-snippets?style=social", 29 | "href": "https://github.com/EndlessTrax/python-template-snippets", 30 | "description": "Star on GitHub" 31 | } 32 | ], 33 | "sponsor": { 34 | "url": "https://github.com/sponsors/EndlessTrax" 35 | }, 36 | "qna": "marketplace", 37 | "contributes": { 38 | "snippets": [ 39 | { 40 | "language": "html", 41 | "path": "./snippets/snippets.json" 42 | }, 43 | { 44 | "language": "html", 45 | "path": "./snippets/jinja-snippets.json" 46 | }, 47 | { 48 | "language": "html", 49 | "path": "./snippets/django-snippets.json" 50 | } 51 | ] 52 | }, 53 | "icon": "logo.png", 54 | "repository": { 55 | "type": "git", 56 | "url": "https://github.com/EndlessTrax/python-template-snippets" 57 | }, 58 | "homepage": "https://github.com/EndlessTrax/python-template-snippets/blob/master/README.md", 59 | "devDependencies": { 60 | "@vscode/vsce": "^3.7.1" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /snippets/snippets.json: -------------------------------------------------------------------------------- 1 | { 2 | "New HTML Template": { 3 | "scope": "html", 4 | "prefix": "ptnew", 5 | "body": [ 6 | "{% extends '${1:base.html}' %}", 7 | "\n", 8 | "{% block content %}", 9 | "\t$2", 10 | "{% endblock content %}", 11 | "\n", 12 | "{% block scripts %}", 13 | "{% endblock scripts %}" 14 | ], 15 | "description": "Creates a simple base Jinja / Django template for a new HTML file" 16 | }, 17 | 18 | "Template Variable": { 19 | "scope": "html", 20 | "prefix": "ptvar", 21 | "body": [ 22 | "{{ $1 }}$0" 23 | ], 24 | "description": "Adds variable tags" 25 | }, 26 | 27 | "Template Variable with Filter": { 28 | "scope": "html", 29 | "prefix": "ptfilt", 30 | "body": [ 31 | "{{ $1 | $2 }}$0" 32 | ], 33 | "description": "Adds variable tags with filter" 34 | }, 35 | 36 | "Template Code Block": { 37 | "scope": "html", 38 | "prefix": "ptcode", 39 | "body": [ 40 | "{% $1 %}$0" 41 | ], 42 | "description": "Adds code block tags" 43 | }, 44 | 45 | "Template Block Tag": { 46 | "scope": "html", 47 | "prefix": "ptblock", 48 | "body": [ 49 | "{% block $1 %}", 50 | "\t$0", 51 | "{% endblock $1 %}" 52 | ], 53 | "description": "Adds code block tags" 54 | }, 55 | 56 | "Template For Loop": { 57 | "scope": "html", 58 | "prefix": "ptfor", 59 | "body": [ 60 | "{% for $1 in $2 %}", 61 | "\t$0", 62 | "{% endfor %}" 63 | ], 64 | "description": "Adds for loop" 65 | }, 66 | 67 | "Template If Statement": { 68 | "scope": "html", 69 | "prefix": "ptif", 70 | "body": [ 71 | "{% if $1 %}", 72 | "\t$0", 73 | "{% endif %}" 74 | ], 75 | "description": "Adds if statement" 76 | }, 77 | 78 | "Template Super": { 79 | "scope": "html", 80 | "prefix": "ptsup", 81 | "body": [ 82 | "{{ super() }}" 83 | ], 84 | "description": "Adds Super() tag" 85 | }, 86 | 87 | "Template Extends": { 88 | "scope": "html", 89 | "prefix": "ptext", 90 | "body": [ 91 | "{% extends '${1:base.html}' %}$0" 92 | ], 93 | "description": "Add extends tag" 94 | }, 95 | 96 | "Template If/Else Statement": { 97 | "scope": "html", 98 | "prefix": "ptifel", 99 | "body": [ 100 | "{% if $1 %}", 101 | "\t$2", 102 | "{% else %}", 103 | "\t$3", 104 | "{% endif %}" 105 | ], 106 | "description": "Adds if/else statement" 107 | }, 108 | 109 | "Template If/Elif/Else Statement": { 110 | "scope": "html", 111 | "prefix": "ptelif", 112 | "body": [ 113 | "{% if $1 %}", 114 | "\t$2", 115 | "{% elif $3 %}", 116 | "\t$4", 117 | "{% else %}", 118 | "\t$5", 119 | "{% endif %}" 120 | ], 121 | "description": "Adds if/elif/else statement" 122 | }, 123 | 124 | "Template With Statement": { 125 | "scope": "html", 126 | "prefix": "ptwith", 127 | "body": [ 128 | "{% with $1 %}", 129 | "\t$0", 130 | "{% endwith %}" 131 | ], 132 | "description": "Adds with statement" 133 | } 134 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | Python Template Snippets Logo 3 | 4 | # Python Template Snippets 5 | 6 | ✨ **Supercharge your template development workflow** ✨ 7 | 8 | A comprehensive VS Code snippet collection for **Jinja2** and **Django** template engines. 9 | 10 | [![GitHub stars](https://img.shields.io/github/stars/EndlessTrax/python-template-snippets?style=social)](https://github.com/EndlessTrax/python-template-snippets) 11 | [![VS Code Marketplace](https://img.shields.io/badge/VS%20Code-Marketplace-blue?logo=visual-studio-code)](https://marketplace.visualstudio.com/items?itemName=RickyWhite.python-template-snippets) 12 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) 13 | 14 |
15 | 16 | --- 17 | 18 | ## 🚀 Why Use This Extension? 19 | 20 | Writing template code can be tedious with all those brackets, tags, and syntax. This extension eliminates the repetitive typing by providing **smart, tab-completion snippets** for common Jinja2 and Django template patterns. 21 | 22 | **Stop typing this:** 23 | ```html 24 | {% for item in items %} 25 | 26 | {% endfor %} 27 | ``` 28 | 29 | **Start typing this:** 30 | ``` 31 | ptfor → Tab → Fill in the blanks! 32 | ``` 33 | 34 | ### ✨ Features 35 | 36 | - 🎯 **20+ carefully crafted snippets** for Jinja2 and Django 37 | - ⚡ **Lightning-fast** - Type `pt` prefix and let IntelliSense do the rest 38 | - 🎨 **Smart cursor positioning** - Jump to exactly where you need to type 39 | - 🔄 **Multi-cursor support** - Tab between placeholders seamlessly 40 | - 🛠️ **Framework-agnostic** - Works with Flask, Django, FastAPI, and any Python web framework 41 | - 📦 **Zero configuration** - Works out of the box 42 | 43 | --- 44 | 45 | ## 📦 Installation 46 | 47 | ### From VS Code Marketplace (Recommended) 48 | 49 | 1. Open VS Code 50 | 2. Press `Ctrl+P` / `Cmd+P` 51 | 3. Type `ext install RickyWhite.python-template-snippets` 52 | 4. Press Enter and reload VS Code 53 | 54 | ### Manual Installation 55 | 56 | 1. Download the latest `.vsix` from [Releases](https://github.com/EndlessTrax/python-template-snippets/releases) 57 | 2. Open VS Code 58 | 3. Go to Extensions (`Ctrl+Shift+X` / `Cmd+Shift+X`) 59 | 4. Click the `...` menu → `Install from VSIX` 60 | 5. Select the downloaded file 61 | 62 | --- 63 | 64 | ## 🎯 Quick Start 65 | 66 | 1. Open any HTML file in VS Code 67 | 2. Type `pt` to see available snippets 68 | 3. Select a snippet from the IntelliSense menu (or type the full prefix) 69 | 4. Press `Tab` to trigger the snippet 70 | 5. Fill in the placeholders and press `Tab` to jump between them 71 | 72 | ### 💡 Pro Tip 73 | Enable tab completion in your VS Code settings for the best experience: 74 | ```json 75 | { 76 | "editor.tabCompletion": "on" 77 | } 78 | ``` 79 | 80 | --- 81 | 82 | ## 📚 Snippet Reference 83 | 84 | All snippets use the `pt` prefix (short for "Python Template"). Here's the complete reference: 85 | 86 | ### 🌐 General Snippets 87 | *Works with both Jinja2 and Django* 88 | 89 | | Prefix | Description | Output | 90 | |--------|-------------|---------| 91 | | `ptnew` | New HTML template file | Complete template with extends and blocks | 92 | | `ptvar` | Template variable | `{{ variable }}` | 93 | | `ptfilt` | Variable with filter | `{{ variable \| filter }}` | 94 | | `ptcode` | Code block tag | `{% code %}` | 95 | | `ptblock` | Block tag | `{% block name %}...{% endblock %}` | 96 | | `ptext` | Extends tag | `{% extends 'base.html' %}` | 97 | | `ptsup` | Super function | `{{ super() }}` | 98 | | `ptfor` | For loop | `{% for item in items %}...{% endfor %}` | 99 | | `ptif` | If statement | `{% if condition %}...{% endif %}` | 100 | | `ptifel` | If/else statement | `{% if %}...{% else %}...{% endif %}` | 101 | | `ptelif` | If/elif/else statement | `{% if %}...{% elif %}...{% else %}...{% endif %}` | 102 | | `ptwith` | With statement | `{% with variable %}...{% endwith %}` | 103 | 104 | ### 🔧 Jinja2-Specific Snippets 105 | *For Flask, FastAPI, and other Jinja2 projects* 106 | 107 | | Prefix | Description | Output | 108 | |--------|-------------|---------| 109 | | `ptj-url` | Static file URL | `{{ url_for('static', filename='file.css') }}` | 110 | | `ptj-mac` | Macro definition | `{% macro name %}...{% endmacro %}` | 111 | | `ptj-com` | Comment | `{# comment #}` | 112 | | `ptj-set` | Set variable | `{% set var = value %}` | 113 | 114 | ### 🎨 Django-Specific Snippets 115 | *For Django projects* 116 | 117 | | Prefix | Description | Output | 118 | |--------|-------------|---------| 119 | | `ptd-url` | URL tag | `{% url 'view-name' args %}` | 120 | | `ptd-load` | Load tag library | `{% load static %}` | 121 | | `ptd-stat` | Static file | `{% static 'path/to/file' %}` | 122 | | `ptd-inc` | Include template | `{% include 'template.html' %}` | 123 | | `ptd-firstof` | First of variables | `{% firstof var1 var2 %}` | 124 | 125 | --- 126 | 127 | ## 💻 Usage Examples 128 | 129 | ### Creating a New Template 130 | 131 | Type `ptnew` and press Tab: 132 | 133 | ```html 134 | {% extends 'base.html' %} 135 | 136 | {% block content %} 137 | 138 | {% endblock content %} 139 | 140 | {% block scripts %} 141 | {% endblock scripts %} 142 | ``` 143 | 144 | ### Adding a For Loop 145 | 146 | Type `ptfor` and press Tab: 147 | 148 | ```html 149 | {% for item in items %} 150 | 151 | {% endfor %} 152 | ``` 153 | 154 | Then tab through: `item` → `items` → loop body 155 | 156 | ### Django Static File 157 | 158 | Type `ptd-stat` and press Tab: 159 | 160 | ```html 161 | {% static 'css/style.css' %} 162 | ``` 163 | 164 | --- 165 | 166 | ## 🤝 Contributing 167 | 168 | Found a bug? Want a new snippet? Contributions are welcome! 169 | 170 | 1. **Report Issues**: [Open an issue](https://github.com/EndlessTrax/python-template-snippets/issues) 171 | 2. **Request Features**: Have an idea? Share it! 172 | 3. **Submit PRs**: Fork, code, and submit a pull request 173 | 174 | ### Suggesting New Snippets 175 | 176 | When requesting a new snippet, please include: 177 | - The template syntax you want added 178 | - Which framework it's for (Jinja2/Django/both) 179 | - A brief description of what it does 180 | 181 | --- 182 | 183 | ## 📝 Release Notes 184 | 185 | See [GitHub Releases](https://github.com/EndlessTrax/python-template-snippets/releases) for the detailed version history and changelog. 186 | 187 | --- 188 | 189 | ## 💖 Support This Project 190 | 191 | This extension is free and open source. If you find it helpful, consider: 192 | 193 | - ⭐ [Starring the repo](https://github.com/EndlessTrax/python-template-snippets) 194 | - 💰 [Sponsoring on GitHub](https://github.com/sponsors/EndlessTrax) 195 | - 🐦 [Sharing on social media](https://twitter.com/intent/tweet?text=Check%20out%20Python%20Template%20Snippets%20for%20VS%20Code!&url=https://github.com/EndlessTrax/python-template-snippets) 196 | - 📝 [Writing a review](https://marketplace.visualstudio.com/items?itemName=RickyWhite.python-template-snippets&ssr=false#review-details) 197 | 198 | --- 199 | 200 | ## 📜 License 201 | 202 | MIT © [Ricky White](https://github.com/EndlessTrax) 203 | 204 | --- 205 | 206 | ## 🙏 Acknowledgments 207 | 208 | Created and maintained by [Ricky White](https://twitter.com/endlesstrax) 209 | 210 | Special thanks to all [contributors](https://github.com/EndlessTrax/python-template-snippets/graphs/contributors) who have helped improve this extension! 211 | 212 | --- 213 | 214 |
215 | 216 | **Happy Coding! 🎉** 217 | 218 | Made with ❤️ for the Python community 219 | 220 |
221 | --------------------------------------------------------------------------------