VS Code 및 Node를 사용하여 스타일로 HTML 작성
이 기사에서는 Visual Studio Code 및 Node.js의 기능을 사용하여 까다로운 블로그 플랫폼을 극복하고 Markdown을 작성하는 사용자 지정 편집 도구를 구축하는 방법을 설명합니다.
이 기사의 세부 사항은 우리가 겪고 있던 문제에 맞게 조정되었지만, 여기에 관련된 전략은 Markdown을 사용하여 레거시 시스템에 대한 일부 콘텐츠를 만들거나 훨씬 더 흥미로운 다른 사용자 정의 편집기 워크플로를 만들려는 많은 작업에 적용할 수 있습니다. 예를 들어, 이메일에 포함할 HTML을 작성하려는 경우 사용할 수 있는 마크업에 대해 많은 제약이 있습니다.

문제점
Infragistics는 오랫동안 포럼과 블로깅을 제공해 왔으며, 콘텐츠의 대규모 백 라이브러리에 액세스 할 수 있도록 유지해야 할 때 자주 발생하는 것처럼 작동하지만 작업하기에 반드시 즐겁지는 않은 다소 오래된 블로깅 소프트웨어를 실행하고 있습니다. 시스템에 콘텐츠를 가져오기 위한 주요 벡터는 다음과 같습니다.
- 코드 스니펫 입력을 잘 지원하지 않는 버그가 있는 웹 기반 WYSIWYG 편집기로 작업하고 기존 콘텐츠를 잘못 왕복하여 다시 편집하면 콘텐츠가 예측할 수 없는 방식으로 변경됩니다.
- 버그가 있는 웹 기반 WYSIWYG 편집기의 버튼을 사용하여 리터럴 HTML 코드를 삽입하면 주입된 HTML을 때때로 버그가 있는 형태로 강제 변환하여 안전하지 않은 패턴을 방지할 수 있지만 일반적으로 작성자가 의도한 것처럼 전혀 보이지 않는 결과가 발생합니다.
- 어두운 마법을 부리고 모호한 단일 로그인 시스템과 싸우면서 Windows Live Writer (현재 Open Live Writer)를 웹 서비스 인터페이스에 연결하고 거기에서 콘텐츠를 주입하지만 블로그 엔진은 여전히 제출 된 HTML을 바람직하지 않은 방식으로 망쳐 놓았습니다.
실제로 콘텐츠를 시스템에 가져오는 어려움 외에도 Infragistics 블로그 콘텐츠가 코드 스니펫 사용에 중점을 둔다는 사실이 있습니다. 이것들은 이상적으로 보기 좋고 구문 강조 표시가 있어야 합니다.
Github Gist 같은 스니펫 저장 서비스를 사용한다면 이 부분이 쉽다고 생각할 수 있지만, 저희 문제는 블로그 소프트웨어가 게시물 콘텐츠에서 요소를 일부러 억제하고 제거iframe 한다는 점입니다. 이것은 엔진이 편집 시 게시물 내용과 댓글 내용을 구분하기에 준비가 부족해 보안 장치라고 생각하며, 댓글 작성자가 iframe을 삽입하는 것을 원하지 않을 것입니다!
안타깝게도 대부분의 괜찮은 외부 스니펫 소프트웨어는 스니펫iframe을 로드하거나 사용자 지정 자바스크립트가 필요하다고 생각합니다(우리 블로그 엔진에서는 이 역시 금기입니다).
한동안 우리는 사이트 단위에서 자바스크립트를 실행해 매우 정밀한 형식의 태그에pre 문법 강조를 적용했지만, 웹사이트 팀이 사이트를 대대적으로 수정할 때마다 이 자바스크립트가 계속 사라져서 이 자바스크립트에 의존하는 모든 문서가 갑자기 형편없어 보였습니다. 최근에 이 기능이 사라졌을 때, 저는 이 해결책을 고민하기 시작했습니다.
마지막으로, 독점 블로그 포털의 WYSIWYG 편집기에서 작업하면 라이브로 전환하기 전에 콘텐츠를 검토하고 반복할 수 있는 방법이 많지 않습니다. 이상적으로는 누군가 게시하기 전에 동료나 카피 에디터에게 블로그 게시물에 대한 검토를 요청할 수 있어야 합니다. 이에 가장 근접한 방법은 목록에 없는 초안 게시물을 게시하고 피드백을 요청하는 것이었습니다. 그러나 끌어오기 요청 워크플로를 사용하여 변경한 내용이 git에 저장된 markdown 파일과 같이 인라인으로 콘텐츠에 주석을 달고 주석을 달 수 있는 방법은 없었습니다.
이제 고맙게도 블로그 소프트웨어를 곧 훨씬 더 최신 엔진으로 업데이트할 예정이므로 이 문제는 제가 다루고 있는 단기적인 문제이지만 이 단기적인 솔루션은 만드는 것이 그리 어렵지 않았고 업데이트 후에도 계속 관련성이 있을 수 있으며 우리와 유사한 문제를 해결하기 위해 사용자 정의 편집 워크플로를 만드는 데 훌륭한 전략을 제공합니다. 많은 엔지니어가 콘텐츠 작성 및 반복에 대한 장벽으로 인해 블로그를 덜 하거나 전혀 하지 않을 것이며, 이러한 장벽을 낮추면 더 많은 콘텐츠를 장려할 수 있습니다.
계획
자, 극복해야 할 문제를 요약해 보겠습니다.
- 현재 시스템에 리터럴 HTML을 주입하는 것 외에는 아무 것도 수행하지 않는 것은 매우 어려우며, 시스템이 무시, 파괴 또는 잘못 표현하는 HTML 패턴이 많기 때문에 이 작업조차도 주의해서 수행해야 합니다.
- 블로깅 엔진의 WYSIWYG 편집기 또는 Open Live Writer로 작업하는 것은 특히 코드 스니펫으로 작업하거나 콘텐츠를 반복할 때 큰 고통입니다.
- 보기 좋고 일부 외부 JavasScript가 누락되었을 때 폭발하지 않는 코드 조각이 필요합니다.
- 콘텐츠에 대한 검토 워크플로를 가질 수 있는 몇 가지 방법이 필요합니다.
문제를 해결하기 위한 계획은 다음과 같습니다.
- VS Code는 무료이며 markdown 파일을 편집할 때 Markdown 미리보기를 나란히 제공합니다.
- Node.js와 Gulp를 사용하면 Markdown 파일이 저장될 때마다 HTML로 지속적으로 변환하는 백그라운드 작업을 시작할 수 있습니다.
- 꿀꺽 파이프라인의 일부로 임의의 JavaScript를 실행할 수 있기 때문에 생성된 HTML을 조작하기 위한 추가 작업을 수행하여 블로깅 소프트웨어가 정상적으로 수락하도록 할 수 있어야 합니다.
- 편집 환경이 VS Code에서 Markdown 파일을 반복하는 것이라면 해당 Markdown 파일을 git에 저장하고 표준 끌어오기 요청 검토 워크플로를 사용하여 게시물에 대한 검토 프로세스를 만들 수 있어야 합니다.
해결책
우선 Visual Studio Code와 Node.js 설치되어 있는지 확인해야 합니다. 이 작업이 이 워크플로우의 주요 작업물이 될 것입니다. 설치가 완료되면 마크다운 파일을 보관할 디렉터리를 만들어야 합니다. 예를 들어c:\Blogging, 해당 폴더를 가리키는 VS Code를 열어야 합니다.
먼저 디렉터리에 빈 파일을 생성package.json 하여 다음만 포함합니다:
{ }
이제 폴더의 컨텍스트에서 콘솔에서 많은 명령을 실행해야 하므로 다음을 통해 통합 터미널을 엽니다.
View => Integrated Terminal
다음으로 Markdown을 HTML로 변환하는 데 사용할 Node.js 패키지인 markdown-it을 전역적으로 설치해야 합니다.
npm install -g markdown-it
다음으로 gulp를 전역적으로, 로컬에 설치하고 마크다운 파일을 HTML로 변환하는 작업 흐름을 관리하는 데 도움이 되는 몇 가지 gulp 확장을 설치해야 합니다.
npm install -g gulp npm install gulp gulp-markdown-it --save
이 정도면 저장되는 디렉터리의 Markdown 파일을 지속적으로 HTML로 변환하는 스크립트gulpfile.js를 작성하고, VS Code 마법으로 이 과정을Ctrl + Shift + B 시작할 수 있을 것입니다.
먼저, 폴더 내에 테스트test.md Markdown 파일을 만들고 다음과 같은 내용을 넣을 것입니다:
## Introduction
This is an introduction.
This is another paragraph.
```cs
//this is a gated code block
public class TestClass
{
public void TestMethod()
{
}
}
```
Markdown 미리보기CTRL-K V를 열고 편집 중인 파일과 함께 미리보기를 볼 수 있습니다:

이제 변환 워크플로우를 설정하는 gulp 구성을 만들 수 있습니다. 디렉터리에 파일을gulpfile.js 만들고 다음 내용으로 채우세요:
var gulp = require('gulp');
var markdown = require('gulp-markdown-it');
var fs = require('fs');
gulp.task('markdown', function() {
return gulp.src(['**/*.md', '!node_modules/**'])
.pipe(markdown({
options: {
html: true
}
}))
.pipe(gulp.dest(function(f) {
return f.base;
}));
});
gulp.task('default', ['markdown'], function() {
gulp.watch(['**/*.md', '!node_modules/**'], ['markdown']);
});
해당 파일을 저장하면 gulp를 실행하고 결과를 볼 수 있어야 하므로 통합 터미널에서 다음을 실행합니다.
gulp

이로 인해 우리 디렉터리에 다음과 같은 내용의 파일이test.html 생성됩니다:
<h2>Introduction</h2>
<p>This is an introduction.</p>
<p>This is another paragraph.</p>
<pre><code class="language-cs">//this is a gated code block
public class TestClass
{
public void TestMethod()
{
}
}
</code></pre>
우리가 구성한 방식으로 gulp는 이 디렉토리(또는 하위 디렉토리)에 있는 Markdown 파일의 변경 사항을 계속 주시하고 그 중 변경 사항이 있으면 Markdown-it을 통해 이를 공급하여 Markdown 파일과 동일한 이름의 html 파일에 새 HTML 콘텐츠를 생성합니다. Markdown 파일을 변경하는 경우:
## Introduction
This is an introduction.
This is another paragraph.
```cs
//this is a gated code block
public class TestClass2
{
public void TestMethod2()
{
}
}
```
여기TestClass는 읽기TestClass2로 변경되었고,TestMethod 읽기TestMethod2로 변경되었습니다. 저장을 누르고 잠시 기다리면,test.html 이제 다음을 포함합니다:
<h2>Introduction</h2>
<p>This is an introduction.</p>
<p>This is another paragraph.</p>
<pre><code class="language-cs">//this is a gated code block
public class TestClass2
{
public void TestMethod2()
{
}
}
</code></pre>
이 점은 멋지지만, VS Code를 사용하기 때문에 시작할 때 gulp 명령어를 실행할 필요도 없을 수 있습니다. 프로젝트 디렉터리의 하위 폴더에tasks.json 파일을 만들고.vscode 다음 내용을 제공하는 것만 하면 됩니다:
{
"version": "2.0.0",
"tasks": [
{
"type": "gulp",
"task": "default",
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
이렇게 하면 버튼을 누르CTRL + SHIFT + B 면 백그라운드에서 gulp 명령어가 실행되기 시작합니다. 이렇게 해서 VS Code의 마크다운 에디터(정말 멋진 미리보기 창을 포함해서)와 Node.js, 마크다운 잇, 그리고 굴프를 결합해 멋진 HTML 에디터를 만들고 있습니다.
Ornery 블로깅 엔진 길들이기
이제 우리처럼 일부 괴상한 블로깅 엔진을 다루지 않는다면 위의 모든 것이 필요할 수 있습니다. 그러나 그렇다 하더라도이 나머지 부분은 흥미롭고 유용하다는 것을 알게 될 것입니다. 해결해야 할 블로그 엔진의 문제는 다음과 같습니다.
- 우리는 외부 JS 또는 CSS 스타일 시트가 없는 상태에서 코드 스니펫을 정적 스타일 html로 렌더링하는 것을 선호합니다.
- 우리 블로깅 엔진은 태그에 내장된
pre탭을 조작합니다(왜 그런지는 저도 잘 모르겠습니다). - 저희 블로깅 엔진은 태그 내
pre줄 바갛기를 왕복하지 못하고 자주 빠뜨리기 때문에, 줄 바꿔 줄꿈을 명시적인 줄바꿈 태그로 변환하는 것이 더 안전합니다. 그렇지 않으면 HTML을 다시 게시할 때 문제가 생깁니다. - 우리 블로깅 엔진은 태그 안
pre에서도 줄 앞의 여백을 제거하려 하므로, 이를 끊기지 않는 공백으로 변환하고 싶습니다 ( )
우선, 코드 스니펫을 강조하고 태그 내pre 문제의 HTML을 정제하는 작업을 다룰 것입니다. highlightjs라는 노드 패키지를 사용해 마크다운 내 게이팅된 코드 블로그를 구문 하이라이트 마크업으로 포맷할 예정입니다. 그럼 먼저 설치해 보겠습니다:
npm install highlightjs --save
설치가 완료되면 다음과 같이 수정gulpfile.js 할 수 있습니다:
var gulp = require('gulp');
var markdown = require('gulp-markdown-it');
//new
var hljs = require('highlightjs/highlight.pack.js');
var fs = require('fs');
//new
hljs.configure({
tabReplace: ' '
});
gulp.task('markdown', function() {
return gulp.src(['**/*.md', '!node_modules/**'])
.pipe(markdown({
options: {
html: true,
//new
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
var output = hljs.highlight(lang, str).value;
output = output.replace(/(?:\r\n|\r|\n)/g, '<br />');
output = output.replace(/^\s+/gm, function(m){ return m.replace(/\s/g, ' ');});
output = output.replace(/(\<br\s+\/\>)(\s+)/gm, function(m){ return m.replace(/\>(\s+)/g, function (n) { return n.replace(/\s/g, ' '); } ); });
return '<pre class="hljs"><code>' +
output +
'</code></pre>';
} catch (e) {}
}
return '';
}
}
}))
.pipe(gulp.dest(function(f) {
return f.base;
}));
});
gulp.task('default', ['markdown'], function() {
gulp.watch(['**/*.md', '!node_modules/**'], ['markdown']);
});
위에서 우리는 다음을 수행합니다.
- highlightjs 라이브러리를 사용할 수 있도록 문장을
require추가하세요. - 탭 문자 대신 4개의 줄 바꿈하지 않는 공백을 사용하도록 highlightjs 라이브러리를 구성합니다.
- markdown-it을 실행할 때 강조 표시 훅을 사용하여 펜싱된 코드 블록에 대해 구문 강조 표시를 수행하는 방법을 지정합니다. 이 경우 highlightjs를 호출하여 강조 표시를 수행합니다.
- 펜싱된 코드 블록을 변환하는 것 외에도 출력 콘텐츠에서 일련의 정규식 교체를 수행하여 블로깅 엔진에 문제가 있는 것으로 입증된 문자 패턴을 제거하고 동등하고 안전한 문자 시퀀스로 교체합니다.
이 시점에서 gulp 작업을 다시 시작해야 합니다.
F1 => Terminate Running Task
그리고 다시 작업을CTRL + SHIFT + B 시작하세요. 이 시점에서 test.html는 다음과 같이 읽을 것입니다:
<h2>Introduction</h2>
<p>This is an introduction.</p>
<p>This is another paragraph.</p>
<pre><code class="language-cs"><pre class="hljs"><code><span class="hljs-comment">//this is a gated code block</span><br /><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TestClass2</span><br />{<br /> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">TestMethod2</span>(<span class="hljs-params"></span>)<br /> </span>{<br /> <br /> }<br />}<br /></code></pre></code></pre>
사전 태그에서 모든 줄 바꿈이 제거되어 꽤 추악하지만 이제 블로깅 엔진에서 더 멋지게 재생됩니다.
이 작업을 완료하기 전에 해결하고자 하는 마지막 두 가지 문제가 있습니다. 먼저, 웹사이트/마케팅 팀의 요청에 따라 모든 링크가 새 탭에서 자동으로 열리기를 바랍니다. 둘째, 현재 결과 HTML은 출력 HTML이 코드 스니펫에 대해 실제로 색상이 지정될 수 있도록 CSS 스타일시트가 로드될 것으로 예상합니다. 브라우저에서 출력을 보면 다음과 같이 보일 것입니다.

앞서 언급했듯이 블로그 기사에 게시물당 CSS를 삽입할 수 없으므로 모든 구문 색상 지정을 HTML 인라인에 직접 굽는 것이 좋습니다.
다행히도, 이 두 가지 문제에 대해 간단히 사용할 수 있는 노드 패키지들이 있습니다. 먼저, 마크다운-잇 플러그인이라는 패키지markdown-it-link-target를 설치할 수 있는데, 이 플러그인은 링크가 새 탭에서 열리도록 렌더링되도록 만듭니다:
npm install markdown-it-link-target --save
다음으로 juice라는 노드 패키지를 호출하는 gulp용 플러그인을 설치합니다.
npm install gulp-juice --save
juice는 CSS 스타일 시트와 일부 HTML을 가져온 다음 CSS 스타일을 HTML 인라인으로 굽어 외부 CSS가 더 이상 필요하지 않도록하는 깔끔한 라이브러리입니다. 이 조각들을 연결하려면 gulpfile을 다시 업데이트한 다음 작업을 다시 시작해야 합니다.
var gulp = require('gulp');
var markdown = require('gulp-markdown-it');
var hljs = require('highlightjs/highlight.pack.js');
//new
var juice = require('gulp-juice');
var fs = require('fs');
//new
var codeCss = fs.readFileSync("./node_modules/highlightjs/styles/atom-one-dark.css", "utf-8");
hljs.configure({
tabReplace: ' '
});
gulp.task('markdown', function() {
return gulp.src(['**/*.md', '!node_modules/**'])
.pipe(markdown({
//new
plugins: ["markdown-it-link-target"],
options: {
html: true,
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
var output = hljs.highlight(lang, str).value;
output = output.replace(/(?:\r\n|\r|\n)/g, '<br />');
output = output.replace(/^\s+/gm, function(m){ return m.replace(/\s/g, ' ');});
output = output.replace(/(\<br\s+\/\>)(\s+)/gm, function(m){ return m.replace(/\>(\s+)/g, function (n) { return n.replace(/\s/g, ' '); } ); });
return '<pre class="hljs"><code>' +
output +
'</code></pre>';
} catch (e) {}
}
return '';
}
}
}))
//new
.pipe(juice({ extraCss: codeCss }))
.pipe(gulp.dest(function(f) {
return f.base;
}));
});
gulp.task('default', ['markdown'], function() {
gulp.watch(['**/*.md', '!node_modules/**'], ['markdown']);
});
이 변경으로 이제 다음과test.html 같이 보여야 합니다:
<h2>Introduction</h2>
<p>This is an introduction.</p>
<p>This is another paragraph.</p>
<pre><code class="language-cs"><pre class="hljs" style="background: #282c34; color: #abb2bf; display: block; overflow-x: auto; padding: 0.5em;"><code><span class="hljs-comment" style="color: #5c6370; font-style: italic;">//this is a gated code block</span><br><span class="hljs-keyword" style="color: #c678dd;">public</span> <span class="hljs-keyword" style="color: #c678dd;">class</span> <span class="hljs-title" style="color: #61aeee;">TestClass2</span><br>{<br> <span class="hljs-function"><span class="hljs-keyword" style="color: #c678dd;">public</span> <span class="hljs-keyword" style="color: #c678dd;">void</span> <span class="hljs-title" style="color: #61aeee;">TestMethod2</span>(<span class="hljs-params"></span>)<br> </span>{<br> <br> }<br>}<br></code></pre></code></pre>
앞의 줄에서 이 줄은 다음과 같습니다.
var codeCss = fs.readFileSync("./node_modules/highlightjs/styles/atom-one-dark.css", "utf-8");
highlightjs와 함께 제공되는 CSS 파일 중 하나를 로드하고 HTML과 함께 굽습니다.
이제 이것은 엉뚱한 블로깅 엔진을 포함하여 HTML을 지원하는 거의 모든 것에 원시 HTML로 간단히 붙여 넣을 수 있습니다!
이 시점에서 브라우저에로드하면 다음과 같이 보일 것입니다.

이것이 흥미롭거나 유용하기를 바랍니다!