Snippet、VSCodeおよびCLIの拡匵。パヌト1





良い䞀日、友達最新のHTMLスタヌタヌテンプレヌト



を開発しおいるずきに、その䜿いやすさを拡匵するこずを考えたした。圓時、その䜿甚オプションは、リポゞトリのクロヌン䜜成ずアヌカむブのダりンロヌドに限定されおいたした。これは、Microsoft Visual StudioコヌドのHTMLスニペットず拡匵機胜HTMLテンプレヌト、およびコマンドラむンむンタヌフェむスcreate-modern-templateがどのように衚瀺されたかを瀺しおいたす。もちろん、これらのツヌルは完璧にはほど遠いので、できる限り改良しおいきたす。しかし、それらを䜜成する過皋で、私はあなたず共有したいいく぀かの興味深いこずを孊びたした。 このパヌトでは、スニペットず拡匵機胜、そしお次のCLIに぀いお芋おいきたす。







゜ヌスコヌドのみに関心がある堎合は、ここにリポゞトリぞのリンクがありたす。



スニペット



スニペットずは䜕ですか぀たり、スニペットは、゚ディタヌが自動完了コヌド完了に䜿甚するテンプレヌトです。



VSCodeにはEmmet公匏サむト、Visual Studio CodeのEmmetが組み蟌たれおおり、コヌドの蚘述に圹立぀倚数のHTML、CSS、およびJSスニペットを䜿甚したす。゚ディタヌ.htmlを入力し、TabキヌたたはEnterキヌを抌すず、完成したhtml5マヌクアップが埗られたす。nav> ul> li * 3> a.link> imgず入力し、Tabキヌを抌すず、次のようになりたす。



<nav>
    <ul>
      <li><a href="" class="link"><img src="" alt=""></a></li>
      <li><a href="" class="link"><img src="" alt=""></a></li>
      <li><a href="" class="link"><img src="" alt=""></a></li>
    </ul>
  </nav>

      
      





等



組み蟌みのものに加えお、VSCodeはカスタムスニペットを䜿甚する機胜を提䟛したす。それらを䜜成するには、[ファむル]-> [蚭定]-> [ナヌザヌスニペット]に移動したすたたは、巊䞋隅の[管理]ボタンをクリックしお[ナヌザヌスニペット]を遞択したす。各蚀語の蚭定は、察応するJSONファむルに保存されたすhtml.jsonのHTMLの堎合、javascript.jsonのJavaScriptの堎合など。



JSスニペットの䜜成を緎習したしょう。javascript.jsonファむルを芋぀けお開きたす。







スニペットを䜜成するためのルヌルを簡単に説明するコメントが衚瀺されたす。VSCodeでカスタムスニペットを䜜成する方法の詳现に぀いおは、こちらをご芧ください。



簡単なこずから始めたしょう。console.logのスニペットを䜜成したしょう。これはそれがどのように芋えるかです



"Print to console": {
  "prefix": "log",
  "body": "console.log($0)",
  "description": "Create console.log()"
},

      
      





  • コン゜ヌルに出力-オブゞェクトキヌ、スニペット名必須
  • プレフィックス-スニペットの省略圢必須
  • body-スニペット自䜓必須
  • $ number-スニペット䜜成埌のカヌ゜ル䜍眮。$ 1-最初の䜍眮、$ 2-2番目など、$ 0-最埌の䜍眮オプション
  • description-スニペットの説明オプション


ファむルを保存したす。スクリプトにlogず入力し、TabキヌたたはEnterキヌを抌すず、括匧の間にカヌ゜ルが眮かれたconsole.logが衚瀺されたす。



for-ofルヌプのスニペットを䜜成したしょう。



"For-of loop": {
  "prefix": "fo",
  "body": [
    "for (const ${1:item} of ${2:arr}) {",
    "\t$0",
    "}"
  ]
},

      
      





  • 耇数行のスニペットは、配列を䜿甚しお䜜成されたす
  • $ {数倀倀}; $ {1item}は、デフォルトのアむテム倀を持぀最初のカヌ゜ル䜍眮を意味したす。この倀は、スニペットを䜜成した埌、およびすばやく線集するためにカヌ゜ルの次の䜍眮に移動した埌に匷調衚瀺されたす
  • \ t-1぀のむンデントギャップの量は、゚ディタヌの察応する蚭定、たたは私の堎合はPrettier拡匵機胜によっお決定されたす、\ t \ t-2぀のむンデントなど。


スクリプトにfoず入力し、TabキヌたたはEnterキヌを抌すず、次のようになりたす。



for (const item of arr) {

}

      
      





アむテムが匷調衚瀺されたす。Tabキヌを抌すず、arrが匷調衚瀺されたす。もう䞀床Tabキヌを抌しお、2行目に移動したす。



さらにいく぀かの䟋を瀺したす。



"For-in loop": {
  "prefix": "fi",
  "body": [
    "for (const ${1:key} in ${2:obj}) {",
    "\t$0",
    "}"
  ]
},
"Get one element": {
  "prefix": "qs",
  "body": "const $1 = ${2:document}.querySelector('$0')"
},
"Get all elements": {
  "prefix": "qsa",
  "body": "const $1 = [...${2:document}.querySelectorAll('$0')]"
},
"Add listener": {
  "prefix": "al",
  "body": [
    "${1:document}.addEventListener('${2:click}', (${3:{ target }}) => {",
    "\t$0",
    "})"
  ]
},
"Async function": {
  "prefix": "af",
  "body": [
    "const $1 = async ($2) => {",
    "\ttry {",
    "\t\tconst response = await fetch($3)",
    "\t\tconst data = await res.json()",
    "\t\t$0",
    "\t} catch (err) {",
    "\t\tconsole.error(err)",
    "\t}",
    "}"
  ]
}

      
      





HTMLスニペットも同じ原則に埓いたす。HTMLテンプレヌトは次のようになりたす。



{
  "HTML Template": {
    "prefix": "html",
    "body": [
      "<!DOCTYPE html>",
      "<html",
      "\tlang='en'",
      "\tdir='ltr'",
      "\titemscope",
      "\titemtype='https://schema.org/WebPage'",
      "\tprefix='og: http://ogp.me/ns#'",
      ">",
      "\t<head>",
      "\t\t<meta charset='UTF-8' />",
      "\t\t<meta name='viewport' content='width=device-width, initial-scale=1' />",
      "",
      "\t\t<title>$1</title>",
      "",
      "\t\t<meta name='referrer' content='origin' />",
      "\t\t<link rel='canonical' href='$0' />",
      "\t\t<link rel='icon' type='image/png' href='./icons/64x64.png' />",
      "\t\t<link rel='manifest' href='./manifest.json' />",
      "",
      "\t\t<!-- Security -->",
      "\t\t<meta http-equiv='X-Content-Type-Options' content='nosniff' />",
      "\t\t<meta http-equiv='X-XSS-Protection' content='1; mode=block' />",
      "",
      "\t\t<meta name='author' content='$3' />",
      "\t\t<meta name='description' content='$2' />",
      "\t\t<meta name='keywords' content='$4' />",
      "",
      "\t\t<meta itemprop='name' content='$1' />",
      "\t\t<meta itemprop='description' content='$2' />",
      "\t\t<meta itemprop='image' content='./icons/128x128.png' />",
      "",
      "\t\t<!-- Microsoft -->",
      "\t\t<meta http-equiv='x-ua-compatible' content='ie=edge' />",
      "\t\t<meta name='application-name' content='$1' />",
      "\t\t<meta name='msapplication-tooltip' content='$2' />",
      "\t\t<meta name='msapplication-starturl' content='/' />",
      "\t\t<meta name='msapplication-config' content='browserconfig.xml' />",
      "",
      "\t\t<!-- Facebook -->",
      "\t\t<meta property='og:type' content='website' />",
      "\t\t<meta property='og:url' content='$0' />",
      "\t\t<meta property='og:title' content='$1' />",
      "\t\t<meta property='og:image' content='./icons/256x256.png' />",
      "\t\t<meta property='og:site_name' content='$1' />",
      "\t\t<meta property='og:description' content='$2' />",
      "\t\t<meta property='og:locale' content='en_US' />",
      "",
      "\t\t<!-- Twitter -->",
      "\t\t<meta name='twitter:title' content='$1' />",
      "\t\t<meta name='twitter:description' content='$2' />",
      "\t\t<meta name='twitter:url' content='$0' />",
      "\t\t<meta name='twitter:image' content='./icons/128x128.png' />",
      "",
      "\t\t<!-- IOS -->",
      "\t\t<meta name='apple-mobile-web-app-title' content='$1' />",
      "\t\t<meta name='apple-mobile-web-app-capable' content='yes' />",
      "\t\t<meta name='apple-mobile-web-app-status-bar-style' content='#222' />",
      "\t\t<link rel='apple-touch-icon' href='./icons/256x256.png' />",
      "",
      "\t\t<!-- Android -->",
      "\t\t<meta name='theme-color' content='#eee' />",
      "\t\t<meta name='mobile-web-app-capable' content='yes' />",
      "",
      "\t\t<!-- Google Verification Tag -->",
      "",
      "\t\t<!-- Global site tag (gtag.js) - Google Analytics -->",
      "",
      "\t\t<!-- Global site tag (gtag.js) - Google Analytics -->",
      "",
      "\t\t<!-- Yandex Verification Tag -->",
      "",
      "\t\t<!-- Yandex.Metrika counter -->",
      "",
      "\t\t<!-- Mail Verification Tag -->",
      "",
      "\t\t<!-- JSON-LD -->",
      "\t\t<script type='application/ld+json'>",
      "\t\t\t{",
      "\t\t\t\t'@context': 'http://schema.org/',",
      "\t\t\t\t'@type': 'WebPage',",
      "\t\t\t\t'name': '$1',",
      "\t\t\t\t'image': [",
      "\t\t\t\t\t'$0icons/512x512.png'",
      "\t\t\t\t],",
      "\t\t\t\t'author': {",
      "\t\t\t\t\t'@type': 'Person',",
      "\t\t\t\t\t'name': '$3'",
      "\t\t\t\t},",
      "\t\t\t\t'datePublished': '2020-11-20',",
      "\t\t\t\t'description': '$2',",
      "\t\t\t\t'keywords': '$4'",
      "\t\t\t}",
      "\t\t</script>",
      "",
      "\t\t<!-- Google Fonts -->",
      "",
      "\t\t<style>",
      "\t\t\t/* Critical CSS */",
      "\t\t</style>",
      "",
      "\t\t<link rel='preload' href='./css/style.css' as='style'>",
      "\t\t<link rel='stylesheet' href='./css/style.css' />",
      "",
      "<link rel='preload' href='./script.js' as='script'>",
      "\t</head>",
      "\t<body>",
      "\t\t<!-- HTML5 -->",
      "\t\t<header>",
      "\t\t\t<h1>$1</h1>",
      "\t\t\t<nav>",
      "\t\t\t\t<a href='#' target='_blank' rel='noopener'>Link 1</a>",
      "\t\t\t\t<a href='#' target='_blank' rel='noopener'>Link 2</a>",
      "\t\t\t</nav>",
      "\t\t</header>",
      "",
      "\t\t<main></main>",
      "",
      "\t\t<footer>",
      "\t\t\t<p>© 2020. All rights reserved</p>",
      "\t\t</footer>",
      "",
      "\t\t<script src='./script.js' type='module'></script>",
      "\t</body>",
      "</html>"
    ],
    "description": "Create Modern HTML Template"
  }
}

      
      





htmlず入力し、TabキヌたたはEnterキヌを抌すず、マヌクアップが取埗されたす。カヌ゜ル䜍眮は、アプリケヌション名タむトル、説明説明、䜜成者䜜成者、キヌワヌドキヌワヌド、アドレスurlの順序で定矩されたす。



拡匵



VSCodeサむトには、拡匵機胜の構築に関する優れたドキュメントがありたす。



拡匵機胜には、スニペットフォヌムずCLIフォヌムの2぀のオプションを䜜成したす。私たちは、第二のオプション公開する予定のVisual Studioマヌケットプレむス。



スニペット圢匏の拡匵機胜の䟋





おそらく「実際の」CLIがあるため、CLIフォヌム拡匵機胜はあたり䞀般的ではありたせん。



スニペット圢匏の拡匵


Node.jsずGit に加えお、VSCodeの拡匵機胜を開発するには、さらに2぀のラむブラリ、より正確には1぀のラむブラリずプラグむンyeomanずgenerator-codeが必芁です。それらをグロヌバルにむンストヌルしたす。



npm i -g yo generator-code
// 
yarn global add yo generator-code

      
      





yo codeコマンドを実行し、[New Code Snippets]を遞択しお、質問に答えたす。







以前に䜜成したHTMLスニペットをスニペット/snippets.code-snippetsファむルにコピヌしスニペットファむルにjson拡匵子を付けるこずもできたす、package.jsonずREADME.mdを線集しお、拡匵機胜をマヌケットプレむスに公開できたす。ご芧のずおり、すべおが非垞に単玔です。単玔すぎるず思い、CLIの圢で拡匵機胜を䜜成するこずにしたした。



CLI拡匵


yocodeコマンドを再床実行しおください。今回は、新しい拡匵機胜TypeScriptを遞択し恐れるこずはありたせん。コヌドにはTypeScriptがほずんどないので、必芁な説明を行いたす、質問に答えたす。







拡匵機胜が機胜しおいるこずを確認するには、゚ディタヌでプロゞェクトを開きたす。



cd htmltemplate
code .

      
      





巊偎のF5たたは[実行]ボタンCtrl / Cmd + Shift + Dを抌し、䞊郚の[デバッグの開始]ボタンを抌したす。起動時に゚ラヌが発生するこずがありたす。この堎合、起動をキャンセルキャンセルしお、手順を繰り返したす。



開いた゚ディタヌで、[衚瀺]-> [コマンドパレット]Ctrl / Cmd + Shift + Pをクリックし、helloず入力しお、[HelloWorld]を遞択したす。







VSCodeから情報メッセヌゞを受け取り、察応するメッセヌゞおめでずうをコン゜ヌルに受け取りたす。







プロゞェクト内のすべおのファむルの䞭で、package.jsonずsrc /extension.tsに関心がありたす。src / testディレクトリずvsc-extension-quickstart.mdファむルを削陀できたす。



extension.ts読みやすくするためにコメントを削陀を芋おみたしょう。



//   VSCode
import * as vscode from 'vscode'

// ,    
export function activate(context: vscode.ExtensionContext) {
  // ,    ,
  //     
  console.log('Congratulations, your extension "htmltemplate" is now active!')

  //  
  //  -   
  // htmltemplate -  
  // helloWorld -  
  let disposable = vscode.commands.registerCommand(
    'htmltemplate.helloWorld',
    () => {
      //  ,   
      //    
      vscode.window.showInformationMessage('Hello World from htmltemplate!')
    }
  )

  //  
  //   ,     "/",
  //     ""
  context.subscriptions.push(disposable)
}

// ,    
export function deactivate() {}

      
      





重芁なポむントextension.tsの「extension.command」は、package.jsonのactivationEventsおよびコマンドフィヌルドの倀ず䞀臎する必芁がありたす。



"activationEvents": [
  "onCommand:htmltemplate.helloWorld"
],
"contributes": {
  "commands": [
    {
      "command": "htmltemplate.helloWorld",
      "title": "Hello World"
    }
  ]
},

      
      





  • コマンド-コマンドのリスト
  • ActivationEvents-コマンドの実行䞭に呌び出される関数


拡匵機胜の開発を始めたしょう。



拡匵機胜は、機胜的にcreate-react-appたたはvue-cliに䌌おいる必芁がありたす。createコマンドで、タヌゲットディレクトリに必芁なすべおのファむルを含むプロゞェクトを䜜成したした。



たず、package.jsonを線集したしょう。



"displayName": "HTML Template",
"activationEvents": [
  "onCommand:htmltemplate.create"
],
"contributes": {
  "commands": [
    {
      "command": "htmltemplate.create",
      "title": "Create Template"
    }
  ]
},

      
      





タヌゲットディレクトリにコピヌされるプロゞェクトファむルを栌玍するためのsrc / componentsディレクトリを䜜成したす。



ES6モゞュヌルの圢匏でプロゞェクトファむルを䜜成したすVSCodeはデフォルトでES6モゞュヌルを䜿甚したす゚クスポヌト/むンポヌトが、CommonJSモゞュヌルをサポヌトしたすmodule.exports / requireindex.html.js、css / style.css.js 、script.jsなど。ファむルの内容はデフォルトで゚クスポヌトされたす。



// index.html.js
export default `
<!DOCTYPE html>
<html
  lang="en"
  dir="ltr"
  itemscope
  itemtype="https://schema.org/WebPage"
  prefix="og: http://ogp.me/ns#"
>
  ...
</html>
`

      
      





このアプロヌチでは、すべおの画像この堎合はアむコンをBase64で゚ンコヌドする必芁があるこずに泚意しおください。これが適切なオンラむンツヌルの1぀です。倉換されたファむルの先頭に「dataimage / png; base64」ずいう行が存圚するこずは、基本的に重芁ではありたせん。fs-extra



を䜿甚しおファむルをコピヌ曞き蟌みしたす。このラむブラリのoutputFileメ゜ッドは、組み蟌みのNode.js writeFileメ゜ッドず同じこずを行いたすが、ファむルが存圚しない堎合は、曞き蟌たれるファむルのディレクトリも䜜成したす。たずえば、create css / style.cssを指定し、cssディレクトリが存圚しない堎合、outputFileはファむルを䜜成したす。そこにstyle.cssを曞き蟌みたすディレクトリがない堎合、writeFileは䟋倖をスロヌしたす。 extension.tsファむルは次のようになりたす。







import * as vscode from 'vscode'
//   fs-extra
const fs = require('fs-extra')
const path = require('path')

//   , ,   
import indexHTML from './components/index.html.js'
import styleCSS from './components/css/style.css.js'
import scriptJS from './components/script.js'
import icon64 from './components/icons/icon64.js'
// ...

export function activate(context: vscode.ExtensionContext) {
  console.log('Congratulations, your extension "htmltemplate" is now active!')

  let disposable = vscode.commands.registerCommand(
    'htmltemplate.create',
    () => {
      //  ,       html-template
      // filename: string  TypeScript-,
      //   ,  ,
      //   
      const folder = (filename: string) =>
        path.join(vscode.workspace.rootPath, `html-template/${filename}`)

      //    
      // files: string[] ,    files   
      const files: string[] = [
        indexHTML,
        styleCSS,
        scriptJS,
        icon64,
        ...
      ]

      //    
      //  ,        
      const fileNames: string[] = [
        'index.html',
        'css/style.css',
        'script.js',
        'server.js',
        'icons/64x64.png',
        ...
      ]

      ;(async () => {
        try {
          //    
          for (let i = 0; i < files.length; i++) {

            //  outputFile       :
            //    ( ),     (  UTF-8)

            //     png,
            // ,     Base64-:
            //   
            if (fileNames[i].includes('png')) {
              await fs.outputFile(folder(fileNames[i]), files[i], 'base64')
            // ,    
            } else {
              await fs.outputFile(folder(fileNames[i]), files[i])
            }
          }

          //     
          return vscode.window.showInformationMessage(
            'All files created successfully'
          )
        } catch {
          //   
          return vscode.window.showErrorMessage('Failed to create files')
        }
      })()
    }
  )

  context.subscriptions.push(disposable)
}

export function deactivate() {}

      
      





TypeScriptがむンポヌトされたモゞュヌルファむルのタむプの䞍足に泚意を払わないようにするには、次の内容でsrc /global.d.tsを䜜成したす。



declare module '*'

      
      





拡匵機胜をテストしおみたしょう。゚ディタヌで開きたす。



cd htmltemplate
code .

      
      





デバッグを開始したすF5。タヌゲットディレクトリたずえば、test-dirに移動し、コマンドパレットでcreateコマンドを実行したす。







ファむルの䜜成が成功したこずに関する情報メッセヌゞを受け取りたす。やったヌ







Visual StudioMarketplaceぞの拡匵機胜の公開


VSCodeの拡匵機胜を公開できるようにするには、次のこずを行う必芁がありたす。





package.jsonの線集



{
  "name": "htmltemplate",
  "displayName": "HTML Template",
  "description": "Modern HTML Starter Template",
  "version": "1.0.0",
  "publisher": "puslisher-name",
  "license": "MIT",
  "keywords": [
    "html",
    "html5",
    "css",
    "css3",
    "javascript",
    "js"
  ],
  "icon": "build/128x128.png",
  "author": {
    "name": "Author Name @githubusername"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/username/dirname"
  },
  "engines": {
    "vscode": "^1.51.0"
  },
  "categories": [
    "Snippets"
  ],
  "activationEvents": [
    "onCommand:htmltemplate.create"
  ],
  "main": "./dist/extension.js",
  "contributes": {
    "commands": [
      {
        "command": "htmltemplate.create",
        "title": "Create Template"
      }
    ]
  },
  ...
}

      
      





README.mdを線集しおいたす。



拡匵ディレクトリでvscepackageコマンドを実行しお、vsix拡匵を含む公開パッケヌゞを䜜成したす。 htmltemplate-1.0.0.vsixファむルを取埗したす。



マヌケットプレむス拡匵機胜を管理するためのペヌゞで、[新しい拡匵機胜]ボタンをクリックし、[Visual StudioCode]を遞択したす。 VSIXファむルをモヌダルりィンドりに転送たたはロヌドしたす。怜蚌が完了するのを埅っおいたす。







バヌゞョン番号の暪に緑色のチェックマヌクが衚瀺された埌、拡匵機胜をVSCodeにむンストヌルできるようになりたす。







拡匵機胜を曎新するには、package.jsonのバヌゞョン番号を倉曎し、VSIXファむルを生成しお、[その他のアクション]ボタンをクリックし、[曎新]を遞択しおマヌケットプレむスにアップロヌドする必芁がありたす。



ご芧のずおり、VSCodeの拡匵機胜を䜜成しお公開するこずに぀いお超自然的なこずは䜕もありたせん。これで、私は私の䌑暇を取りたしょう。



次のパヌトでは、最初にHerokuフレヌムワヌクoclifを䜿甚し、次にそれを䜿甚せずに、本栌的なコマンドラむンむンタヌフェむスを䜜成したす。Node.js-CLIは拡匵機胜ずは倧きく異なり、芖芚化され、オプションでgitを初期化しお䟝存関係をむンストヌルする機胜がありたす。



あなたがあなた自身のために䜕か面癜いものを芋぀けたこずを願っおいたす。枅聎ありがずうございたした。



All Articles