├── .gitattributes ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── assets └── icon.png ├── deno.json ├── deno.lock ├── package-lock.json ├── package.json ├── src ├── app.ts ├── deps.ts ├── docgen │ ├── snippets.ts │ └── table-html.ts ├── models │ └── app.ts ├── snippets │ ├── app.ts │ ├── nuxt │ │ ├── app.ts │ │ ├── script.ts │ │ └── template.ts │ ├── pinia │ │ ├── app.ts │ │ └── script.ts │ ├── vue-macros │ │ ├── app.ts │ │ └── script.ts │ ├── vue-router │ │ ├── app.ts │ │ ├── script.ts │ │ └── template.ts │ ├── vue │ │ ├── app.ts │ │ ├── code-snippets.ts │ │ ├── script.ts │ │ ├── style.ts │ │ ├── template.ts │ │ └── vue.ts │ └── vueuse │ │ ├── app.ts │ │ └── js.ts └── utils │ ├── general.ts │ └── snippets.ts └── vsc-extension-quickstart.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set default behavior to automatically normalize line endings. 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.vsix 3 | dist -------------------------------------------------------------------------------- /.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 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "deno.enable": true, 3 | "deno.unstable": true 4 | } 5 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | .gitignore 4 | vsc-extension-quickstart.md 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to the "modern-vue-snippets" extension will be documented in this file. 4 | 5 | Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. 6 | 7 | ## [Unreleased] 8 | 9 | - Initial release -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Matija Osrecki 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue Ecosystem Snippets 2 | 3 | > Snippets for the modern Vue ecosystem - including Nuxt 3, Pinia, VueUse, Vue Router & Vue Macros. 4 | 5 | ![Vue](https://img.shields.io/badge/vue-%2335495e.svg?style=for-the-badge&logo=vuedotjs&logoColor=%234FC08D) 6 | ![Nuxt](https://img.shields.io/badge/Nuxt-002E3B?style=for-the-badge&logo=nuxtdotjs&logoColor=#00DC82) 7 | ![TypeScript](https://img.shields.io/badge/typescript-%23007ACC.svg?style=for-the-badge&logo=typescript&logoColor=white) 8 | 9 | ## Features 10 | - Only the latest Vue syntax 11 | - Over **200** snippets 12 | - TypeScript-first 13 | - Nuxt 3, Pinia, VueUse, Vue Router & Vue Macros support 14 | - Strategically placed tabstops 15 | - Prefixes created with exact-match in mind 16 | - GitHub Copilot compliant 17 | - Auto-generated documentation 18 | 19 | ## Setup 20 | Not mandatory, but highly recommended. 21 | 22 | Look for it in user settings, or edit the settings.json directly: 23 | ```jsonc 24 | "editor.formatOnSave": true, 25 | 26 | // Tab complete snippets when their prefix match. 27 | "editor.tabCompletion": "onlySnippets" 28 | ``` 29 | 30 | ## Snippet syntax 31 | 32 | ### Tabstops 33 | - `$1`, `$2`, `$3` specify cursor locations, in order in which tabstops will be visited 34 | - `$0` denotes the final cursor position 35 | - Multiple occurrences of the same tabstop are linked and updated in sync 36 | 37 | ### Placeholders 38 | - Tabstops with default values → `${1:name}` 39 | 40 | ### Choices 41 | - Tabstops with multiple values → `${1|one,two,three|}`. 42 | - Truncated in documentation, for easier viewing → `${1|one,...|}`. 43 | 44 | ## Snippets 45 | 46 | ### Vue SFC 47 | `.vue` files 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 73 | 74 | 75 | 76 | 77 | 78 | 96 | 97 | 98 | 99 | 100 | 101 | 119 | 120 | 121 | 122 | 123 | 124 | 142 | 143 | 144 | 145 | 146 | 147 | 165 | 166 | 167 | 168 | 169 | 170 | 180 | 181 | 182 | 183 | 184 | 185 | 195 | 196 | 197 | 198 | 199 | 200 | 210 | 211 | 212 | 213 | 214 | 215 | 225 | 226 | 227 | 228 | 229 | 230 | 240 | 241 | 242 | 243 | 244 | 245 | 255 | 256 | 257 | 258 | 259 | 260 | 270 | 271 | 272 | 273 | 274 | 275 | 285 | 286 | 287 | 288 | 289 | 290 | 300 | 301 | 302 | 303 | 304 | 305 | 315 | 316 |
PrefixNameBody
vbaseVue SFC 60 | 61 | ```html 62 | 65 | 66 | 69 | 70 | ``` 71 | 72 |
vbase:fullVue SFC with style | postcss 79 | 80 | ```html 81 | 84 | 85 | 88 | 89 | 92 | 93 | ``` 94 | 95 |
vbase:full:cssVue SFC with style | css 102 | 103 | ```html 104 | 107 | 108 | 111 | 112 | 115 | 116 | ``` 117 | 118 |
vbase:full:scssVue SFC with style | scss 125 | 126 | ```html 127 | 130 | 131 | 134 | 135 | 138 | 139 | ``` 140 | 141 |
vbase:full:lessVue SFC with style | less 148 | 149 | ```html 150 | 153 | 154 | 157 | 158 | 161 | 162 | ``` 163 | 164 |
vscriptVue script setup | ts 171 | 172 | ```html 173 | 176 | 177 | ``` 178 | 179 |
vscript:jsVue script setup | js 186 | 187 | ```html 188 | 191 | 192 | ``` 193 | 194 |
vtemplateVue template 201 | 202 | ```html 203 | 206 | 207 | ``` 208 | 209 |
vstyleVue scoped style | postcss 216 | 217 | ```html 218 | 221 | 222 | ``` 223 | 224 |
vstyle:langVue style with language option 231 | 232 | ```html 233 | 236 | 237 | ``` 238 | 239 |
vstyle:cssVue scoped style | css 246 | 247 | ```html 248 | 251 | 252 | ``` 253 | 254 |
vstyle:scssscoped style | scss 261 | 262 | ```html 263 | 266 | 267 | ``` 268 | 269 |
vstyle:lessscoped style | less 276 | 277 | ```html 278 | 281 | 282 | ``` 283 | 284 |
vstyle:moduleVue style with CSS modules 291 | 292 | ```html 293 | 296 | 297 | ``` 298 | 299 |
vstyle:srcVue scoped style with src 306 | 307 | ```html 308 | 311 | 312 | ``` 313 | 314 |
317 | 318 | 319 | ### Template 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 339 | 340 | 341 | 342 | 343 | 344 | 351 | 352 | 353 | 354 | 355 | 356 | 363 | 364 | 365 | 366 | 367 | 368 | 377 | 378 | 379 | 380 | 381 | 382 | 391 | 392 | 393 | 394 | 395 | 396 | 403 | 404 | 405 | 406 | 407 | 408 | 417 | 418 | 419 | 420 | 421 | 422 | 431 | 432 | 433 | 434 | 435 | 436 | 445 | 446 | 447 | 448 | 449 | 450 | 459 | 460 | 461 | 462 | 463 | 464 | 473 | 474 | 475 | 476 | 477 | 478 | 487 | 488 | 489 | 490 | 491 | 492 | 501 | 502 | 503 | 504 | 505 | 506 | 515 | 516 | 517 | 518 | 519 | 520 | 532 | 533 | 534 | 535 | 536 | 537 | 544 | 545 | 546 | 547 | 548 | 549 | 556 | 557 | 558 | 559 | 560 | 561 | 568 | 569 | 570 | 571 | 572 | 573 | 580 | 581 | 582 | 583 | 584 | 585 | 592 | 593 | 594 | 595 | 596 | 597 | 604 | 605 | 606 | 607 | 608 | 609 | 616 | 617 | 618 | 619 | 620 | 621 | 628 | 629 | 630 | 631 | 632 | 633 | 640 | 641 | 642 | 643 | 644 | 645 | 652 | 653 | 654 | 655 | 656 | 657 | 664 | 665 | 666 | 667 | 668 | 669 | 676 | 677 | 678 | 679 | 680 | 681 | 688 | 689 | 690 | 691 | 692 | 693 | 700 | 701 | 702 | 703 | 704 | 705 | 712 | 713 | 714 | 715 | 716 | 717 | 724 | 725 | 726 | 727 | 728 | 729 | 736 | 737 | 738 | 739 | 740 | 741 | 748 | 749 | 750 | 751 | 752 | 753 | 760 | 761 | 762 | 763 | 764 | 765 | 772 | 773 | 774 | 775 | 776 | 777 | 784 | 785 | 786 | 787 | 788 | 789 | 796 | 797 | 798 | 799 | 800 | 801 | 808 | 809 | 810 | 811 | 812 | 813 | 820 | 821 | 822 | 823 | 824 | 825 | 832 | 833 | 834 | 835 | 836 | 837 | 844 | 845 | 846 | 847 | 848 | 849 | 856 | 857 | 858 | 859 | 860 | 861 | 868 | 869 | 870 | 871 | 872 | 873 | 880 | 881 | 882 | 883 | 884 | 885 | 892 | 893 | 894 | 895 | 896 | 897 | 904 | 905 | 906 | 907 | 908 | 909 | 916 | 917 | 918 | 919 | 920 | 921 | 928 | 929 | 930 | 931 | 932 | 933 | 940 | 941 | 942 | 943 | 944 | 945 | 952 | 953 | 954 | 955 | 956 | 957 | 964 | 965 | 966 | 967 | 968 | 969 | 976 | 977 | 978 | 979 | 980 | 981 | 988 | 989 | 990 | 991 | 992 | 993 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1192 | 1193 |
PrefixNameBody
slotslot 333 | 334 | ```html 335 | $0 336 | ``` 337 | 338 |
template / vtemplatetemplate 345 | 346 | ```html 347 | 348 | ``` 349 | 350 |
component / vcomponentcomponent 357 | 358 | ```html 359 | $0 360 | ``` 361 | 362 |
nslotnamed slot 369 | 370 | ```html 371 | 372 | $0 373 | 374 | ``` 375 | 376 |
ntemplatenamed template 383 | 384 | ```html 385 | 388 | ``` 389 | 390 |
vcomponentVue component 397 | 398 | ```html 399 | $0 400 | ``` 401 | 402 |
vKeepAliveVue KeepAlive 409 | 410 | ```html 411 | 412 | $0 413 | 414 | ``` 415 | 416 |
vTeleportVue teleport 423 | 424 | ```html 425 | 426 | $0 427 | 428 | ``` 429 | 430 |
vTransitionVue Transition 437 | 438 | ```html 439 | 440 | $0 441 | 442 | ``` 443 | 444 |
vTransition:name / nTransitionVue Transition with name 451 | 452 | ```html 453 | 454 | $0 455 | 456 | ``` 457 | 458 |
vTransition:typeVue Transition with type 465 | 466 | ```html 467 | 468 | $0 469 | 470 | ``` 471 | 472 |
vTransition:appearVue Transition with appear 479 | 480 | ```html 481 | 482 | $0 483 | 484 | ``` 485 | 486 |
vTransitionGroupVue TransitionGroup 493 | 494 | ```html 495 | 496 | $0 497 | 498 | ``` 499 | 500 |
vSuspenseVue Suspense 507 | 508 | ```html 509 | 510 | $0 511 | 512 | ``` 513 | 514 |
vSuspense:fallbackVue Suspense with fallback 521 | 522 | ```html 523 | 524 | $0 525 | 528 | 529 | ``` 530 | 531 |
vtextv-text 538 | 539 | ```html 540 | v-text="$1" 541 | ``` 542 | 543 |
vhtmlv-html 550 | 551 | ```html 552 | v-html="$1" 553 | ``` 554 | 555 |
vshowv-show 562 | 563 | ```html 564 | v-show="$1" 565 | ``` 566 | 567 |
vif / ifv-if 574 | 575 | ```html 576 | v-if="$1" 577 | ``` 578 | 579 |
veif / elifv-else-if 586 | 587 | ```html 588 | v-else-if="$1" 589 | ``` 590 | 591 |
velse / elsev-else 598 | 599 | ```html 600 | v-else 601 | ``` 602 | 603 |
vforv-for 610 | 611 | ```html 612 | v-for="${2:item} in ${1:items}" :key="$2$3" 613 | ``` 614 | 615 |
vforiv-for (indexed) 622 | 623 | ```html 624 | v-for="(${2:item}, ${3:i}) in ${1:items}" :key="${4:$3}" 625 | ``` 626 | 627 |
vforrv-for range 634 | 635 | ```html 636 | v-for="${1:n} in ${2:5}" :key="$1" 637 | ``` 638 | 639 |
vemit / emitemit 646 | 647 | ```html 648 | emit('$1'$2) 649 | ``` 650 | 651 |
vemit:passVue pass emit 658 | 659 | ```html 660 | @${1|click,input,...|}="\$emit('${2:$1}', \$event)" 661 | ``` 662 | 663 |
vonv-on 670 | 671 | ```html 672 | v-on="${1:emits}" 673 | ``` 674 | 675 |
von:event / voeevent handler 682 | 683 | ```html 684 | @$1="$2" 685 | ``` 686 | 687 |
von:click / vocclick handler 694 | 695 | ```html 696 | @click="${1:onClick}" 697 | ``` 698 | 699 |
von:input / voiinput handler 706 | 707 | ```html 708 | @input="${1:onInput}" 709 | ``` 710 | 711 |
von:updateupdate handler 718 | 719 | ```html 720 | @update="${1:onUpdate}" 721 | ``` 722 | 723 |
von:changechange handler 730 | 731 | ```html 732 | @change="${1:onChange}" 733 | ``` 734 | 735 |
von:blurblur handler 742 | 743 | ```html 744 | @blur="${1:onBlur}" 745 | ``` 746 | 747 |
von:focusfocus handler 754 | 755 | ```html 756 | @focus="${1:onFocus}" 757 | ``` 758 | 759 |
von:submitsubmit handler 766 | 767 | ```html 768 | @submit${1:.prevent}="${2:onSubmit}" 769 | ``` 770 | 771 |
vbindv-bind 778 | 779 | ```html 780 | v-bind="$1" 781 | ``` 782 | 783 |
vbind:attrsv-bind attrs 790 | 791 | ```html 792 | v-bind="\$attrs" 793 | ``` 794 | 795 |
vbind:propsv-bind props 802 | 803 | ```html 804 | v-bind="\$props" 805 | ``` 806 | 807 |
vbind:fullv-bind props and attrs 814 | 815 | ```html 816 | v-bind="[\$props, \$attrs]" 817 | ``` 818 | 819 |
vmodelv-model 826 | 827 | ```html 828 | v-model="$1" 829 | ``` 830 | 831 |
vmodel:numberv-model.number 838 | 839 | ```html 840 | v-model.number="$1" 841 | ``` 842 | 843 |
vmodel:trimv-model.trim 850 | 851 | ```html 852 | v-model.trim="$1" 853 | ``` 854 | 855 |
vmodel:customcustom v-model 862 | 863 | ```html 864 | v-model:${1:custom}="$2" 865 | ``` 866 | 867 |
vslotscoped slot 874 | 875 | ```html 876 | v-slot="{$1}" 877 | ``` 878 | 879 |
vprev-pre 886 | 887 | ```html 888 | v-pre="$1" 889 | ``` 890 | 891 |
voncev-once 898 | 899 | ```html 900 | v-once 901 | ``` 902 | 903 |
vmemov-memo 910 | 911 | ```html 912 | v-memo="[$1]" 913 | ``` 914 | 915 |
vcloakv-cloak 922 | 923 | ```html 924 | v-cloak 925 | ``` 926 | 927 |
vkeyVue key 934 | 935 | ```html 936 | :key="$1" 937 | ``` 938 | 939 |
vrefVue ref 946 | 947 | ```html 948 | ref="$1" 949 | ``` 950 | 951 |
vnamename property 958 | 959 | ```html 960 | ${1|name,:name|}="$2" 961 | ``` 962 | 963 |
visis property 970 | 971 | ```html 972 | ${1|is,:is|}="$2" 973 | ``` 974 | 975 |
vbbind attribute 982 | 983 | ```html 984 | :${1:prop}="${2:$1}" 985 | ``` 986 | 987 |
vaattribute 994 | 995 | ```html 996 | ${1:prop}="$2" 997 | ``` 998 | 999 |
vclass / vcVue classes 1006 | 1007 | ```html 1008 | :class="$1" 1009 | ``` 1010 | 1011 |
vclass:list / vcaVue classes list 1018 | 1019 | ```html 1020 | :class="[$1]" 1021 | ``` 1022 | 1023 |
vclass:cond / vccVue conditional classes 1030 | 1031 | ```html 1032 | :class="{ $1: $2 }" 1033 | ``` 1034 | 1035 |
vstyleVue inline style 1042 | 1043 | ```html 1044 | :style="{ $1: $2 }" 1045 | ``` 1046 | 1047 |
vstyle:listVue inline style list 1054 | 1055 | ```html 1056 | :style="[$1]" 1057 | ``` 1058 | 1059 |
vvVue 1066 | 1067 | ```html 1068 | {{ $1 }} 1069 | ``` 1070 | 1071 |
vvtVue i18n translation 1078 | 1079 | ```html 1080 | {{ t('$1') }} 1081 | ``` 1082 | 1083 |
vif:slotv-if slot defined 1090 | 1091 | ```html 1092 | v-if="\$slots.${1:default}" 1093 | ``` 1094 | 1095 |
vif:slot-propv-if slot or prop defined 1102 | 1103 | ```html 1104 | v-if="\$slots.${1:label} || ${2:$1}" 1105 | ``` 1106 | 1107 |
vformform submit.prevent 1114 | 1115 | ```html 1116 |
1117 | $0 1118 |
1119 | ``` 1120 | 1121 |
vfor:templatev-for in template 1128 | 1129 | ```html 1130 | <${1|template,div,...|} v-for="${3:item} in ${2:items}" :key="$3$4"> 1131 | $0 1132 | 1133 | ``` 1134 | 1135 |
vfori:templatev-for (indexed) in template 1142 | 1143 | ```html 1144 | <${1|template,div,...|} v-for="(${3:item}, ${4:i}) in ${2:items}" :key="${5:$4}"> 1145 | $0 1146 | 1147 | ``` 1148 | 1149 |
vif:templatev-if in template 1156 | 1157 | ```html 1158 | <${1|template,div,...|} v-if="$2"> 1159 | $0 1160 | 1161 | ``` 1162 | 1163 |
vtiftemplate with v-if 1170 | 1171 | ```html 1172 | 1175 | ``` 1176 | 1177 |
vdifdiv with v-if 1184 | 1185 | ```html 1186 |
1187 | $0 1188 |
1189 | ``` 1190 | 1191 |
1194 | 1195 | 1196 | ### Style 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1252 | 1253 |
PrefixNameBody
vbindv-bind 1210 | 1211 | ```css 1212 | v-bind($0) 1213 | ``` 1214 | 1215 |
deep:deep() 1222 | 1223 | ```css 1224 | :deep($1) 1225 | ``` 1226 | 1227 |
slot:slotted() 1234 | 1235 | ```css 1236 | :slotted($1) 1237 | ``` 1238 | 1239 |
global:global() 1246 | 1247 | ```css 1248 | :global($1) 1249 | ``` 1250 | 1251 |
1254 | 1255 | 1256 | ### Script 1257 | Script setup and composables 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1288 | 1289 | 1290 | 1291 | 1292 | 1293 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1377 | 1378 | 1379 | 1380 | 1381 | 1382 | 1389 | 1390 | 1391 | 1392 | 1393 | 1394 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1425 | 1426 | 1427 | 1428 | 1429 | 1430 | 1439 | 1440 | 1441 | 1442 | 1443 | 1444 | 1453 | 1454 | 1455 | 1456 | 1457 | 1458 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1479 | 1480 | 1481 | 1482 | 1483 | 1484 | 1493 | 1494 | 1495 | 1496 | 1497 | 1498 | 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1521 | 1522 | 1523 | 1524 | 1525 | 1526 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | 1561 | 1562 | 1563 | 1564 | 1565 | 1566 | 1575 | 1576 | 1577 | 1578 | 1579 | 1580 | 1589 | 1590 | 1591 | 1592 | 1593 | 1594 | 1601 | 1602 | 1603 | 1604 | 1605 | 1606 | 1615 | 1616 | 1617 | 1618 | 1619 | 1620 | 1627 | 1628 | 1629 | 1630 | 1631 | 1632 | 1639 | 1640 | 1641 | 1642 | 1643 | 1644 | 1653 | 1654 | 1655 | 1656 | 1657 | 1658 | 1667 | 1668 | 1669 | 1670 | 1671 | 1672 | 1681 | 1682 | 1683 | 1684 | 1685 | 1686 | 1695 | 1696 | 1697 | 1698 | 1699 | 1700 | 1709 | 1710 | 1711 | 1712 | 1713 | 1714 | 1723 | 1724 | 1725 | 1726 | 1727 | 1728 | 1737 | 1738 | 1739 | 1740 | 1741 | 1742 | 1751 | 1752 | 1753 | 1754 | 1755 | 1756 | 1765 | 1766 | 1767 | 1768 | 1769 | 1770 | 1779 | 1780 | 1781 | 1782 | 1783 | 1784 | 1791 | 1792 | 1793 | 1794 | 1795 | 1796 | 1803 | 1804 | 1805 | 1806 | 1807 | 1808 | 1815 | 1816 | 1817 | 1818 | 1819 | 1820 | 1827 | 1828 | 1829 | 1830 | 1831 | 1832 | 1839 | 1840 | 1841 | 1842 | 1843 | 1844 | 1851 | 1852 | 1853 | 1854 | 1855 | 1856 | 1863 | 1864 | 1865 | 1866 | 1867 | 1868 | 1875 | 1876 | 1877 | 1878 | 1879 | 1880 | 1887 | 1888 |
PrefixNameBody
vref / vrVue ref 1270 | 1271 | ```javascript 1272 | const ${1:name} = ref($2) 1273 | ``` 1274 | 1275 |
vref:ts / vrtVue ref (typed) 1282 | 1283 | ```javascript 1284 | const ${1:name} = ref<$2>($3) 1285 | ``` 1286 | 1287 |
vcomputed / vcVue computed 1294 | 1295 | ```javascript 1296 | const ${1:name} = computed(() => $2) 1297 | ``` 1298 | 1299 |
vcomputed:ts / vctVue computed (typed) 1306 | 1307 | ```javascript 1308 | const ${1:name} = computed<$2>(() => $3) 1309 | ``` 1310 | 1311 |
vcomputed:gs / vcgsVue computed (get/set) 1318 | 1319 | ```javascript 1320 | const ${1:name} = computed({ 1321 | get: () => ${2}, 1322 | set: (${3:value}: ${4:string}) => { 1323 | ${5} 1324 | }, 1325 | }) 1326 | ``` 1327 | 1328 |
vreactive / vraVue reactive 1335 | 1336 | ```javascript 1337 | const ${1:name} = reactive({$2}) 1338 | ``` 1339 | 1340 |
vreactive:tsVue reactive (typed) 1347 | 1348 | ```javascript 1349 | const ${1:name}: ${2:type} = reactive({$3}) 1350 | ``` 1351 | 1352 |
vshallowRefVue shallowRef 1359 | 1360 | ```javascript 1361 | const ${1:name} = shallowRef($2) 1362 | ``` 1363 | 1364 |
vtoRefVue toRef 1371 | 1372 | ```javascript 1373 | toRef(${1:props}, '$2') 1374 | ``` 1375 | 1376 |
vtoRefsVue toRefs 1383 | 1384 | ```javascript 1385 | toRefs(${1:props}) 1386 | ``` 1387 | 1388 |
vunrefVue unref 1395 | 1396 | ```javascript 1397 | unref($1) 1398 | ``` 1399 | 1400 |
vreadonlyVue readonly 1407 | 1408 | ```javascript 1409 | readonly(${1:object}) 1410 | ``` 1411 | 1412 |
vref:elemVue element ref 1419 | 1420 | ```javascript 1421 | const ${1:elem} = ref<${2|HTMLInputElement,HTMLInputElement,...|} | null>(null) 1422 | ``` 1423 | 1424 |
vwatchEffectVue watchEffect 1431 | 1432 | ```javascript 1433 | watchEffect(() => { 1434 | $0 1435 | }) 1436 | ``` 1437 | 1438 |
vwatchVue watch source 1445 | 1446 | ```javascript 1447 | watch(${1:source}, (${2:val}) => { 1448 | $0 1449 | }) 1450 | ``` 1451 | 1452 |
vwatch:inlineVue watch inline 1459 | 1460 | ```javascript 1461 | watch(${1:source}, ${2:fn}) 1462 | ``` 1463 | 1464 |
vwatch:getterVue watch getter 1471 | 1472 | ```javascript 1473 | watch(() => ${1:source}, (${2:val}) => { 1474 | $0 1475 | }) 1476 | ``` 1477 | 1478 |
vwatch:multipleVue watch multiple 1485 | 1486 | ```javascript 1487 | watch([${1:source1}, ${2:source2}], ([new${1/(.*)/${1:/capitalize}/}, new${2/(.*)/${1:/capitalize}/}]) => { 1488 | $0 1489 | }) 1490 | ``` 1491 | 1492 |
vwatch:immediateVue watch immediate 1499 | 1500 | ```javascript 1501 | watch(${1:source}, (${2:val}) => { 1502 | $0 1503 | }, { immediate: true }) 1504 | ``` 1505 | 1506 |
vwatch:deepVue watch deep 1513 | 1514 | ```javascript 1515 | watch(${1:source}, (${2:val}) => { 1516 | $0 1517 | }, { deep: true }) 1518 | ``` 1519 | 1520 |
vwatch:log / vwlVue watch source | log 1527 | 1528 | ```javascript 1529 | watch(${1:source}, (${2:val}) => { 1530 | console.log('$1:', $2) 1531 | }) 1532 | ``` 1533 | 1534 |
vpropsVue defineProps 1541 | 1542 | ```javascript 1543 | ${1:const props = }defineProps<${2:Props}>() 1544 | ``` 1545 | 1546 |
vprops:defaultsVue defineProps with defaults 1553 | 1554 | ```javascript 1555 | ${1:const props = }withDefaults(defineProps<${2:Props}>(), { 1556 | $0 1557 | }) 1558 | ``` 1559 | 1560 |
vprops:jsVue defineProps without TS 1567 | 1568 | ```javascript 1569 | ${1:const props = }defineProps({ 1570 | $2 1571 | }) 1572 | ``` 1573 | 1574 |
vemitsVue defineEmits 1581 | 1582 | ```javascript 1583 | ${1:const emit = }defineEmits<{ 1584 | ${2:click}: [${3:payload}: ${4:string}],$5 1585 | }>() 1586 | ``` 1587 | 1588 |
vemits:altVue defineEmits without TS 1595 | 1596 | ```javascript 1597 | ${1:const emit = }defineEmits(['$2']) 1598 | ``` 1599 | 1600 |
vemits:oldVue defineEmits (old syntax) 1607 | 1608 | ```javascript 1609 | ${1:const emit = }defineEmits<{ 1610 | (e: '${2:click}', ${3:payload}: ${4:string}): void,$5 1611 | }>() 1612 | ``` 1613 | 1614 |
vmodelVue defineModel 1621 | 1622 | ```javascript 1623 | const ${1:modelValue} = defineModel<${2:string}>($3) 1624 | ``` 1625 | 1626 |
vemitVue emit event 1633 | 1634 | ```javascript 1635 | emit('$1'$2) 1636 | ``` 1637 | 1638 |
vexposeVue defineExpose 1645 | 1646 | ```javascript 1647 | defineExpose({ 1648 | $1 1649 | }) 1650 | ``` 1651 | 1652 |
v:onMountedVue onMounted 1659 | 1660 | ```javascript 1661 | onMounted(() => { 1662 | $0 1663 | }) 1664 | ``` 1665 | 1666 |
v:onBeforeMountVue onBeforeMount 1673 | 1674 | ```javascript 1675 | onBeforeMount(() => { 1676 | $0 1677 | }) 1678 | ``` 1679 | 1680 |
v:onUnmountedVue onUnmounted 1687 | 1688 | ```javascript 1689 | onUnmounted(() => { 1690 | $0 1691 | }) 1692 | ``` 1693 | 1694 |
v:onBeforeUnmountVue onBeforeUnmount 1701 | 1702 | ```javascript 1703 | onBeforeUnmount(() => { 1704 | $0 1705 | }) 1706 | ``` 1707 | 1708 |
v:onUpdatedVue onUpdated 1715 | 1716 | ```javascript 1717 | onUpdated(() => { 1718 | $0 1719 | }) 1720 | ``` 1721 | 1722 |
v:onBeforeUpdateVue onBeforeUpdate 1729 | 1730 | ```javascript 1731 | onBeforeUpdate(() => { 1732 | $0 1733 | }) 1734 | ``` 1735 | 1736 |
v:onErrorCapturedVue onErrorCaptured 1743 | 1744 | ```javascript 1745 | onErrorCaptured(() => { 1746 | $0 1747 | }) 1748 | ``` 1749 | 1750 |
v:onActivatedVue onActivated 1757 | 1758 | ```javascript 1759 | onActivated(() => { 1760 | $0 1761 | }) 1762 | ``` 1763 | 1764 |
v:onDeactivatedVue onDeactivated 1771 | 1772 | ```javascript 1773 | onDeactivated(() => { 1774 | $0 1775 | }) 1776 | ``` 1777 | 1778 |
vprovideVue provide 1785 | 1786 | ```javascript 1787 | provide(${1:key}, ${2:value}) 1788 | ``` 1789 | 1790 |
vprovide:tsVue provide (typed) 1797 | 1798 | ```javascript 1799 | provide<${1:string}>(${2:key}, ${3:value}) 1800 | ``` 1801 | 1802 |
vinjectVue inject 1809 | 1810 | ```javascript 1811 | const ${1:value} = inject(${2:key}) 1812 | ``` 1813 | 1814 |
vinject:tsVue inject (typed) 1821 | 1822 | ```javascript 1823 | const ${1:value} = inject<${2:string}>(${3:key}) 1824 | ``` 1825 | 1826 |
vinject:defaultVue inject with default 1833 | 1834 | ```javascript 1835 | const ${1:value} = inject(${2:key}, ${3:defaultValue}) 1836 | ``` 1837 | 1838 |
vinjectkeyVue injection key 1845 | 1846 | ```javascript 1847 | const ${1:key} = Symbol('$2') as InjectionKey<${3:string}> 1848 | ``` 1849 | 1850 |
vslotsVue useSlots 1857 | 1858 | ```javascript 1859 | const slots = useSlots() 1860 | ``` 1861 | 1862 |
vattrsVue useAttrs 1869 | 1870 | ```javascript 1871 | const attrs = useAttrs() 1872 | ``` 1873 | 1874 |
vimport / vimImport from vue 1881 | 1882 | ```javascript 1883 | import { $1 } from 'vue' 1884 | ``` 1885 | 1886 |
1889 | 1890 | ### Code snippets 1891 | Useful vue snippets and helpers 1892 | 1893 | 1894 | 1895 | 1896 | 1897 | 1898 | 1899 | 1900 | 1901 | 1902 | 1903 | 1917 | 1918 | 1919 | 1920 | 1921 | 1922 | 1936 | 1937 | 1938 | 1939 | 1940 | 1941 | 1948 | 1949 | 1950 | 1951 | 1952 | 1953 | 1960 | 1961 | 1962 | 1963 | 1964 | 1965 | 1983 | 1984 | 1985 | 1986 | 1987 | 1988 | 1996 | 1997 |
PrefixNameBody
vcomposable / vdcVue define composable 1904 | 1905 | ```javascript 1906 | export const use${1/(.*)/${1:/pascalcase}/} = () => { 1907 | $0 1908 | 1909 | return { 1910 | 1911 | } 1912 | } 1913 | 1914 | ``` 1915 | 1916 |
vcomposable:file / vdcfVue define composable in file 1923 | 1924 | ```javascript 1925 | export const use${TM_FILENAME_BASE/^(.*)$/${1:/pascalcase}/} = () => { 1926 | $0 1927 | 1928 | return { 1929 | 1930 | } 1931 | } 1932 | 1933 | ``` 1934 | 1935 |
vuse / vuUse composable 1942 | 1943 | ```javascript 1944 | const ${2:$1} = use${1/(.*)/${1:/capitalize}/}($3) 1945 | ``` 1946 | 1947 |
vused / vudUse composable with destructuring 1954 | 1955 | ```javascript 1956 | const { $2 } = use${1/(.*)/${1:/capitalize}/}($3) 1957 | ``` 1958 | 1959 |
vmodel:manualImplement v-model manually 1966 | 1967 | ```javascript 1968 | const props = defineProps<{ 1969 | ${1:modelValue}: ${2:string} 1970 | }>() 1971 | 1972 | const emit = defineEmits<{ 1973 | (e: 'update:$1', ${3:value}?: $2): void 1974 | }>() 1975 | 1976 | const ${4:value} = computed({ 1977 | get: () => props.$1, 1978 | set: (val: $2) => emit('update:$1', val), 1979 | }) 1980 | ``` 1981 | 1982 |
v:has-slotVue check for slots 1989 | 1990 | ```javascript 1991 | const slots = useSlots() 1992 | const hasSlot = (name: string) => !!slots[name] 1993 | ``` 1994 | 1995 |
1998 | 1999 | 2000 | ### Vue Router (script) 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2032 | 2033 | 2034 | 2035 | 2036 | 2037 | 2050 | 2051 |
PrefixNameBody
vrouterVue router 2014 | 2015 | ```javascript 2016 | const ${1:router} = useRouter() 2017 | ``` 2018 | 2019 |
vrouteVue route 2026 | 2027 | ```javascript 2028 | const ${1:route} = useRoute() 2029 | ``` 2030 | 2031 |
vrouter:createCreate Vue router 2038 | 2039 | ```javascript 2040 | const router = createRouter({ 2041 | history: createWebHashHistory(), 2042 | routes: ${1:routes}, 2043 | scrollBehavior(to, from, savedPosition) { 2044 | $2 2045 | } 2046 | }) 2047 | ``` 2048 | 2049 |
2052 | 2053 | 2054 | ### Vue Router (template) 2055 | 2056 | 2057 | 2058 | 2059 | 2060 | 2061 | 2062 | 2063 | 2064 | 2065 | 2066 | 2067 | 2074 | 2075 | 2076 | 2077 | 2078 | 2079 | 2086 | 2087 | 2088 | 2089 | 2090 | 2091 | 2098 | 2099 | 2100 | 2101 | 2102 | 2103 | 2110 | 2111 | 2112 | 2113 | 2114 | 2115 | 2122 | 2123 | 2124 | 2125 | 2126 | 2127 | 2136 | 2137 | 2138 | 2139 | 2140 | 2141 | 2148 | 2149 | 2150 | 2151 | 2152 | 2153 | 2160 | 2161 | 2162 | 2163 | 2164 | 2165 | 2172 | 2173 | 2174 | 2175 | 2176 | 2177 | 2184 | 2185 | 2186 | 2187 | 2188 | 2189 | 2196 | 2197 |
PrefixNameBody
vtoVue Router to 2068 | 2069 | ```html 2070 | ${1|to,:to|}="$2" 2071 | ``` 2072 | 2073 |
vto:paramVue Router :to with param 2080 | 2081 | ```html 2082 | :to="`$1${${2:id}}$3`" 2083 | ``` 2084 | 2085 |
vto:objVue Router :to object 2092 | 2093 | ```html 2094 | :to="{ $1 }" 2095 | ``` 2096 | 2097 |
vto:nameVue Router :to name 2104 | 2105 | ```html 2106 | :to="{ name: '$1',$2 }" 2107 | ``` 2108 | 2109 |
vto:pathVue Router :to path 2116 | 2117 | ```html 2118 | :to="{ path: '$1',$2 }" 2119 | ``` 2120 | 2121 |
vviewRouterView 2128 | 2129 | ```html 2130 | 2131 | $0 2132 | 2133 | ``` 2134 | 2135 |
vlinkRouterLink 2142 | 2143 | ```html 2144 | $3 2145 | ``` 2146 | 2147 |
vlink:paramRouterLink with param 2154 | 2155 | ```html 2156 | $4 2157 | ``` 2158 | 2159 |
vlink:objRouterLink with object 2166 | 2167 | ```html 2168 | $2 2169 | ``` 2170 | 2171 |
vlink:nameRouterLink with name 2178 | 2179 | ```html 2180 | $3 2181 | ``` 2182 | 2183 |
vlink:pathRouterLink with path 2190 | 2191 | ```html 2192 | $3 2193 | ``` 2194 | 2195 |
2198 | 2199 | 2200 | ### Pinia 2201 | 2202 | 2203 | 2204 | 2205 | 2206 | 2207 | 2208 | 2209 | 2210 | 2211 | 2212 | 2213 | 2229 | 2230 | 2231 | 2232 | 2233 | 2234 | 2250 | 2251 | 2252 | 2253 | 2254 | 2255 | 2262 | 2263 |
PrefixNameBody
pstoreSetup Pinia store 2214 | 2215 | ```javascript 2216 | import { defineStore } from 'pinia' 2217 | 2218 | export const use${TM_FILENAME_BASE/^(.*)$/${1:/pascalcase}/}Store = defineStore('$TM_FILENAME_BASE', () => { 2219 | $0 2220 | 2221 | return { 2222 | 2223 | } 2224 | }) 2225 | 2226 | ``` 2227 | 2228 |
pstore:optionsSetup Pinia store (Options) 2235 | 2236 | ```javascript 2237 | import { defineStore } from 'pinia' 2238 | 2239 | export const use${TM_FILENAME_BASE/^(.*)$/${1:/pascalcase}/}Store = defineStore('$TM_FILENAME_BASE', { 2240 | state: () => ({ 2241 | $0 2242 | }), 2243 | getters: {}, 2244 | actions: {}, 2245 | }) 2246 | 2247 | ``` 2248 | 2249 |
vuseStore / vusUse store 2256 | 2257 | ```javascript 2258 | const ${2:$1Store} = use${1/(.*)/${1:/capitalize}/}Store() 2259 | ``` 2260 | 2261 |
2264 | 2265 | 2266 | ### Nuxt (script) 2267 | 2268 | 2269 | 2270 | 2271 | 2272 | 2273 | 2274 | 2275 | 2276 | 2277 | 2278 | 2279 | 2286 | 2287 | 2288 | 2289 | 2290 | 2291 | 2298 | 2299 | 2300 | 2301 | 2302 | 2303 | 2310 | 2311 | 2312 | 2313 | 2314 | 2315 | 2322 | 2323 | 2324 | 2325 | 2326 | 2327 | 2337 | 2338 | 2339 | 2340 | 2341 | 2342 | 2349 | 2350 | 2351 | 2352 | 2353 | 2354 | 2361 | 2362 | 2363 | 2364 | 2365 | 2366 | 2373 | 2374 | 2375 | 2376 | 2377 | 2378 | 2385 | 2386 | 2387 | 2388 | 2389 | 2390 | 2397 | 2398 | 2399 | 2400 | 2401 | 2402 | 2409 | 2410 | 2411 | 2412 | 2413 | 2414 | 2421 | 2422 | 2423 | 2424 | 2425 | 2426 | 2433 | 2434 | 2435 | 2436 | 2437 | 2438 | 2445 | 2446 | 2447 | 2448 | 2449 | 2450 | 2457 | 2458 | 2459 | 2460 | 2461 | 2462 | 2469 | 2470 | 2471 | 2472 | 2473 | 2474 | 2483 | 2484 | 2485 | 2486 | 2487 | 2488 | 2497 | 2498 | 2499 | 2500 | 2501 | 2502 | 2511 | 2512 | 2513 | 2514 | 2515 | 2516 | 2525 | 2526 | 2527 | 2528 | 2529 | 2530 | 2539 | 2540 | 2541 | 2542 | 2543 | 2544 | 2553 | 2554 | 2555 | 2556 | 2557 | 2558 | 2565 | 2566 | 2567 | 2568 | 2569 | 2570 | 2577 | 2578 | 2579 | 2580 | 2581 | 2582 | 2589 | 2590 | 2591 | 2592 | 2593 | 2594 | 2601 | 2602 | 2603 | 2604 | 2605 | 2606 | 2613 | 2614 | 2615 | 2616 | 2617 | 2618 | 2627 | 2628 | 2629 | 2630 | 2631 | 2632 | 2641 | 2642 | 2643 | 2644 | 2645 | 2646 | 2655 | 2656 | 2657 | 2658 | 2659 | 2660 | 2669 | 2670 | 2671 | 2672 | 2673 | 2674 | 2683 | 2684 | 2685 | 2686 | 2687 | 2688 | 2697 | 2698 | 2699 | 2700 | 2701 | 2702 | 2715 | 2716 | 2717 | 2718 | 2719 | 2720 | 2729 | 2730 | 2731 | 2732 | 2733 | 2734 | 2741 | 2742 | 2743 | 2744 | 2745 | 2746 | 2753 | 2754 | 2755 | 2756 | 2757 | 2758 | 2765 | 2766 | 2767 | 2768 | 2769 | 2770 | 2777 | 2778 |
PrefixNameBody
nfetchNuxt useFetch 2280 | 2281 | ```javascript 2282 | const { data: ${1:data} } = await useFetch('$2'$3) 2283 | ``` 2284 | 2285 |
nfetch:cbNuxt useFetch with callback 2292 | 2293 | ```javascript 2294 | const { data: ${1:data} } = await useFetch(() => '$2'$3) 2295 | ``` 2296 | 2297 |
nfetch:lazyNuxt useLazyFetch 2304 | 2305 | ```javascript 2306 | const { pending, data: ${1:data} } = useLazyFetch('$2'$3) 2307 | ``` 2308 | 2309 |
nfetch:lazy:cbNuxt useLazyFetch callback 2316 | 2317 | ```javascript 2318 | const { pending, data: ${1:data} } = useLazyFetch(() => '$2'$3) 2319 | ``` 2320 | 2321 |
nfetch:postNuxt useFetch POST 2328 | 2329 | ```javascript 2330 | const { data: ${1:data} } = await useFetch('$2', { 2331 | method: 'POST', 2332 | body: ${3:body},$4 2333 | }) 2334 | ``` 2335 | 2336 |
nasyncdataNuxt useAsyncData 2343 | 2344 | ```javascript 2345 | const { data: ${1:data} } = await useAsyncData('${2:key}', () => $fetch('$3')$4) 2346 | ``` 2347 | 2348 |
nasyncdata:lazyNuxt useLazyAsyncData 2355 | 2356 | ```javascript 2357 | const { pending, data: ${1:data} } = useLazyAsyncData('${2:key}', () => $fetch('$3')$4) 2358 | ``` 2359 | 2360 |
nappNuxt useNuxtApp 2367 | 2368 | ```javascript 2369 | const app = useNuxtApp() 2370 | ``` 2371 | 2372 |
nappConfigNuxt useAppConfig 2379 | 2380 | ```javascript 2381 | const appConfig = useAppConfig() 2382 | ``` 2383 | 2384 |
nruntimeConfigNuxt useRuntimeConfig 2391 | 2392 | ```javascript 2393 | const config = useRuntimeConfig() 2394 | ``` 2395 | 2396 |
ncookieNuxt useCookie 2403 | 2404 | ```javascript 2405 | const ${1:cookie} = useCookie('${2:$1}'$3) 2406 | ``` 2407 | 2408 |
ncookie:optsNuxt useCookie with options 2415 | 2416 | ```javascript 2417 | const ${1:cookie} = useCookie('${2:$1}', { $3 }) 2418 | ``` 2419 | 2420 |
ndataNuxt useNuxtData 2427 | 2428 | ```javascript 2429 | const { data: ${2:$1} } = useNuxtData('${1:key}') 2430 | ``` 2431 | 2432 |
nerrorNuxt useError 2439 | 2440 | ```javascript 2441 | const ${1:error} = useError() 2442 | ``` 2443 | 2444 |
nstateNuxt useState 2451 | 2452 | ```javascript 2453 | const ${1:state} = useState('${2:$1}'$3) 2454 | ``` 2455 | 2456 |
nstate:initNuxt useState (init) 2463 | 2464 | ```javascript 2465 | const ${1:state} = useState('${2:$1}', () => $3) 2466 | ``` 2467 | 2468 |
nheadNuxt useHead 2475 | 2476 | ```javascript 2477 | useHead({ 2478 | $1 2479 | }) 2480 | ``` 2481 | 2482 |
nhead:titleNuxt useHead title 2489 | 2490 | ```javascript 2491 | useHead({ 2492 | title: $1,$0 2493 | }) 2494 | ``` 2495 | 2496 |
npageMetaNuxt definePageMeta 2503 | 2504 | ```javascript 2505 | definePageMeta({ 2506 | $1 2507 | }) 2508 | ``` 2509 | 2510 |
npageMeta:titleNuxt definePageMeta title 2517 | 2518 | ```javascript 2519 | definePageMeta({ 2520 | title: '$1',$0 2521 | }) 2522 | ``` 2523 | 2524 |
npageMeta:layoutNuxt definePageMeta layout 2531 | 2532 | ```javascript 2533 | definePageMeta({ 2534 | layout: '$1',$0 2535 | }) 2536 | ``` 2537 | 2538 |
npageMeta:middlewareNuxt definePageMeta middleware 2545 | 2546 | ```javascript 2547 | definePageMeta({ 2548 | middleware: ['$1'$2],$0 2549 | }) 2550 | ``` 2551 | 2552 |
ntoNuxt navigateTo 2559 | 2560 | ```javascript 2561 | navigateTo('$1'$2) 2562 | ``` 2563 | 2564 |
nto:objNuxt navigateTo object 2571 | 2572 | ```javascript 2573 | navigateTo({ $1 }$2) 2574 | ``` 2575 | 2576 |
nto:replaceNuxt navigateTo replace 2583 | 2584 | ```javascript 2585 | navigateTo('$1', { replace: true }) 2586 | ``` 2587 | 2588 |
nto:externalNuxt navigateTo external 2595 | 2596 | ```javascript 2597 | navigateTo('$1', { external: true }) 2598 | ``` 2599 | 2600 |
nto:redirectNuxt navigateTo redirect 2607 | 2608 | ```javascript 2609 | navigateTo('$1', { redirectCode: ${2|301,302,...|} }) 2610 | ``` 2611 | 2612 |
nto:nameNuxt navigateTo name 2619 | 2620 | ```javascript 2621 | navigateTo({ 2622 | name: '$1',$0 2623 | }) 2624 | ``` 2625 | 2626 |
nto:pathNuxt navigateTo path 2633 | 2634 | ```javascript 2635 | navigateTo({ 2636 | path: '$1',$0 2637 | }) 2638 | ``` 2639 | 2640 |
npluginNuxt plugin 2647 | 2648 | ```javascript 2649 | export default defineNuxtPlugin((nuxtApp) => { 2650 | $1 2651 | }) 2652 | ``` 2653 | 2654 |
nplugin:vueNuxt plugin use vue package 2661 | 2662 | ```javascript 2663 | export default defineNuxtPlugin((nuxtApp) => { 2664 | nuxtApp.vueApp.use($1) 2665 | }) 2666 | ``` 2667 | 2668 |
nmiddleware:routeNuxt route middleware 2675 | 2676 | ```javascript 2677 | export default defineNuxtRouteMiddleware((to, from) => { 2678 | $1 2679 | }) 2680 | ``` 2681 | 2682 |
nmiddleware:serverNuxt server middleware 2689 | 2690 | ```javascript 2691 | export default defineEventHandler((event) => { 2692 | $1 2693 | }) 2694 | ``` 2695 | 2696 |
napiNuxt api route 2703 | 2704 | ```javascript 2705 | export default defineEventHandler(${1:async }(event) => { 2706 | $2 2707 | 2708 | return { 2709 | $3 2710 | } 2711 | }) 2712 | ``` 2713 | 2714 |
nplugin:serverNuxt server plugin 2721 | 2722 | ```javascript 2723 | export default defineNitroPlugin((nitroApp) => { 2724 | $1 2725 | }) 2726 | ``` 2727 | 2728 |
nreadBodyNuxt readBody 2735 | 2736 | ```javascript 2737 | const ${1:body} = await readBody(event) 2738 | ``` 2739 | 2740 |
ngetQueryNuxt getQuery 2747 | 2748 | ```javascript 2749 | const { $1 } = getQuery(event) 2750 | ``` 2751 | 2752 |
ngetCookieNuxt getCookie 2759 | 2760 | ```javascript 2761 | getCookie(event, '${1:cookie}') 2762 | ``` 2763 | 2764 |
nsetCookieNuxt setCookie 2771 | 2772 | ```javascript 2773 | setCookie(event, '${1:cookie}', ${2:value}) 2774 | ``` 2775 | 2776 |
2779 | 2780 | 2781 | ### Nuxt (template) 2782 | 2783 | 2784 | 2785 | 2786 | 2787 | 2788 | 2789 | 2790 | 2791 | 2792 | 2793 | 2794 | 2801 | 2802 | 2803 | 2804 | 2805 | 2806 | 2813 | 2814 | 2815 | 2816 | 2817 | 2818 | 2825 | 2826 | 2827 | 2828 | 2829 | 2830 | 2837 | 2838 | 2839 | 2840 | 2841 | 2842 | 2849 | 2850 | 2851 | 2852 | 2853 | 2854 | 2861 | 2862 | 2863 | 2864 | 2865 | 2866 | 2873 | 2874 | 2875 | 2876 | 2877 | 2878 | 2885 | 2886 | 2887 | 2888 | 2889 | 2890 | 2897 | 2898 | 2899 | 2900 | 2901 | 2902 | 2909 | 2910 | 2911 | 2912 | 2913 | 2914 | 2921 | 2922 | 2923 | 2924 | 2925 | 2926 | 2933 | 2934 | 2935 | 2936 | 2937 | 2938 | 2945 | 2946 | 2947 | 2948 | 2949 | 2950 | 2957 | 2958 | 2959 | 2960 | 2961 | 2962 | 2973 | 2974 | 2975 | 2976 | 2977 | 2978 | 2987 | 2988 |
PrefixNameBody
nlinkNuxtLink 2795 | 2796 | ```html 2797 | $3 2798 | ``` 2799 | 2800 |
nlink:blankNuxtLink with target _blank 2807 | 2808 | ```html 2809 | $4 2810 | ``` 2811 | 2812 |
nlink:externalNuxtLink with target external 2819 | 2820 | ```html 2821 | $5 2822 | ``` 2823 | 2824 |
nlink:paramNuxtLink with param 2831 | 2832 | ```html 2833 | $5 2834 | ``` 2835 | 2836 |
nlink:objNuxtLink with object 2843 | 2844 | ```html 2845 | $3 2846 | ``` 2847 | 2848 |
nlink:nameNuxtLink with name 2855 | 2856 | ```html 2857 | $4 2858 | ``` 2859 | 2860 |
nlink:pathNuxtLink with path 2867 | 2868 | ```html 2869 | $4 2870 | ``` 2871 | 2872 |
nloadingNuxtLoadingIndicator 2879 | 2880 | ```html 2881 | 2882 | ``` 2883 | 2884 |
nlayoutNuxtLayout 2891 | 2892 | ```html 2893 | $2 2894 | ``` 2895 | 2896 |
nlayout:nameNuxtLayout with name 2903 | 2904 | ```html 2905 | $4 2906 | ``` 2907 | 2908 |
npageNuxtPage 2915 | 2916 | ```html 2917 | 2918 | ``` 2919 | 2920 |
npage:staticNuxtPage with static key 2927 | 2928 | ```html 2929 | 2930 | ``` 2931 | 2932 |
nclientClientOnly 2939 | 2940 | ```html 2941 | $2 2942 | ``` 2943 | 2944 |
nclient:fallbacksClientOnly with fallback props 2951 | 2952 | ```html 2953 | $3 2954 | ``` 2955 | 2956 |
nclient:fallbackClientOnly with fallback template 2963 | 2964 | ```html 2965 | 2966 | 2969 | 2970 | ``` 2971 | 2972 |
nTeleportNuxt Teleport 2979 | 2980 | ```html 2981 | 2982 | $0 2983 | 2984 | ``` 2985 | 2986 |
2989 | 2990 | 2991 | ### VueUse (script) 2992 | 2993 | 2994 | 2995 | 2996 | 2997 | 2998 | 2999 | 3000 | 3001 | 3002 | 3003 | 3004 | 3011 | 3012 | 3013 | 3014 | 3015 | 3016 | 3025 | 3026 | 3027 | 3028 | 3029 | 3030 | 3039 | 3040 | 3041 | 3042 | 3043 | 3044 | 3053 | 3054 | 3055 | 3056 | 3057 | 3058 | 3067 | 3068 | 3069 | 3070 | 3071 | 3072 | 3081 | 3082 | 3083 | 3084 | 3085 | 3086 | 3095 | 3096 | 3097 | 3098 | 3099 | 3100 | 3109 | 3110 | 3111 | 3112 | 3113 | 3114 | 3123 | 3124 | 3125 | 3126 | 3127 | 3128 | 3137 | 3138 | 3139 | 3140 | 3141 | 3142 | 3151 | 3152 | 3153 | 3154 | 3155 | 3156 | 3165 | 3166 | 3167 | 3168 | 3169 | 3170 | 3177 | 3178 | 3179 | 3180 | 3181 | 3182 | 3189 | 3190 | 3191 | 3192 | 3193 | 3194 | 3202 | 3203 | 3204 | 3205 | 3206 | 3207 | 3214 | 3215 | 3216 | 3217 | 3218 | 3219 | 3226 | 3227 | 3228 | 3229 | 3230 | 3231 | 3238 | 3239 | 3240 | 3241 | 3242 | 3243 | 3250 | 3251 | 3252 | 3253 | 3254 | 3255 | 3262 | 3263 | 3264 | 3265 | 3266 | 3267 | 3274 | 3275 | 3276 | 3277 | 3278 | 3279 | 3286 | 3287 |
PrefixNameBody
vRefAutoResetVueUse refAutoReset 3005 | 3006 | ```javascript 3007 | const ${1:name} = refAutoReset('$2', ${3:1000}) 3008 | ``` 3009 | 3010 |
vwatchArrayVueUse watchArray 3017 | 3018 | ```javascript 3019 | watchArray(${1:list}, (new${1/(.*)/${1:/capitalize}/}, old${1/(.*)/${1:/capitalize}/}, ${4:added}, ${5:removed}) => { 3020 | $0 3021 | }) 3022 | ``` 3023 | 3024 |
vwatchAtMostVueUse watchAtMost 3031 | 3032 | ```javascript 3033 | watchAtMost(${1:source}, (${2:val}) => { 3034 | $0 3035 | }, { max: ${3:3} }) 3036 | ``` 3037 | 3038 |
vwatchDebouncedVueUse watchDebounced 3045 | 3046 | ```javascript 3047 | watchDebounced(${1:source}, (${2:val}) => { 3048 | $0 3049 | }, { debounce: ${3:500}, maxWait: ${4:1000} }) 3050 | ``` 3051 | 3052 |
vwatchIgnorableVueUse watchIgnorable 3059 | 3060 | ```javascript 3061 | const { stop:$3, ignoreUpdates:$4 } = = watchIgnorable(${1:source}, (${2:val}) => { 3062 | $0 3063 | }) 3064 | ``` 3065 | 3066 |
vwatchOnceVueUse watchOnce 3073 | 3074 | ```javascript 3075 | watchOnce(${1:source}, (${2:val}) => { 3076 | $0 3077 | }) 3078 | ``` 3079 | 3080 |
vwatchImmediateVueUse watchImmediate 3087 | 3088 | ```javascript 3089 | vwatchImmediate(${1:source}, (${2:val}) => { 3090 | $0 3091 | }) 3092 | ``` 3093 | 3094 |
vwatchPausableVueUse watchPausable 3101 | 3102 | ```javascript 3103 | const { stop$3, pause$4, resume$5 } = watchPausable(${1:source}, (${2:val}) => { 3104 | $0 3105 | }) 3106 | ``` 3107 | 3108 |
vwatchThrottledVueUse watchThrottled 3115 | 3116 | ```javascript 3117 | watchThrottled(${1:source}, (${2:val}) => { 3118 | $0 3119 | }, { throttle: ${3:500} }) 3120 | ``` 3121 | 3122 |
vwatchTriggerableVueUse watchTriggerable 3129 | 3130 | ```javascript 3131 | const { trigger$3, ignoreUpdates$4 } = watchTriggerable(${1:source}, (${2:val}) => { 3132 | $0 3133 | }) 3134 | ``` 3135 | 3136 |
vwatchWithFilterVueUse watchWithFilter 3143 | 3144 | ```javascript 3145 | watchWithFilter(${1:source}, (${2:val}) => { 3146 | $0 3147 | }, { eventFilter: $3 }) 3148 | ``` 3149 | 3150 |
vwheneverVueUse whenever 3157 | 3158 | ```javascript 3159 | whenever(${1:source}, (${2:val}) => { 3160 | $0 3161 | }) 3162 | ``` 3163 | 3164 |
vuse:vmodelImplement v-model using useVModel 3171 | 3172 | ```javascript 3173 | const ${2:value} = useVModel(props, '${1:modelValue}', emit) 3174 | ``` 3175 | 3176 |
vuse:vmodelsImplement v-model using useVModels 3183 | 3184 | ```javascript 3185 | const { ${1:modelValue}$2 } = useVModels(props, emit) 3186 | ``` 3187 | 3188 |
vuse:hoverVueUse useElementHover 3195 | 3196 | ```javascript 3197 | const ${1:elem} = ref<${2|HTMLInputElement,HTMLDivElement,...|} | null>(null) 3198 | const ${3:isHovered} = useElementHover($1) 3199 | ``` 3200 | 3201 |
vuse:fetch / vufVueUse useFetch 3208 | 3209 | ```javascript 3210 | const { data: ${1:data} } = useFetch('$2'$3) 3211 | ``` 3212 | 3213 |
vgetVueUse get 3220 | 3221 | ```javascript 3222 | get($1) 3223 | ``` 3224 | 3225 |
vsetVueUse set 3232 | 3233 | ```javascript 3234 | set($1, $2) 3235 | ``` 3236 | 3237 |
vdefVueUse isDefined 3244 | 3245 | ```javascript 3246 | isDefined($1) 3247 | ``` 3248 | 3249 |
vuse:toggle / vutVueUse useToggle 3256 | 3257 | ```javascript 3258 | const [${1:value}, ${2:toggle}] = useToggle() 3259 | ``` 3260 | 3261 |
vuse:toggle:fn / vuttVueUse useToggle function 3268 | 3269 | ```javascript 3270 | const toggle${2/(.*)/${1:/capitalize}/} = useToggle($1) 3271 | ``` 3272 | 3273 |
vuse:import / vuimImport from vueuse 3280 | 3281 | ```javascript 3282 | import { $1 } from '@vueuse/core' 3283 | ``` 3284 | 3285 |
3288 | 3289 | 3290 | ### Vue Macros 3291 | 3292 | 3293 | 3294 | 3295 | 3296 | 3297 | 3298 | 3299 | 3300 | 3301 | 3302 | 3303 | 3312 | 3313 | 3314 | 3315 | 3316 | 3317 | 3326 | 3327 | 3328 | 3329 | 3330 | 3331 | 3340 | 3341 | 3342 | 3343 | 3344 | 3345 | 3354 | 3355 | 3356 | 3357 | 3358 | 3359 | 3368 | 3369 | 3370 | 3371 | 3372 | 3373 | 3384 | 3385 |
PrefixNameBody
vdefineModels / vmacro:modelDefine models 3304 | 3305 | ```javascript 3306 | const { modelValue$2 } = defineModels<{ 3307 | modelValue: ${1:string} 3308 | }>() 3309 | ``` 3310 | 3311 |
vdefinePropsRefs / vmacro:propsDefine props refs 3318 | 3319 | ```javascript 3320 | const { $2 } = definePropsRefs<{ 3321 | $1 3322 | }>() 3323 | ``` 3324 | 3325 |
vdefineOptions / vmacro:optionsDefine options 3332 | 3333 | ```javascript 3334 | defineOptions({ 3335 | $0 3336 | }) 3337 | ``` 3338 | 3339 |
vdefineSlots / vmacro:slotsDefine slots 3346 | 3347 | ```javascript 3348 | defineSlots<{ 3349 | $0 3350 | }>() 3351 | ``` 3352 | 3353 |
vdefineRender / vmacro:renderDefine render 3360 | 3361 | ```javascript 3362 | defineRender( 3363 | $0 3364 | ) 3365 | ``` 3366 | 3367 |
vdefineRender:fn / vmacro:render:fnDefine render function 3374 | 3375 | ```javascript 3376 | defineRender(() => { 3377 | return ( 3378 | $0 3379 | ) 3380 | }) 3381 | ``` 3382 | 3383 |
3386 | 3387 | 3388 | 3389 | ## Running locally 3390 | 3391 | ```bash 3392 | # ensure Deno is installed 3393 | # https://deno.land/manual@v1.29.1/getting_started/installation 3394 | 3395 | # generate .code-snippets and documentation 3396 | deno task generate 3397 | ``` 3398 | -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matijaoe/vue-ecosystem-snippets/025c4ec53c23512f1cc5b9d39bdb9a2d6d547973/assets/icon.png -------------------------------------------------------------------------------- /deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "publish": "vsce package && vsce publish", 4 | "watch": "deno run -A --watch src/app.ts --snippets --docs", 5 | "generate": "deno run -A src/app.ts --snippets --docs", 6 | "generate:snippets": "deno run -A src/app.ts --snippets" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /deno.lock: -------------------------------------------------------------------------------- 1 | { 2 | "version": "3", 3 | "packages": { 4 | "specifiers": { 5 | "npm:replace-in-file": "npm:replace-in-file@6.3.5" 6 | }, 7 | "npm": { 8 | "ansi-regex@5.0.1": { 9 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 10 | "dependencies": {} 11 | }, 12 | "ansi-styles@4.3.0": { 13 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 14 | "dependencies": { 15 | "color-convert": "color-convert@2.0.1" 16 | } 17 | }, 18 | "balanced-match@1.0.2": { 19 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 20 | "dependencies": {} 21 | }, 22 | "brace-expansion@1.1.11": { 23 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 24 | "dependencies": { 25 | "balanced-match": "balanced-match@1.0.2", 26 | "concat-map": "concat-map@0.0.1" 27 | } 28 | }, 29 | "chalk@4.1.2": { 30 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 31 | "dependencies": { 32 | "ansi-styles": "ansi-styles@4.3.0", 33 | "supports-color": "supports-color@7.2.0" 34 | } 35 | }, 36 | "cliui@8.0.1": { 37 | "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 38 | "dependencies": { 39 | "string-width": "string-width@4.2.3", 40 | "strip-ansi": "strip-ansi@6.0.1", 41 | "wrap-ansi": "wrap-ansi@7.0.0" 42 | } 43 | }, 44 | "color-convert@2.0.1": { 45 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 46 | "dependencies": { 47 | "color-name": "color-name@1.1.4" 48 | } 49 | }, 50 | "color-name@1.1.4": { 51 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 52 | "dependencies": {} 53 | }, 54 | "concat-map@0.0.1": { 55 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 56 | "dependencies": {} 57 | }, 58 | "emoji-regex@8.0.0": { 59 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 60 | "dependencies": {} 61 | }, 62 | "escalade@3.1.1": { 63 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 64 | "dependencies": {} 65 | }, 66 | "fs.realpath@1.0.0": { 67 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 68 | "dependencies": {} 69 | }, 70 | "get-caller-file@2.0.5": { 71 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 72 | "dependencies": {} 73 | }, 74 | "glob@7.2.3": { 75 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 76 | "dependencies": { 77 | "fs.realpath": "fs.realpath@1.0.0", 78 | "inflight": "inflight@1.0.6", 79 | "inherits": "inherits@2.0.4", 80 | "minimatch": "minimatch@3.1.2", 81 | "once": "once@1.4.0", 82 | "path-is-absolute": "path-is-absolute@1.0.1" 83 | } 84 | }, 85 | "has-flag@4.0.0": { 86 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 87 | "dependencies": {} 88 | }, 89 | "inflight@1.0.6": { 90 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 91 | "dependencies": { 92 | "once": "once@1.4.0", 93 | "wrappy": "wrappy@1.0.2" 94 | } 95 | }, 96 | "inherits@2.0.4": { 97 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 98 | "dependencies": {} 99 | }, 100 | "is-fullwidth-code-point@3.0.0": { 101 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 102 | "dependencies": {} 103 | }, 104 | "minimatch@3.1.2": { 105 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 106 | "dependencies": { 107 | "brace-expansion": "brace-expansion@1.1.11" 108 | } 109 | }, 110 | "once@1.4.0": { 111 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 112 | "dependencies": { 113 | "wrappy": "wrappy@1.0.2" 114 | } 115 | }, 116 | "path-is-absolute@1.0.1": { 117 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 118 | "dependencies": {} 119 | }, 120 | "replace-in-file@6.3.5": { 121 | "integrity": "sha512-arB9d3ENdKva2fxRnSjwBEXfK1npgyci7ZZuwysgAp7ORjHSyxz6oqIjTEv8R0Ydl4Ll7uOAZXL4vbkhGIizCg==", 122 | "dependencies": { 123 | "chalk": "chalk@4.1.2", 124 | "glob": "glob@7.2.3", 125 | "yargs": "yargs@17.7.1" 126 | } 127 | }, 128 | "require-directory@2.1.1": { 129 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 130 | "dependencies": {} 131 | }, 132 | "string-width@4.2.3": { 133 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 134 | "dependencies": { 135 | "emoji-regex": "emoji-regex@8.0.0", 136 | "is-fullwidth-code-point": "is-fullwidth-code-point@3.0.0", 137 | "strip-ansi": "strip-ansi@6.0.1" 138 | } 139 | }, 140 | "strip-ansi@6.0.1": { 141 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 142 | "dependencies": { 143 | "ansi-regex": "ansi-regex@5.0.1" 144 | } 145 | }, 146 | "supports-color@7.2.0": { 147 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 148 | "dependencies": { 149 | "has-flag": "has-flag@4.0.0" 150 | } 151 | }, 152 | "wrap-ansi@7.0.0": { 153 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 154 | "dependencies": { 155 | "ansi-styles": "ansi-styles@4.3.0", 156 | "string-width": "string-width@4.2.3", 157 | "strip-ansi": "strip-ansi@6.0.1" 158 | } 159 | }, 160 | "wrappy@1.0.2": { 161 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 162 | "dependencies": {} 163 | }, 164 | "y18n@5.0.8": { 165 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 166 | "dependencies": {} 167 | }, 168 | "yargs-parser@21.1.1": { 169 | "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 170 | "dependencies": {} 171 | }, 172 | "yargs@17.7.1": { 173 | "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", 174 | "dependencies": { 175 | "cliui": "cliui@8.0.1", 176 | "escalade": "escalade@3.1.1", 177 | "get-caller-file": "get-caller-file@2.0.5", 178 | "require-directory": "require-directory@2.1.1", 179 | "string-width": "string-width@4.2.3", 180 | "y18n": "y18n@5.0.8", 181 | "yargs-parser": "yargs-parser@21.1.1" 182 | } 183 | } 184 | } 185 | }, 186 | "redirects": { 187 | "https://esm.sh/markdown-table@3": "https://esm.sh/markdown-table@3.0.3" 188 | }, 189 | "remote": { 190 | "https://deno.land/std@0.141.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74", 191 | "https://deno.land/std@0.141.0/_util/os.ts": "3b4c6e27febd119d36a416d7a97bd3b0251b77c88942c8f16ee5953ea13e2e49", 192 | "https://deno.land/std@0.141.0/fs/_util.ts": "0fb24eb4bfebc2c194fb1afdb42b9c3dda12e368f43e8f2321f84fc77d42cb0f", 193 | "https://deno.land/std@0.141.0/fs/ensure_dir.ts": "9dc109c27df4098b9fc12d949612ae5c9c7169507660dcf9ad90631833209d9d", 194 | "https://deno.land/std@0.141.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3", 195 | "https://deno.land/std@0.141.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09", 196 | "https://deno.land/std@0.141.0/path/_util.ts": "c1e9686d0164e29f7d880b2158971d805b6e0efc3110d0b3e24e4b8af2190d2b", 197 | "https://deno.land/std@0.141.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633", 198 | "https://deno.land/std@0.141.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee", 199 | "https://deno.land/std@0.141.0/path/mod.ts": "d3e68d0abb393fb0bf94a6d07c46ec31dc755b544b13144dee931d8d5f06a52d", 200 | "https://deno.land/std@0.141.0/path/posix.ts": "293cdaec3ecccec0a9cc2b534302dfe308adb6f10861fa183275d6695faace44", 201 | "https://deno.land/std@0.141.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9", 202 | "https://deno.land/std@0.141.0/path/win32.ts": "31811536855e19ba37a999cd8d1b62078235548d67902ece4aa6b814596dd757", 203 | "https://deno.land/std@0.168.0/_util/asserts.ts": "d0844e9b62510f89ce1f9878b046f6a57bf88f208a10304aab50efcb48365272", 204 | "https://deno.land/std@0.168.0/flags/mod.ts": "4f50ec6383c02684db35de38b3ffb2cd5b9fcfcc0b1147055d1980c49e82521c", 205 | "https://esm.sh/markdown-table@3.0.3": "caa0dd21025549ced82404779633939ea74977d21a60897da4ad4abd14867122", 206 | "https://esm.sh/v114/markdown-table@3.0.3/deno/markdown-table.mjs": "da67682e0275b8779bb5835d6debec160690e097f3111d0784630ce6dead2e66", 207 | "https://esm.sh/v114/markdown-table@3.0.3/index.d.ts": "d6fdaeb6f1e4e29d7827e30d743dfef5cb6c8bca4bc546001a3b3e751a2de06c" 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-nuxt-snippets", 3 | "version": "0.8.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "vue-nuxt-snippets", 9 | "version": "0.7.0", 10 | "license": "MIT", 11 | "engines": { 12 | "vscode": "^1.x.x" 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-nuxt-snippets", 3 | "displayName": "Vue Ecosystem Snippets", 4 | "description": "Snippets for the modern Vue ecosystem - including Nuxt 3, Pinia, VueUse, Vue Router & Vue Macros.", 5 | "version": "0.8.0", 6 | "license": "MIT", 7 | "icon": "assets/icon.png", 8 | "author": { 9 | "name": "Matija Osrečki", 10 | "email": "matija.osrecki@gmail.com" 11 | }, 12 | "publisher": "matijao", 13 | "repository": "https://github.com/mat2ja/vue-ecosystem-snippets", 14 | "bugs": "https://github.com/mat2ja/vue-ecosystem-snippets/issues", 15 | "engines": { 16 | "vscode": "^1.x.x" 17 | }, 18 | "categories": [ 19 | "Snippets" 20 | ], 21 | "keywords": [ 22 | "Vue", 23 | "Nuxt", 24 | "Vue 3", 25 | "Nuxt 3", 26 | "Pinia", 27 | "Volar", 28 | "VueUse", 29 | "Composition API", 30 | "TypeScript", 31 | "Vue Snippets", 32 | "Nuxt Snippets", 33 | "snippets", 34 | "snippet" 35 | ], 36 | "contributes": { 37 | "snippets": [ 38 | { 39 | "language": "vue", 40 | "path": "./dist/vue.code-snippets" 41 | }, 42 | { 43 | "language": "html", 44 | "path": "./dist/vue-template.code-snippets" 45 | }, 46 | { 47 | "language": "css", 48 | "path": "./dist/vue-style.code-snippets" 49 | }, 50 | { 51 | "language": "postcss", 52 | "path": "./dist/vue-style.code-snippets" 53 | }, 54 | { 55 | "language": "scss", 56 | "path": "./dist/vue-style.code-snippets" 57 | }, 58 | { 59 | "language": "sass", 60 | "path": "./dist/vue-style.code-snippets" 61 | }, 62 | { 63 | "language": "javascript", 64 | "path": "./dist/vue-script.code-snippets" 65 | }, 66 | { 67 | "language": "typescript", 68 | "path": "./dist/vue-script.code-snippets" 69 | }, 70 | { 71 | "language": "javascriptreact", 72 | "path": "./dist/vue-script.code-snippets" 73 | }, 74 | { 75 | "language": "typescriptreact", 76 | "path": "./dist/vue-script.code-snippets" 77 | }, 78 | { 79 | "language": "javascript", 80 | "path": "./dist/vue-router-script.code-snippets" 81 | }, 82 | { 83 | "language": "typescript", 84 | "path": "./dist/vue-router-script.code-snippets" 85 | }, 86 | { 87 | "language": "javascriptreact", 88 | "path": "./dist/vue-router-script.code-snippets" 89 | }, 90 | { 91 | "language": "typescriptreact", 92 | "path": "./dist/vue-router-script.code-snippets" 93 | }, 94 | { 95 | "language": "javascript", 96 | "path": "./dist/vue-router-script.code-snippets" 97 | }, 98 | { 99 | "language": "javascript", 100 | "path": "./dist/pinia.code-snippets" 101 | }, 102 | { 103 | "language": "typescript", 104 | "path": "./dist/pinia.code-snippets" 105 | }, 106 | { 107 | "language": "javascriptreact", 108 | "path": "./dist/pinia.code-snippets" 109 | }, 110 | { 111 | "language": "typescriptreact", 112 | "path": "./dist/pinia.code-snippets" 113 | }, 114 | { 115 | "language": "javascript", 116 | "path": "./dist/vueuse.code-snippets" 117 | }, 118 | { 119 | "language": "typescript", 120 | "path": "./dist/vueuse.code-snippets" 121 | }, 122 | { 123 | "language": "javascriptreact", 124 | "path": "./dist/vueuse.code-snippets" 125 | }, 126 | { 127 | "language": "typescriptreact", 128 | "path": "./dist/vueuse.code-snippets" 129 | }, 130 | { 131 | "language": "javascript", 132 | "path": "./dist/vue-macros.code-snippets" 133 | }, 134 | { 135 | "language": "typescript", 136 | "path": "./dist/vue-macros.code-snippets" 137 | }, 138 | { 139 | "language": "javascriptreact", 140 | "path": "./dist/vue-macros.code-snippets" 141 | }, 142 | { 143 | "language": "typescriptreact", 144 | "path": "./dist/vue-macros.code-snippets" 145 | }, 146 | { 147 | "language": "javascript", 148 | "path": "./dist/nuxt-script.code-snippets" 149 | }, 150 | { 151 | "language": "typescript", 152 | "path": "./dist/nuxt-script.code-snippets" 153 | }, 154 | { 155 | "language": "javascriptreact", 156 | "path": "./dist/nuxt-script.code-snippets" 157 | }, 158 | { 159 | "language": "typescriptreact", 160 | "path": "./dist/nuxt-script.code-snippets" 161 | }, 162 | { 163 | "language": "html", 164 | "path": "./dist/nuxt-template.code-snippets" 165 | }, 166 | { 167 | "language": "html", 168 | "path": "./dist/vue-router-template.code-snippets" 169 | } 170 | ] 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | import { parse } from "./deps.ts"; 2 | import { generateDocs, populateDocsBlock } from "./docgen/snippets.ts"; 3 | import { variants } from "./snippets/app.ts"; 4 | import { 5 | convertToVscSnippet, 6 | generateSnippets, 7 | groupSnippets, 8 | } from "./utils/snippets.ts"; 9 | 10 | const main = () => { 11 | const flags = parse(Deno.args, { 12 | boolean: ["snippets", "docs"], 13 | default: { snippets: false, docs: false }, 14 | }); 15 | 16 | if (!flags.snippets && !flags.docs) { 17 | return console.log( 18 | "Please specify at least one flag: --snippets or --docs", 19 | ); 20 | } 21 | 22 | // Convert XDefinitions to VscDefinitions, for every variant 23 | const variantsAsVsc = variants.map((variant) => { 24 | const snippetDefinitions = variant.snippetDefinitions 25 | .map((def) => ({ 26 | ...def, 27 | snippets: convertToVscSnippet(def.snippets), 28 | })); 29 | 30 | return { ...variant, snippetDefinitions }; 31 | }); 32 | 33 | if (flags.snippets) { 34 | console.log("\nGenerating snippets..."); 35 | 36 | variantsAsVsc.forEach((variant) => { 37 | const vscSnippetDict = groupSnippets( 38 | variant.snippetDefinitions.map((def) => def.snippets), 39 | ); 40 | generateSnippets(variant.fileName, vscSnippetDict); 41 | }); 42 | } 43 | 44 | // important to know it generates docs off of defined xSnippets 45 | // so .code-snippets could be out of date if you haven't run --snippets 46 | if (flags.docs) { 47 | console.log("\nGenerating docs..."); 48 | const docs = generateDocs(variantsAsVsc); 49 | populateDocsBlock(docs); 50 | } 51 | }; 52 | 53 | main(); 54 | -------------------------------------------------------------------------------- /src/deps.ts: -------------------------------------------------------------------------------- 1 | export { ensureDirSync } from "https://deno.land/std@0.141.0/fs/ensure_dir.ts"; 2 | export { parse } from "https://deno.land/std@0.168.0/flags/mod.ts"; 3 | export { markdownTable } from "https://esm.sh/markdown-table@3"; 4 | 5 | import replace, * as _replace from "npm:replace-in-file"; 6 | 7 | // Fix types 8 | export const replaceInFile = replace as unknown as ( 9 | config: _replace.ReplaceInFileConfig, 10 | ) => Promise<_replace.ReplaceResult[]>; 11 | -------------------------------------------------------------------------------- /src/docgen/snippets.ts: -------------------------------------------------------------------------------- 1 | import { replaceInFile } from "../deps.ts"; 2 | import { VscSnippetDefinition, VscSnippetVariant } from "../models/app.ts"; 3 | import { 4 | parseMultiline, 5 | replaceSymbol, 6 | replaceTabs, 7 | } from "../utils/general.ts"; 8 | import { 9 | $col, 10 | $colCode, 11 | $colCodeBlock, 12 | $row, 13 | $table, 14 | htmlComment, 15 | joinByDoubleNewLine, 16 | joinByNewLine, 17 | } from "./table-html.ts"; 18 | 19 | type SnippetRow = { 20 | prefix: string[]; 21 | name: string; 22 | body: string | string[]; 23 | }; 24 | 25 | const truncateOptions = (str: string) => { 26 | const regex = /\|([^|]+)\|/g; 27 | return str.replace(regex, (_match, p1) => { 28 | const [first, second, third] = p1.split(",").map((o: string) => o.trim()); 29 | if (!third) { 30 | return `|${first},${second}|`; 31 | } else { 32 | return `|${first},${second},...|`; 33 | } 34 | }); 35 | }; 36 | 37 | const snippetRow = ({ prefix, name, body }: SnippetRow, lang?: string) => { 38 | const cols = joinByNewLine([ 39 | $colCode(prefix), 40 | $col(name), 41 | $colCodeBlock(truncateOptions(replaceTabs(parseMultiline(body))), lang), 42 | ]); 43 | 44 | return $row(cols); 45 | }; 46 | 47 | const generateSnippetTable = (items: SnippetRow[], lang?: string) => { 48 | const headings = ["Prefix", "Name", "Body"]; 49 | const rows = items.map((item) => snippetRow(item, lang)); 50 | 51 | return $table(headings, rows); 52 | }; 53 | 54 | const generateSnippetSection = ({ meta, snippets }: VscSnippetDefinition) => { 55 | const title = `### ${meta.title}`; 56 | const description = meta.description ?? ""; 57 | const table = generateSnippetTable( 58 | Object.entries(snippets).map(([name, { body, prefix, description }]) => { 59 | return { 60 | name: replaceSymbol(name), 61 | body, 62 | prefix: Array.isArray(prefix) ? prefix : [prefix], 63 | description, 64 | }; 65 | }), 66 | meta.lang, 67 | ); 68 | 69 | return joinByNewLine([title, description, table, ""]); 70 | }; 71 | 72 | // there are no strict sections in this projects, maybe in the future divided by Vue, Nuxt, etc. 73 | const generateVariantSection = (variant: VscSnippetVariant) => { 74 | const sections = variant.snippetDefinitions.map(generateSnippetSection); 75 | 76 | return joinByNewLine(sections); 77 | }; 78 | 79 | export const generateDocs = (variants: VscSnippetVariant[]) => { 80 | return joinByDoubleNewLine(variants.map(generateVariantSection)); 81 | }; 82 | 83 | const docsGenId = "docgen"; 84 | const docsGen = { 85 | start: htmlComment(`START:${docsGenId}`), 86 | end: htmlComment(`END:${docsGenId}`), 87 | }; 88 | 89 | const docsBlock = (s: string) => { 90 | return joinByNewLine([docsGen.start, s, docsGen.end]); 91 | }; 92 | 93 | export const populateDocsBlock = async (input: string) => { 94 | const regex = new RegExp( 95 | `${docsGen.start}[\\s\\S]*?${docsGen.end}`, 96 | "g", 97 | ); 98 | 99 | const file = "./README.md"; 100 | const options = { 101 | files: file, 102 | from: regex, 103 | to: docsBlock(input), 104 | }; 105 | 106 | try { 107 | const results = await replaceInFile(options); 108 | const readmeResult = results.find((r) => r.file === file); 109 | 110 | if (readmeResult?.hasChanged) { 111 | console.log("✅ README updated"); 112 | } else { 113 | console.log("👍 README already up to date"); 114 | } 115 | } catch (error) { 116 | console.error("Error while updating README:", error); 117 | } 118 | }; 119 | -------------------------------------------------------------------------------- /src/docgen/table-html.ts: -------------------------------------------------------------------------------- 1 | export const joinInline = (s: string[]) => s.join(""); 2 | export const joinByNewLine = (s: string[]) => s.join("\n"); 3 | export const joinByDoubleNewLine = (s: string[]) => s.join("\n\n"); 4 | export const indent = (s: string, size = 2) => `${" ".repeat(size)}${s}`; 5 | export const escapeBackticks = (s: string) => s.replace(/`/g, "\`"); 6 | 7 | export const htmlComment = (s: string) => ``; 8 | export const code = (s: string) => { 9 | return `${s}`; 10 | }; 11 | 12 | export const codeBlock = (s: string, lang = "javascript") => { 13 | return joinByNewLine([ 14 | `${escapeBackticks("```" + lang)}`, 15 | s, 16 | `${escapeBackticks("```")}`, 17 | ]); 18 | }; 19 | 20 | export const $row = (s: string) => { 21 | return joinByNewLine(["", "", s, ""]); 22 | }; 23 | 24 | export const $col = (s: string) => { 25 | return `${s}`; 26 | }; 27 | export const $colCode = (s: string | string[]) => { 28 | if (Array.isArray(s)) { 29 | return joinInline(["", s.map(code).join(" / "), ""]); 30 | } 31 | return joinInline(["", code(s), ""]); 32 | }; 33 | 34 | export const $colCodeBlock = (s: string, lang?: string) => { 35 | return joinByDoubleNewLine(["", codeBlock(s, lang), ""]); 36 | }; 37 | 38 | export const $headerRow = (headers: string[]) => { 39 | const cols = joinByNewLine(headers.map($col)); 40 | return $row(cols); 41 | }; 42 | 43 | export const $table = (headings: string[], rows: string[]) => { 44 | return joinByNewLine([ 45 | '', 46 | $headerRow(headings), 47 | joinByNewLine(rows), 48 | "
", 49 | ]); 50 | }; 51 | -------------------------------------------------------------------------------- /src/models/app.ts: -------------------------------------------------------------------------------- 1 | export type VscSnippet = { 2 | prefix: string | string[]; 3 | body: string | string[]; 4 | description?: string; 5 | }; 6 | export type VscSnippetDict = Record; 7 | 8 | export type XSnippet = Omit & { name: string, alt?: string[] }; 9 | export type XSnippetDict = Record; 10 | 11 | export type SnippetMeta = { 12 | title: string; 13 | description?: string; 14 | lang?: string; 15 | }; 16 | 17 | export type SnippetDefinition = { 18 | meta: SnippetMeta; 19 | snippets: T; 20 | }; 21 | export type XSnippetDefinition = SnippetDefinition; 22 | export type VscSnippetDefinition = SnippetDefinition; 23 | 24 | export type SnippetVariant = { 25 | label?: string; 26 | description?: string; 27 | fileName: string; 28 | snippetDefinitions: T[]; 29 | }; 30 | 31 | export type XSnippetVariant = SnippetVariant; 32 | export type VscSnippetVariant = SnippetVariant; 33 | -------------------------------------------------------------------------------- /src/snippets/app.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetVariant } from "../models/app.ts"; 2 | import { nuxt } from "./nuxt/app.ts"; 3 | import { pinia } from "./pinia/app.ts"; 4 | import { vueMacros } from "./vue-macros/app.ts"; 5 | import { vueRouter } from "./vue-router/app.ts"; 6 | import { vue } from "./vue/app.ts"; 7 | import { vueUse } from "./vueuse/app.ts"; 8 | 9 | export const variants: XSnippetVariant[] = [ 10 | ...vue, 11 | ...vueRouter, 12 | ...pinia, 13 | ...nuxt, 14 | ...vueUse, 15 | ...vueMacros 16 | ]; 17 | -------------------------------------------------------------------------------- /src/snippets/nuxt/app.ts: -------------------------------------------------------------------------------- 1 | import { script } from "./script.ts"; 2 | import { template } from "./template.ts"; 3 | 4 | export const nuxt = [ 5 | { 6 | fileName: "nuxt-script", 7 | snippetDefinitions: [script], 8 | }, 9 | { 10 | fileName: "nuxt-template", 11 | snippetDefinitions: [template], 12 | }, 13 | ]; 14 | -------------------------------------------------------------------------------- /src/snippets/nuxt/script.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const script: XSnippetDefinition = { 4 | meta: { 5 | title: "Nuxt (script)", 6 | }, 7 | snippets: { 8 | nfetch: { 9 | name: "Nuxt useFetch", 10 | body: "const { data: ${1:data} } = await useFetch('$2'$3)", 11 | }, 12 | "nfetch:cb": { 13 | name: "Nuxt useFetch with callback", 14 | body: "const { data: ${1:data} } = await useFetch(() => '$2'$3)", 15 | }, 16 | "nfetch:lazy": { 17 | name: "Nuxt useLazyFetch", 18 | body: "const { pending, data: ${1:data} } = useLazyFetch('$2'$3)", 19 | }, 20 | "nfetch:lazy:cb": { 21 | name: "Nuxt useLazyFetch callback", 22 | body: "const { pending, data: ${1:data} } = useLazyFetch(() => '$2'$3)", 23 | }, 24 | "nfetch:post": { 25 | name: "Nuxt useFetch POST", 26 | body: [ 27 | "const { data: ${1:data} } = await useFetch('$2', {", 28 | "\tmethod: 'POST',", 29 | "\tbody: ${3:body},$4", 30 | "})", 31 | ], 32 | }, 33 | nasyncdata: { 34 | name: "Nuxt useAsyncData", 35 | body: 36 | "const { data: ${1:data} } = await useAsyncData('${2:key}', () => $$fetch('$3')$4)", 37 | }, 38 | "nasyncdata:lazy": { 39 | name: "Nuxt useLazyAsyncData", 40 | body: 41 | "const { pending, data: ${1:data} } = useLazyAsyncData('${2:key}', () => $$fetch('$3')$4)", 42 | }, 43 | napp: { 44 | name: "Nuxt useNuxtApp", 45 | body: "const app = useNuxtApp()", 46 | }, 47 | nappConfig: { 48 | name: "Nuxt useAppConfig", 49 | body: "const appConfig = useAppConfig()", 50 | }, 51 | nruntimeConfig: { 52 | name: "Nuxt useRuntimeConfig", 53 | body: "const config = useRuntimeConfig()", 54 | }, 55 | ncookie: { 56 | name: "Nuxt useCookie", 57 | body: "const ${1:cookie} = useCookie('${2:$1}'$3)", 58 | }, 59 | "ncookie:opts": { 60 | name: "Nuxt useCookie with options", 61 | body: "const ${1:cookie} = useCookie('${2:$1}', { $3 })", 62 | }, 63 | ndata: { 64 | name: "Nuxt useNuxtData", 65 | body: "const { data: ${2:$1} } = useNuxtData('${1:key}')", 66 | }, 67 | nerror: { 68 | name: "Nuxt useError", 69 | body: "const ${1:error} = useError()", 70 | }, 71 | nstate: { 72 | name: "Nuxt useState", 73 | body: "const ${1:state} = useState('${2:$1}'$3)", 74 | }, 75 | "nstate:init": { 76 | name: "Nuxt useState (init)", 77 | body: "const ${1:state} = useState('${2:$1}', () => $3)", 78 | }, 79 | nhead: { 80 | name: "Nuxt useHead", 81 | body: [ 82 | "useHead({", 83 | "\t$1", 84 | "})", 85 | ], 86 | }, 87 | "nhead:title": { 88 | name: "Nuxt useHead title", 89 | body: [ 90 | "useHead({", 91 | "\ttitle: $1,$0", 92 | "})", 93 | ], 94 | }, 95 | npageMeta: { 96 | name: "Nuxt definePageMeta", 97 | body: [ 98 | "definePageMeta({", 99 | "\t$1", 100 | "})", 101 | ], 102 | }, 103 | "npageMeta:title": { 104 | name: "Nuxt definePageMeta title", 105 | body: [ 106 | "definePageMeta({", 107 | "\ttitle: '$1',$0", 108 | "})", 109 | ], 110 | }, 111 | "npageMeta:layout": { 112 | name: "Nuxt definePageMeta layout", 113 | body: [ 114 | "definePageMeta({", 115 | "\tlayout: '$1',$0", 116 | "})", 117 | ], 118 | }, 119 | "npageMeta:middleware": { 120 | name: "Nuxt definePageMeta middleware", 121 | body: [ 122 | "definePageMeta({", 123 | "\tmiddleware: ['$1'$2],$0", 124 | "})", 125 | ], 126 | }, 127 | nto: { 128 | name: "Nuxt navigateTo", 129 | body: "navigateTo('$1'$2)", 130 | }, 131 | "nto:obj": { 132 | name: "Nuxt navigateTo object", 133 | body: "navigateTo({ $1 }$2)", 134 | }, 135 | "nto:replace": { 136 | name: "Nuxt navigateTo replace", 137 | body: "navigateTo('$1', { replace: true })", 138 | }, 139 | "nto:external": { 140 | name: "Nuxt navigateTo external", 141 | body: "navigateTo('$1', { external: true })", 142 | }, 143 | "nto:redirect": { 144 | name: "Nuxt navigateTo redirect", 145 | body: "navigateTo('$1', { redirectCode: ${2|301,302,307|} })", 146 | }, 147 | "nto:name": { 148 | name: "Nuxt navigateTo name", 149 | body: [ 150 | "navigateTo({", 151 | "\tname: '$1',$0", 152 | "})", 153 | ], 154 | }, 155 | "nto:path": { 156 | name: "Nuxt navigateTo path", 157 | body: [ 158 | "navigateTo({", 159 | "\tpath: '$1',$0", 160 | "})", 161 | ], 162 | }, 163 | nplugin: { 164 | name: "Nuxt plugin", 165 | body: [ 166 | "export default defineNuxtPlugin((nuxtApp) => {", 167 | "\t$1", 168 | "})", 169 | ], 170 | }, 171 | "nplugin:vue": { 172 | name: "Nuxt plugin use vue package", 173 | body: [ 174 | "export default defineNuxtPlugin((nuxtApp) => {", 175 | "\tnuxtApp.vueApp.use($1)", 176 | "})", 177 | ], 178 | }, 179 | "nmiddleware:route": { 180 | name: "Nuxt route middleware", 181 | body: [ 182 | "export default defineNuxtRouteMiddleware((to, from) => {", 183 | "\t$1", 184 | "})", 185 | ], 186 | }, 187 | "nmiddleware:server": { 188 | name: "Nuxt server middleware", 189 | body: [ 190 | "export default defineEventHandler((event) => {", 191 | "\t$1", 192 | "})", 193 | ], 194 | }, 195 | napi: { 196 | name: "Nuxt api route", 197 | body: [ 198 | "export default defineEventHandler(${1:async }(event) => {", 199 | "\t$2", 200 | "\t", 201 | "\treturn {", 202 | "\t\t$3", 203 | "\t}", 204 | "})", 205 | ], 206 | }, 207 | "nplugin:server": { 208 | name: "Nuxt server plugin", 209 | body: [ 210 | "export default defineNitroPlugin((nitroApp) => {", 211 | "\t$1", 212 | "})", 213 | ], 214 | }, 215 | nreadBody: { 216 | name: "Nuxt readBody", 217 | body: "const ${1:body} = await readBody(event)", 218 | }, 219 | ngetQuery: { 220 | name: "Nuxt getQuery", 221 | body: "const { $1 } = getQuery(event)", 222 | }, 223 | ngetCookie: { 224 | name: "Nuxt getCookie", 225 | body: "getCookie(event, '${1:cookie}')", 226 | }, 227 | nsetCookie: { 228 | name: "Nuxt setCookie", 229 | body: "setCookie(event, '${1:cookie}', ${2:value})", 230 | }, 231 | }, 232 | }; 233 | -------------------------------------------------------------------------------- /src/snippets/nuxt/template.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const template: XSnippetDefinition = { 4 | meta: { 5 | title: "Nuxt (template)", 6 | lang: "html", 7 | }, 8 | snippets: { 9 | nlink: { 10 | name: "NuxtLink", 11 | body: '$3', 12 | }, 13 | "nlink:blank": { 14 | name: "NuxtLink with target _blank", 15 | body: '$4', 16 | }, 17 | "nlink:external": { 18 | name: "NuxtLink with target external", 19 | body: 20 | '$5', 21 | }, 22 | "nlink:param": { 23 | name: "NuxtLink with param", 24 | body: '$5', 25 | }, 26 | "nlink:obj": { 27 | name: "NuxtLink with object", 28 | body: '$3', 29 | }, 30 | "nlink:name": { 31 | name: "NuxtLink with name", 32 | body: `$4`, 33 | }, 34 | "nlink:path": { 35 | name: "NuxtLink with path", 36 | body: `$4`, 37 | }, 38 | "nloading": { 39 | name: "NuxtLoadingIndicator", 40 | body: ``, 41 | }, 42 | nlayout: { 43 | name: "NuxtLayout", 44 | body: "$2", 45 | }, 46 | "nlayout:name": { 47 | name: "NuxtLayout with name", 48 | body: '$4', 49 | }, 50 | npage: { 51 | name: "NuxtPage", 52 | body: "", 53 | }, 54 | "npage:static": { 55 | name: "NuxtPage with static key", 56 | body: '', 57 | }, 58 | nclient: { 59 | name: "ClientOnly", 60 | body: "$2", 61 | }, 62 | "nclient:fallbacks": { 63 | name: "ClientOnly with fallback props", 64 | body: 65 | '$3', 66 | }, 67 | "nclient:fallback": { 68 | name: "ClientOnly with fallback template", 69 | body: [ 70 | "", 71 | "\t", 74 | "", 75 | ], 76 | }, 77 | nTeleport: { 78 | name: "Nuxt Teleport", 79 | body: '\n\t$0\n', 80 | }, 81 | }, 82 | }; 83 | -------------------------------------------------------------------------------- /src/snippets/pinia/app.ts: -------------------------------------------------------------------------------- 1 | import { script } from "./script.ts"; 2 | 3 | export const pinia = [ 4 | { 5 | fileName: "pinia", 6 | snippetDefinitions: [script], 7 | }, 8 | ]; 9 | -------------------------------------------------------------------------------- /src/snippets/pinia/script.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const script: XSnippetDefinition = { 4 | meta: { 5 | title: "Pinia", 6 | }, 7 | snippets: { 8 | pstore: { 9 | name: "Setup Pinia store", 10 | body: [ 11 | "import { defineStore } from 'pinia'", 12 | "", 13 | "export const use${TM_FILENAME_BASE/^(.*)$/${1:/pascalcase}/}Store = defineStore('$TM_FILENAME_BASE', () => {", 14 | "\t$0", 15 | "\t", 16 | "\treturn {", 17 | "\t ", 18 | "\t}", 19 | "})", 20 | "", 21 | ], 22 | }, 23 | "pstore:options": { 24 | name: "Setup Pinia store (Options)", 25 | body: [ 26 | "import { defineStore } from 'pinia'", 27 | "", 28 | "export const use${TM_FILENAME_BASE/^(.*)$/${1:/pascalcase}/}Store = defineStore('$TM_FILENAME_BASE', {", 29 | " state: () => ({", 30 | " $0", 31 | " }),", 32 | " getters: {},", 33 | " actions: {},", 34 | "})", 35 | "" 36 | ], 37 | }, 38 | vuseStore: { 39 | name: "Use store", 40 | body: "const ${2:$1Store} = use${1/(.*)/${1:/capitalize}/}Store()", 41 | alt: ["vus"], 42 | }, 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /src/snippets/vue-macros/app.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetVariant } from "../../models/app.ts"; 2 | import { script } from "./script.ts"; 3 | 4 | export const vueMacros: XSnippetVariant[] = [ 5 | { 6 | label: "Vue Macros", 7 | fileName: "vue-macros", 8 | snippetDefinitions: [script], 9 | }, 10 | ]; 11 | -------------------------------------------------------------------------------- /src/snippets/vue-macros/script.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const script: XSnippetDefinition = { 4 | meta: { 5 | title: "Vue Macros", 6 | lang: "javascript", 7 | }, 8 | snippets: { 9 | vdefineModels: { 10 | name: "Define models", 11 | body: [ 12 | "const { modelValue$2 } = defineModels<{", 13 | "\tmodelValue: ${1:string}", 14 | "}>()", 15 | ], 16 | alt: ["vmacro:model"], 17 | }, 18 | vdefinePropsRefs: { 19 | name: "Define props refs", 20 | body: [ 21 | "const { $2 } = definePropsRefs<{", 22 | "\t$1", 23 | "}>()", 24 | ], 25 | alt: ["vmacro:props"], 26 | }, 27 | vdefineOptions: { 28 | name: "Define options", 29 | body: [ 30 | "defineOptions({", 31 | "\t$0", 32 | "})", 33 | ], 34 | alt: ["vmacro:options"], 35 | }, 36 | vdefineSlots: { 37 | name: "Define slots", 38 | body: [ 39 | "defineSlots<{", 40 | "\t$0", 41 | "}>()", 42 | ], 43 | alt: ["vmacro:slots"], 44 | }, 45 | vdefineRender: { 46 | name: "Define render", 47 | body: [ 48 | "defineRender(", 49 | "\t$0", 50 | ")", 51 | ], 52 | alt: ["vmacro:render"], 53 | }, 54 | "vdefineRender:fn": { 55 | name: "Define render function", 56 | "body": [ 57 | "defineRender(() => {", 58 | "\treturn (", 59 | "\t\t$0", 60 | "\t)", 61 | "})", 62 | ], 63 | alt: ["vmacro:render:fn"], 64 | }, 65 | }, 66 | }; 67 | -------------------------------------------------------------------------------- /src/snippets/vue-router/app.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetVariant } from "../../models/app.ts"; 2 | import { template } from "./template.ts"; 3 | import { script } from "./script.ts"; 4 | 5 | export const vueRouter: XSnippetVariant[] = [ 6 | { 7 | fileName: "vue-router-script", 8 | snippetDefinitions: [script], 9 | }, 10 | { 11 | fileName: "vue-router-template", 12 | snippetDefinitions: [template], 13 | }, 14 | ]; 15 | -------------------------------------------------------------------------------- /src/snippets/vue-router/script.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const script: XSnippetDefinition = { 4 | meta: { 5 | title: "Vue Router (script)", 6 | lang: "javascript", 7 | }, 8 | snippets: { 9 | vrouter: { 10 | name: "Vue router", 11 | body: "const ${1:router} = useRouter()", 12 | }, 13 | vroute: { 14 | name: "Vue route", 15 | body: "const ${1:route} = useRoute()", 16 | }, 17 | "vrouter:create": { 18 | name: "Create Vue router", 19 | body: [ 20 | "const router = createRouter({", 21 | "\thistory: createWebHashHistory(),", 22 | "\troutes: ${1:routes},", 23 | "\tscrollBehavior(to, from, savedPosition) {", 24 | "\t\t$2", 25 | "\t}", 26 | "})" 27 | ], 28 | }, 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/snippets/vue-router/template.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const template: XSnippetDefinition = { 4 | meta: { 5 | title: "Vue Router (template)", 6 | lang: "html", 7 | }, 8 | snippets: { 9 | vto: { 10 | name: "Vue Router to", 11 | body: '${1|to,:to|}="$2"', 12 | }, 13 | "vto:param": { 14 | name: "Vue Router :to with param", 15 | body: ':to="`$1${${2:id}}$3`"', 16 | }, 17 | "vto:obj": { 18 | name: "Vue Router :to object", 19 | body: ':to="{ $1 }"', 20 | }, 21 | "vto:name": { 22 | name: "Vue Router :to name", 23 | body: `:to="{ name: '$1',$2 }"`, 24 | }, 25 | "vto:path": { 26 | name: "Vue Router :to path", 27 | body: `:to="{ path: '$1',$2 }"`, 28 | }, 29 | vview: { 30 | name: "RouterView", 31 | body: "\n\t$0\n", 32 | }, 33 | vlink: { 34 | name: "RouterLink", 35 | body: '$3', 36 | }, 37 | "vlink:param": { 38 | name: "RouterLink with param", 39 | body: '$4', 40 | }, 41 | "vlink:obj": { 42 | name: "RouterLink with object", 43 | body: '$2', 44 | }, 45 | "vlink:name": { 46 | name: "RouterLink with name", 47 | body: `$3`, 48 | }, 49 | "vlink:path": { 50 | name: "RouterLink with path", 51 | body: `$3`, 52 | }, 53 | }, 54 | }; 55 | -------------------------------------------------------------------------------- /src/snippets/vue/app.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetVariant } from "../../models/app.ts"; 2 | 3 | import { codeSnippets } from "./code-snippets.ts"; 4 | import { script } from "./script.ts"; 5 | import { style } from "./style.ts"; 6 | import { template } from "./template.ts"; 7 | import { vueSfc } from "./vue.ts"; 8 | 9 | export const vue: XSnippetVariant[] = [ 10 | { 11 | fileName: "vue", 12 | snippetDefinitions: [vueSfc], 13 | }, 14 | { 15 | fileName: "vue-template", 16 | snippetDefinitions: [template], 17 | }, 18 | { 19 | fileName: "vue-style", 20 | snippetDefinitions: [style], 21 | }, 22 | { 23 | fileName: "vue-script", 24 | snippetDefinitions: [script, codeSnippets], 25 | }, 26 | ]; 27 | -------------------------------------------------------------------------------- /src/snippets/vue/code-snippets.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const codeSnippets: XSnippetDefinition = { 4 | meta: { 5 | title: "Code snippets", 6 | description: "Useful vue snippets and helpers", 7 | }, 8 | snippets: { 9 | vcomposable: { 10 | name: "Vue define composable", 11 | body: [ 12 | "export const use${1/(.*)/${1:/pascalcase}/} = () => {", 13 | "\t$0", 14 | "\t", 15 | "\treturn {", 16 | "\t\t", 17 | "\t}", 18 | "}", 19 | "", 20 | ], 21 | alt: ["vdc"], 22 | }, 23 | "vcomposable:file": { 24 | name: "Vue define composable in file", 25 | body: [ 26 | "export const use${TM_FILENAME_BASE/^(.*)$/${1:/pascalcase}/} = () => {", 27 | "\t$0", 28 | "\t", 29 | "\treturn {", 30 | "\t\t", 31 | "\t}", 32 | "}", 33 | "", 34 | ], 35 | alt: ["vdcf"], 36 | }, 37 | vuse: { 38 | name: "Use composable", 39 | body: "const ${2:$1} = use${1/(.*)/${1:/capitalize}/}($3)", 40 | alt: ["vu"], 41 | }, 42 | vused: { 43 | name: "Use composable with destructuring", 44 | body: "const { $2 } = use${1/(.*)/${1:/capitalize}/}($3)", 45 | alt: ["vud"], 46 | }, 47 | "vmodel:manual": { 48 | name: "Implement v-model manually", 49 | body: [ 50 | "const props = defineProps<{", 51 | "\t${1:modelValue}: ${2:string}", 52 | "}>()", 53 | "", 54 | "const emit = defineEmits<{", 55 | "\t(e: 'update:$1', ${3:value}?: $2): void", 56 | "}>()", 57 | "", 58 | "const ${4:value} = computed({", 59 | "\tget: () => props.$1,", 60 | "\tset: (val: $2) => emit('update:$1', val),", 61 | "})", 62 | ], 63 | }, 64 | "v:has-slot": { 65 | name: "Vue check for slots", 66 | body: [ 67 | "const slots = useSlots()", 68 | "const hasSlot = (name: string) => !!slots[name]", 69 | ], 70 | }, 71 | }, 72 | }; 73 | -------------------------------------------------------------------------------- /src/snippets/vue/script.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const script: XSnippetDefinition = { 4 | meta: { 5 | title: "Script", 6 | description: "Script setup and composables", 7 | lang: "javascript", 8 | }, 9 | snippets: { 10 | vref: { 11 | name: "Vue ref", 12 | body: "const ${1:name} = ref($2)", 13 | alt: ["vr"], 14 | }, 15 | "vref:ts": { 16 | name: "Vue ref (typed)", 17 | body: "const ${1:name} = ref<$2>($3)", 18 | alt: ["vrt"], 19 | }, 20 | vcomputed: { 21 | name: "Vue computed", 22 | body: "const ${1:name} = computed(() => $2)", 23 | alt: ["vc"], 24 | }, 25 | "vcomputed:ts": { 26 | name: "Vue computed (typed)", 27 | body: "const ${1:name} = computed<$2>(() => $3)", 28 | alt: ["vct"], 29 | }, 30 | "vcomputed:gs": { 31 | name: "Vue computed (get/set)", 32 | body: [ 33 | "const ${1:name} = computed({", 34 | "\tget: () => ${2},", 35 | "\tset: (${3:value}: ${4:string}) => {", 36 | "\t\t${5}", 37 | "\t},", 38 | "})", 39 | ], 40 | alt: ["vcgs"], 41 | }, 42 | vreactive: { 43 | name: "Vue reactive", 44 | body: "const ${1:name} = reactive({$2})", 45 | alt: ["vra"], 46 | }, 47 | "vreactive:ts": { 48 | name: "Vue reactive (typed)", 49 | body: "const ${1:name}: ${2:type} = reactive({$3})", 50 | }, 51 | vshallowRef: { 52 | name: "Vue shallowRef", 53 | body: "const ${1:name} = shallowRef($2)", 54 | }, 55 | vtoRef: { 56 | name: "Vue toRef", 57 | body: "toRef(${1:props}, '$2')", 58 | }, 59 | vtoRefs: { 60 | name: "Vue toRefs", 61 | body: "toRefs(${1:props})", 62 | }, 63 | vunref: { 64 | name: "Vue unref", 65 | body: "unref($1)", 66 | }, 67 | vreadonly: { 68 | name: "Vue readonly", 69 | body: "readonly(${1:object})", 70 | }, 71 | "vref:elem": { 72 | name: "Vue element ref", 73 | body: 74 | "const ${1:elem} = ref<${2|HTMLInputElement,HTMLInputElement,HTMLDivElement,HTMLFormElement|} | null>(null)", 75 | }, 76 | vwatchEffect: { 77 | name: "Vue watchEffect", 78 | body: "watchEffect(() => {\n\t$0\n})", 79 | }, 80 | vwatch: { 81 | name: "Vue watch source", 82 | body: "watch(${1:source}, (${2:val}) => {\n\t$0\n})", 83 | }, 84 | "vwatch:inline": { 85 | name: "Vue watch inline", 86 | body: "watch(${1:source}, ${2:fn})", 87 | }, 88 | "vwatch:getter": { 89 | name: "Vue watch getter", 90 | body: "watch(() => ${1:source}, (${2:val}) => {\n\t$0\n})", 91 | }, 92 | "vwatch:multiple": { 93 | name: "Vue watch multiple", 94 | body: 95 | "watch([${1:source1}, ${2:source2}], ([new${1/(.*)/${1:/capitalize}/}, new${2/(.*)/${1:/capitalize}/}]) => {\n\t$0\n})", 96 | }, 97 | "vwatch:immediate": { 98 | name: "Vue watch immediate", 99 | body: "watch(${1:source}, (${2:val}) => {\n\t$0\n}, { immediate: true })", 100 | }, 101 | "vwatch:deep": { 102 | name: "Vue watch deep", 103 | body: "watch(${1:source}, (${2:val}) => {\n\t$0\n}, { deep: true })", 104 | }, 105 | "vwatch:log": { 106 | name: "Vue watch source | log", 107 | body: [ 108 | "watch(${1:source}, (${2:val}) => {", 109 | "\tconsole.log('$1:', $2)", 110 | "})", 111 | ], 112 | alt: ["vwl"], 113 | }, 114 | vprops: { 115 | name: "Vue defineProps", 116 | body: "${1:const props = }defineProps<${2:Props}>()", 117 | }, 118 | "vprops:defaults": { 119 | name: "Vue defineProps with defaults", 120 | body: [ 121 | "${1:const props = }withDefaults(defineProps<${2:Props}>(), {\n\t$0\n})", 122 | ], 123 | }, 124 | "vprops:js": { 125 | name: "Vue defineProps without TS", 126 | body: "${1:const props = }defineProps({\n\t$2\n})", 127 | }, 128 | vemits: { 129 | name: "Vue defineEmits", 130 | body: [ 131 | "${1:const emit = }defineEmits<{", 132 | "\t${2:click}: [${3:payload}: ${4:string}],$5", 133 | "}>()", 134 | ], 135 | }, 136 | "vemits:alt": { 137 | name: "Vue defineEmits without TS", 138 | body: "${1:const emit = }defineEmits(['$2'])", 139 | }, 140 | "vemits:old": { 141 | name: "Vue defineEmits (old syntax)", 142 | body: [ 143 | "${1:const emit = }defineEmits<{", 144 | "\t(e: '${2:click}', ${3:payload}: ${4:string}): void,$5", 145 | "}>()", 146 | ], 147 | }, 148 | vmodel: { 149 | name: "Vue defineModel", 150 | body: "const ${1:modelValue} = defineModel<${2:string}>($3)", 151 | }, 152 | vemit: { 153 | name: "Vue emit event", 154 | body: "emit('$1'$2)", 155 | }, 156 | vexpose: { 157 | name: "Vue defineExpose", 158 | body: [ 159 | "defineExpose({\n\t$1\n})", 160 | ], 161 | }, 162 | "v:onMounted": { 163 | name: "Vue onMounted", 164 | body: [ 165 | "onMounted(() => {\n\t$0\n})", 166 | ], 167 | }, 168 | "v:onBeforeMount": { 169 | name: "Vue onBeforeMount", 170 | body: [ 171 | "onBeforeMount(() => {\n\t$0\n})", 172 | ], 173 | }, 174 | "v:onUnmounted": { 175 | name: "Vue onUnmounted", 176 | body: [ 177 | "onUnmounted(() => {\n\t$0\n})", 178 | ], 179 | }, 180 | "v:onBeforeUnmount": { 181 | name: "Vue onBeforeUnmount", 182 | body: [ 183 | "onBeforeUnmount(() => {\n\t$0\n})", 184 | ], 185 | }, 186 | "v:onUpdated": { 187 | name: "Vue onUpdated", 188 | body: [ 189 | "onUpdated(() => {\n\t$0\n})", 190 | ], 191 | }, 192 | "v:onBeforeUpdate": { 193 | name: "Vue onBeforeUpdate", 194 | body: [ 195 | "onBeforeUpdate(() => {\n\t$0\n})", 196 | ], 197 | }, 198 | "v:onErrorCaptured": { 199 | name: "Vue onErrorCaptured", 200 | body: [ 201 | "onErrorCaptured(() => {\n\t$0\n})", 202 | ], 203 | }, 204 | "v:onActivated": { 205 | name: "Vue onActivated", 206 | body: [ 207 | "onActivated(() => {\n\t$0\n})", 208 | ], 209 | }, 210 | "v:onDeactivated": { 211 | name: "Vue onDeactivated", 212 | body: [ 213 | "onDeactivated(() => {\n\t$0\n})", 214 | ], 215 | }, 216 | vprovide: { 217 | name: "Vue provide", 218 | body: "provide(${1:key}, ${2:value})", 219 | }, 220 | "vprovide:ts": { 221 | name: "Vue provide (typed)", 222 | body: "provide<${1:string}>(${2:key}, ${3:value})", 223 | }, 224 | vinject: { 225 | name: "Vue inject", 226 | body: "const ${1:value} = inject(${2:key})", 227 | }, 228 | "vinject:ts": { 229 | name: "Vue inject (typed)", 230 | body: "const ${1:value} = inject<${2:string}>(${3:key})", 231 | }, 232 | "vinject:default": { 233 | name: "Vue inject with default", 234 | body: "const ${1:value} = inject(${2:key}, ${3:defaultValue})", 235 | }, 236 | "vinjectkey": { 237 | name: "Vue injection key", 238 | body: "const ${1:key} = Symbol('$2') as InjectionKey<${3:string}>", 239 | }, 240 | vslots: { 241 | name: "Vue useSlots", 242 | body: "const slots = useSlots()", 243 | }, 244 | vattrs: { 245 | name: "Vue useAttrs", 246 | body: "const attrs = useAttrs()", 247 | }, 248 | vimport: { 249 | name: "Import from vue", 250 | body: "import { $1 } from 'vue'", 251 | alt: ["vim"], 252 | }, 253 | }, 254 | }; 255 | -------------------------------------------------------------------------------- /src/snippets/vue/style.ts: -------------------------------------------------------------------------------- 1 | export const style = { 2 | meta: { 3 | title: "Style", 4 | lang: "css", 5 | }, 6 | snippets: { 7 | vbind: { 8 | name: "v-bind", 9 | body: "v-bind($0)", 10 | }, 11 | deep: { 12 | name: ":deep()", 13 | body: ":deep($1)", 14 | }, 15 | slot: { 16 | name: ":slotted()", 17 | body: ":slotted($1)", 18 | }, 19 | global: { 20 | name: ":global()", 21 | body: ":global($1)", 22 | }, 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /src/snippets/vue/template.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const template: XSnippetDefinition = { 4 | meta: { 5 | title: "Template", 6 | lang: "html", 7 | }, 8 | snippets: { 9 | slot: { 10 | name: "slot", 11 | body: "$0", 12 | }, 13 | template: { 14 | name: "template", 15 | body: "", 16 | alt: ["vtemplate"] 17 | }, 18 | component: { 19 | name: "component", 20 | body: "$0", 21 | alt: ["vcomponent"] 22 | }, 23 | nslot: { 24 | name: "named slot", 25 | body: [ 26 | '', 27 | "\t$0", 28 | "", 29 | ], 30 | }, 31 | ntemplate: { 32 | name: "named template", 33 | body: [ 34 | "", 37 | ], 38 | }, 39 | vcomponent: { 40 | name: "Vue component", 41 | body: '$0', 42 | }, 43 | vKeepAlive: { 44 | name: "Vue KeepAlive", 45 | "body": [ 46 | "\n\t$0\n", 47 | ], 48 | }, 49 | vTeleport: { 50 | name: "Vue teleport", 51 | body: '\n\t$0\n', 52 | }, 53 | vTransition: { 54 | name: "Vue Transition", 55 | body: "\n\t$0\n", 56 | }, 57 | "vTransition:name": { 58 | name: "Vue Transition with name", 59 | body: '\n\t$0\n', 60 | alt: ["nTransition"], 61 | }, 62 | "vTransition:type": { 63 | name: "Vue Transition with type", 64 | body: 65 | '\n\t$0\n', 66 | }, 67 | "vTransition:appear": { 68 | name: "Vue Transition with appear", 69 | body: "\n\t$0\n", 70 | }, 71 | vTransitionGroup: { 72 | name: "Vue TransitionGroup", 73 | body: 74 | '\n\t$0\n', 75 | }, 76 | vSuspense: { 77 | name: "Vue Suspense", 78 | body: "\n\t$0\n", 79 | }, 80 | "vSuspense:fallback": { 81 | name: "Vue Suspense with fallback", 82 | body: [ 83 | "", 84 | "\t$0", 85 | "\t", 88 | "", 89 | ], 90 | }, 91 | vtext: { 92 | name: "v-text", 93 | body: 'v-text="$1"', 94 | }, 95 | vhtml: { 96 | name: "v-html", 97 | body: 'v-html="$1"', 98 | }, 99 | vshow: { 100 | name: "v-show", 101 | body: 'v-show="$1"', 102 | }, 103 | vif: { 104 | name: "v-if", 105 | body: 'v-if="$1"', 106 | alt: ["if"], 107 | }, 108 | veif: { 109 | name: "v-else-if", 110 | body: 'v-else-if="$1"', 111 | alt: ["elif"], 112 | }, 113 | velse: { 114 | name: "v-else", 115 | body: "v-else", 116 | alt: ["else"], 117 | }, 118 | vfor: { 119 | name: "v-for", 120 | body: 'v-for="${2:item} in ${1:items}" :key="$2$3"', 121 | }, 122 | vfori: { 123 | name: "v-for (indexed)", 124 | body: 'v-for="(${2:item}, ${3:i}) in ${1:items}" :key="${4:$3}"', 125 | }, 126 | vforr: { 127 | name: "v-for range", 128 | body: 'v-for="${1:n} in ${2:5}" :key="$1"', 129 | }, 130 | vemit: { 131 | name: "emit", 132 | body: "emit('$1'$2)", 133 | alt: ["emit"] 134 | }, 135 | "vemit:pass": { 136 | name: "Vue pass emit", 137 | body: 138 | "@${1|click,input,change,focus,blur|}=\"\\$emit('${2:$1}', \\$event)\"", 139 | }, 140 | von: { 141 | name: "v-on", 142 | body: 'v-on="${1:emits}"', 143 | }, 144 | "von:event": { 145 | name: "event handler", 146 | body: '@$1="$2"', 147 | alt: ['voe'] 148 | }, 149 | "von:click": { 150 | name: "click handler", 151 | body: '@click="${1:onClick}"', 152 | alt: ['voc'] 153 | }, 154 | "von:input": { 155 | name: "input handler", 156 | body: '@input="${1:onInput}"', 157 | alt: ['voi'] 158 | }, 159 | "von:update": { 160 | name: "update handler", 161 | body: '@update="${1:onUpdate}"', 162 | }, 163 | "von:change": { 164 | name: "change handler", 165 | body: '@change="${1:onChange}"', 166 | }, 167 | "von:blur": { 168 | name: "blur handler", 169 | body: '@blur="${1:onBlur}"', 170 | }, 171 | "von:focus": { 172 | name: "focus handler", 173 | body: '@focus="${1:onFocus}"', 174 | }, 175 | "von:submit": { 176 | name: "submit handler", 177 | body: '@submit${1:.prevent}="${2:onSubmit}"', 178 | }, 179 | vbind: { 180 | name: "v-bind", 181 | body: 'v-bind="$1"', 182 | }, 183 | "vbind:attrs": { 184 | name: "v-bind attrs", 185 | body: 'v-bind="\\$attrs"', 186 | }, 187 | "vbind:props": { 188 | name: "v-bind props", 189 | body: 'v-bind="\\$props"', 190 | }, 191 | "vbind:full": { 192 | name: "v-bind props and attrs", 193 | body: 'v-bind="[\\$props, \\$attrs]"', 194 | }, 195 | vmodel: { 196 | name: "v-model", 197 | body: 'v-model="$1"', 198 | }, 199 | "vmodel:number": { 200 | name: "v-model.number", 201 | body: 'v-model.number="$1"', 202 | }, 203 | "vmodel:trim": { 204 | name: "v-model.trim", 205 | body: 'v-model.trim="$1"', 206 | }, 207 | "vmodel:custom": { 208 | name: "custom v-model", 209 | body: 'v-model:${1:custom}="$2"', 210 | }, 211 | vslot: { 212 | name: "scoped slot", 213 | body: 'v-slot="{$1}"', 214 | }, 215 | vpre: { 216 | name: "v-pre", 217 | body: 'v-pre="$1"', 218 | }, 219 | vonce: { 220 | name: "v-once", 221 | body: "v-once", 222 | }, 223 | vmemo: { 224 | name: "v-memo", 225 | body: 'v-memo="[$1]"', 226 | }, 227 | vcloak: { 228 | name: "v-cloak", 229 | body: "v-cloak", 230 | }, 231 | vkey: { 232 | name: "Vue key", 233 | body: ':key="$1"', 234 | }, 235 | vref: { 236 | name: "Vue ref", 237 | body: 'ref="$1"', 238 | }, 239 | vname: { 240 | name: "name property", 241 | body: '${1|name,:name|}="$2"', 242 | }, 243 | vis: { 244 | name: "is property", 245 | body: '${1|is,:is|}="$2"', 246 | }, 247 | vb: { 248 | name: "bind attribute", 249 | body: ':${1:prop}="${2:$1}"', 250 | }, 251 | va: { 252 | name: "attribute", 253 | body: '${1:prop}="$2"', 254 | }, 255 | vclass: { 256 | name: "Vue classes", 257 | body: `:class="$1"`, 258 | alt: ["vc"], 259 | }, 260 | "vclass:list": { 261 | name: "Vue classes list", 262 | body: `:class="[$1]"`, 263 | alt: ["vca"], 264 | }, 265 | "vclass:cond": { 266 | name: "Vue conditional classes", 267 | body: `:class="{ $1: $2 }"`, 268 | alt: ["vcc"], 269 | }, 270 | vstyle: { 271 | name: "Vue inline style", 272 | body: `:style="{ $1: $2 }"`, 273 | }, 274 | "vstyle:list": { 275 | name: "Vue inline style list", 276 | body: `:style="[$1]"`, 277 | }, 278 | vv: { 279 | name: "Vue ", 280 | body: "{{ $1 }}", 281 | }, 282 | vvt: { 283 | name: "Vue i18n translation", 284 | body: "{{ t('$1') }}", 285 | }, 286 | "vif:slot": { 287 | name: "v-if slot defined", 288 | body: 'v-if="\\$slots.${1:default}"', 289 | }, 290 | "vif:slot-prop": { 291 | name: "v-if slot or prop defined", 292 | body: 'v-if="\\$slots.${1:label} || ${2:$1}"', 293 | }, 294 | vform: { 295 | name: "form submit.prevent", 296 | body: [ 297 | '
', 298 | "\t$0", 299 | "
", 300 | ], 301 | }, 302 | "vfor:template": { 303 | name: "v-for in template", 304 | body: [ 305 | '<${1|template,div,li|} v-for="${3:item} in ${2:items}" :key="$3$4">', 306 | "\t$0", 307 | "", 308 | ], 309 | }, 310 | "vfori:template": { 311 | name: "v-for (indexed) in template", 312 | body: [ 313 | '<${1|template,div,li|} v-for="(${3:item}, ${4:i}) in ${2:items}" :key="${5:$4}">', 314 | "\t$0", 315 | "", 316 | ], 317 | }, 318 | "vif:template": { 319 | name: "v-if in template", 320 | body: [ 321 | '<${1|template,div,p,ul,section|} v-if="$2">', 322 | "\t$0", 323 | "", 324 | ], 325 | }, 326 | "vtif": { 327 | name: "template with v-if", 328 | body: [ 329 | '", 332 | ], 333 | }, 334 | "vdif": { 335 | name: "div with v-if", 336 | body: [ 337 | '
', 338 | "\t$0", 339 | "
", 340 | ], 341 | }, 342 | }, 343 | }; 344 | -------------------------------------------------------------------------------- /src/snippets/vue/vue.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const vueSfc: XSnippetDefinition = { 4 | meta: { 5 | title: "Vue SFC", 6 | description: "`.vue` files", 7 | lang: "html", 8 | }, 9 | snippets: { 10 | vbase: { 11 | name: "Vue SFC", 12 | body: [ 13 | '", 16 | "", 17 | "", 20 | "", 21 | ], 22 | }, 23 | "vbase:full": { 24 | name: "Vue SFC with style | postcss", 25 | body: [ 26 | '", 29 | "", 30 | "", 33 | "", 34 | '", 37 | "", 38 | ], 39 | }, 40 | "vbase:full:css": { 41 | name: "Vue SFC with style | css", 42 | body: [ 43 | '", 46 | "", 47 | "", 50 | "", 51 | '", 54 | "", 55 | ], 56 | }, 57 | "vbase:full:scss": { 58 | name: "Vue SFC with style | scss", 59 | body: [ 60 | '", 63 | "", 64 | "", 67 | "", 68 | '", 71 | "", 72 | ], 73 | }, 74 | "vbase:full:less": { 75 | name: "Vue SFC with style | less", 76 | body: [ 77 | '", 80 | "", 81 | "", 84 | "", 85 | '", 88 | "", 89 | ], 90 | }, 91 | vscript: { 92 | name: "Vue script setup | ts", 93 | body: [ 94 | '", 97 | "", 98 | ], 99 | }, 100 | "vscript:js": { 101 | name: "Vue script setup | js", 102 | body: [ 103 | "", 106 | "", 107 | ], 108 | }, 109 | vtemplate: { 110 | name: "Vue template", 111 | body: [ 112 | "", 115 | "", 116 | ], 117 | }, 118 | vstyle: { 119 | name: "Vue scoped style | postcss", 120 | body: [ 121 | '", 124 | "", 125 | ], 126 | }, 127 | "vstyle:lang": { 128 | name: "Vue style with language option", 129 | body: [ 130 | '", 133 | "", 134 | ], 135 | }, 136 | "vstyle:css": { 137 | name: "Vue scoped style | css", 138 | body: [ 139 | '", 142 | "", 143 | ], 144 | }, 145 | "vstyle:scss": { 146 | name: "scoped style | scss", 147 | body: [ 148 | '", 151 | "", 152 | ], 153 | }, 154 | "vstyle:less": { 155 | name: "scoped style | less", 156 | body: [ 157 | '", 160 | "", 161 | ], 162 | }, 163 | "vstyle:module": { 164 | name: "Vue style with CSS modules", 165 | body: [ 166 | "", 169 | "", 170 | ], 171 | }, 172 | "vstyle:src": { 173 | name: "Vue scoped style with src", 174 | body: [ 175 | `", 178 | "", 179 | ], 180 | }, 181 | }, 182 | }; 183 | -------------------------------------------------------------------------------- /src/snippets/vueuse/app.ts: -------------------------------------------------------------------------------- 1 | import { vueUseJs } from "./js.ts"; 2 | 3 | export const vueUse = [ 4 | { 5 | fileName: "vueuse", 6 | snippetDefinitions: [vueUseJs], 7 | }, 8 | ]; 9 | -------------------------------------------------------------------------------- /src/snippets/vueuse/js.ts: -------------------------------------------------------------------------------- 1 | import { XSnippetDefinition } from "../../models/app.ts"; 2 | 3 | export const vueUseJs: XSnippetDefinition = { 4 | meta: { 5 | title: "VueUse (script)", 6 | }, 7 | snippets: { 8 | "vRefAutoReset": { 9 | name: "VueUse refAutoReset", 10 | body: 11 | "const ${1:name} = refAutoReset('$2', ${3:1000})", 12 | }, 13 | "vwatchArray": { 14 | name: "VueUse watchArray", 15 | body: 16 | "watchArray(${1:list}, (new${1/(.*)/${1:/capitalize}/}, old${1/(.*)/${1:/capitalize}/}, ${4:added}, ${5:removed}) => {\n\t$0\n})", 17 | }, 18 | "vwatchAtMost": { 19 | name: "VueUse watchAtMost", 20 | body: 21 | "watchAtMost(${1:source}, (${2:val}) => {\n\t$0\n}, { max: ${3:3} })", 22 | }, 23 | "vwatchDebounced": { 24 | name: "VueUse watchDebounced", 25 | body: 26 | "watchDebounced(${1:source}, (${2:val}) => {\n\t$0\n}, { debounce: ${3:500}, maxWait: ${4:1000} })", 27 | }, 28 | "vwatchIgnorable": { 29 | name: "VueUse watchIgnorable", 30 | body: 31 | "const { stop:$3, ignoreUpdates:$4 } = = watchIgnorable(${1:source}, (${2:val}) => {\n\t$0\n})", 32 | }, 33 | "vwatchOnce": { 34 | name: "VueUse watchOnce", 35 | body: "watchOnce(${1:source}, (${2:val}) => {\n\t$0\n})", 36 | }, 37 | "vwatchImmediate": { 38 | name: "VueUse watchImmediate", 39 | body: 40 | "vwatchImmediate(${1:source}, (${2:val}) => {\n\t$0\n})", 41 | }, 42 | "vwatchPausable": { 43 | name: "VueUse watchPausable", 44 | body: 45 | "const { stop$3, pause$4, resume$5 } = watchPausable(${1:source}, (${2:val}) => {\n\t$0\n})", 46 | }, 47 | "vwatchThrottled": { 48 | name: "VueUse watchThrottled", 49 | body: 50 | "watchThrottled(${1:source}, (${2:val}) => {\n\t$0\n}, { throttle: ${3:500} })", 51 | }, 52 | "vwatchTriggerable": { 53 | name: "VueUse watchTriggerable", 54 | body: 55 | "const { trigger$3, ignoreUpdates$4 } = watchTriggerable(${1:source}, (${2:val}) => {\n\t$0\n})", 56 | }, 57 | "vwatchWithFilter": { 58 | name: "VueUse watchWithFilter", 59 | body: 60 | "watchWithFilter(${1:source}, (${2:val}) => {\n\t$0\n}, { eventFilter: $3 })", 61 | }, 62 | "vwhenever": { 63 | name: "VueUse whenever", 64 | body: "whenever(${1:source}, (${2:val}) => {\n\t$0\n})", 65 | }, 66 | "vuse:vmodel": { 67 | name: "Implement v-model using useVModel", 68 | body: [ 69 | "const ${2:value} = useVModel(props, '${1:modelValue}', emit)", 70 | ], 71 | }, 72 | "vuse:vmodels": { 73 | name: "Implement v-model using useVModels", 74 | body: [ 75 | "const { ${1:modelValue}$2 } = useVModels(props, emit)", 76 | ], 77 | }, 78 | "vuse:hover": { 79 | name: "VueUse useElementHover", 80 | body: [ 81 | "const ${1:elem} = ref<${2|HTMLInputElement,HTMLDivElement,HTMLImageElement,HTMLFormElement|} | null>(null)", 82 | "const ${3:isHovered} = useElementHover($1)", 83 | ], 84 | }, 85 | "vuse:fetch": { 86 | name: "VueUse useFetch", 87 | body: "const { data: ${1:data} } = useFetch('$2'$3)", 88 | alt: ["vuf"], 89 | }, 90 | vget: { 91 | name: "VueUse get", 92 | body: "get($1)", 93 | }, 94 | vset: { 95 | name: "VueUse set", 96 | body: "set($1, $2)", 97 | }, 98 | vdef: { 99 | name: "VueUse isDefined", 100 | body: "isDefined($1)", 101 | }, 102 | "vuse:toggle": { 103 | name: "VueUse useToggle", 104 | body: "const [${1:value}, ${2:toggle}] = useToggle()", 105 | alt: ["vut"] 106 | }, 107 | "vuse:toggle:fn": { 108 | name: "VueUse useToggle function", 109 | body: "const toggle${2/(.*)/${1:/capitalize}/} = useToggle($1)", 110 | alt: ["vutt"] 111 | }, 112 | "vuse:import": { 113 | name: "Import from vueuse", 114 | body: "import { $1 } from '@vueuse/core'", 115 | alt: ["vuim"], 116 | }, 117 | }, 118 | }; 119 | -------------------------------------------------------------------------------- /src/utils/general.ts: -------------------------------------------------------------------------------- 1 | const SYMBOL = "🟢"; 2 | 3 | export const replaceSymbol = (str: string) => str.replace(` ${SYMBOL}`, ""); 4 | export const addSymbol = (str: string) => `${str} ${SYMBOL}`; 5 | 6 | export const parseMultiline = (s: string | string[]) => { 7 | return Array.isArray(s) ? s.join("\n") : s; 8 | }; 9 | 10 | export const replaceTabs = (s: string) => s.replace(/\t/g, " "); 11 | -------------------------------------------------------------------------------- /src/utils/snippets.ts: -------------------------------------------------------------------------------- 1 | import { ensureDirSync } from "../deps.ts"; 2 | import { VscSnippetDict, XSnippetDict } from "../models/app.ts"; 3 | import { addSymbol } from "./general.ts"; 4 | 5 | export const convertToVscSnippet = (snippets: XSnippetDict) => { 6 | return Object.entries(snippets) 7 | .reduce((acc, [prefix, { name, body, alt }]) => { 8 | const prefixes = [prefix]; 9 | if (alt?.length) { 10 | prefixes.push(...alt); 11 | } 12 | acc[addSymbol(name)] = { prefix: prefixes, body }; 13 | return acc; 14 | }, {} as VscSnippetDict); 15 | }; 16 | 17 | export const groupSnippets = (dicts: VscSnippetDict[]) => { 18 | return dicts.reduce((acc, curr) => ({ 19 | ...acc, 20 | ...curr, 21 | })); 22 | }; 23 | 24 | export const generateSnippets = (name: string, data: VscSnippetDict) => { 25 | const path = "./dist"; 26 | const fileName = `${name}.code-snippets`; 27 | try { 28 | ensureDirSync(path); 29 | const file = `${path}/${fileName}`; 30 | 31 | Deno.writeTextFileSync( 32 | file, 33 | JSON.stringify(data, null, 2), 34 | ); 35 | 36 | console.log(`✅ ${fileName}`); 37 | } catch (error) { 38 | console.log(`❌ ${fileName}`); 39 | console.error(error); 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /vsc-extension-quickstart.md: -------------------------------------------------------------------------------- 1 | # Welcome to your VS Code Extension 2 | 3 | ## What's in the folder 4 | 5 | * This folder contains all of the files necessary for your extension. 6 | * `package.json` - this is the manifest file that defines the location of the snippet file and specifies the language of the snippets. 7 | * `snippets/snippets.code-snippets` - the file containing all snippets. 8 | 9 | ## Get up and running straight away 10 | 11 | * Press `F5` to open a new window with your extension loaded. 12 | * Create a new file with a file name suffix matching your language. 13 | * Verify that your snippets are proposed on IntelliSense. 14 | 15 | ## Make changes 16 | 17 | * You can relaunch the extension from the debug toolbar after making changes to the files listed above. 18 | * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. 19 | 20 | ## Install your extension 21 | 22 | * To start using your extension with Visual Studio Code copy it into the `/.vscode/extensions` folder and restart Code. 23 | * To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension. 24 | --------------------------------------------------------------------------------