Rev. 2.73

개발자들이 정의한 각종 데이터를 최종 결과물인 HTML 문서를 통해서 출력하지만 이를 다시 데이터형으로 돌리기에는 많은 어려움이 있기 때문에 HTML 문서에서 데이터를 구분해 낼 수 있는 방법으로 마이크로데이터이나 마이크로포맷 또는 RDFa를 이용할 수 있습니다. RDFa는 XHTML에나 잘 어울릴 법한 모양새이고 사용법이 다소 까다롭다는 점에서 개인적으로는 마이크로포맷이나 마이크로데이터를 선호합니다. 마이크로포맷은 별도의 네임스페이스 선언을 필요로하지 않고 class와 rel 속성만을 이용하여 구조화된 데이터를 표현할 수 있지만, 단계가 있거나 관계가 있는 데이터를 구조화하기에는 부족한 면이 있습니다. 마이크로데이터는 RDFa와 마이크로포맷의 중간쯤으로 볼 수 있습니다. 자세한 사용 방법은 구글이 문서(microdata, microformats, RDFa)를 잘 만들어 뒀습니다.

이 얘기는 수년 전부터 거론되었지만 웹사이트 소유주에게 돌아가는 이렇다 할 가치가 없었기 때문에 지들끼리 말만 많았던 HTML5 스팩이죠. 최근 구글은 이 구조화된 데이터를 이용하여 저자나 인물을 표시하거나 제품이나 장소 등의 평점 및 리뷰, 앨범의 트랙 정보 이벤트 등을 검색결과에 노출하고 있으며, 이것을 리치 스니펫이라 부르고 있습니다. 구글은 리치 스니펫을 제공하는 방법으로는 마이크로데이터를 권장하고 있으며 이는 데이터가 어떤 종류인지를 정의하는 스키마를 필요로합니다. 대표적으로 data-vocabulary.org또는 schema.org에서 제공하는 데이터 스키마를 선언하는데 이를 잘 이용하면 관계형 데이터 구조화가 가능해 집니다.

구글은 웹마스터 도구를 통해 구조화된 데이터 테스팅 도구를 제공합니다. 다음은 schema.org의 데이터 스키마를 기반으로 이 블로그의 데이터를 구조화하고 테스팅 도구를 통해 얻은 결과입니다. 제법 쓸만한 데이터가 만들어 지더라고요. 조금 더 발전하면 ATOM이나 RSS를 별도로 제공하는게 무의미해질지도 모르겠네요.

Item

  • type: http://schema.org/blog
  • property:
    • url: Firejune
    • name: Firejune
    • description: The Web is still changing.
    • version: 2.19
    • blogpost: Item 1
    • author: Item 2

Item 1

Item 3

  • type: http://schema.org/comment
  • property:
    • datecreated: 2012-12-20T08:55:50+09:00
    • image: http://a0.twimg.com/profile_images/2399594250/8dp14wildkk8xbt8ownl_normal.png
    • url: beyonditblog
    • name: beyonditblog
    • text: Node.JS용 Scribd 모듈 배포: 역시나, 기업 요구사항은 파일 교환 보다는 문서 관리쪽으로 많이 치우쳐져 있더군요. 그래서 문서관련 기능을 강화하기...

Item 4

  • type: http://schema.org/comment
  • property:
    • datecreated: 2012-12-20T09:24:06+09:00
    • image: http://a0.twimg.com/profile_images/1123405595/IT_NEWS_normal.jpg
    • url: All_IT_News
    • name: All_IT_News
    • text: text: [경준호] Node.JS용 Scribd 모듈 배포: 역시나, 기업 요구사항은 파일 교환 보다는 문서 관리쪽으로 많이 치우쳐져 있더군요. 그래서 문서관련 기능을...

Item 5

  • type: http://schema.org/comment
  • property:
    • datecreated: 2012-12-22T00:50:28+09:00
    • image: http://a0.twimg.com/profile_images/2514809179/stcr8k585g4tkcch9pgw_normal.jpeg
    • url: nanhapark
    • name: nanhapark
    • text: Node.JS용 Scribd 모듈 배포 http://t.co/qpzDlro0 #nodeqa

Item 6

  • type: http://schema.org/comment
  • property:
    • datecreated: 2012-12-22T01:20:16+09:00
    • image: http://a0.twimg.com/profile_images/1032276925/imazine_normal.jpg
    • url: iMaZiNe80
    • name: iMaZiNe80
    • text: RT @nanhapark: Node.JS용 Scribd 모듈 배포 http://t.co/qpzDlro0 #nodeqa

Item 2

  • type: http://schema.org/person
  • property:
    • image: https://firejune.com/attach/image/272778.jpeg
    • name: Joon Kyoung
    • jobtitle: web front-end development
    • worksfor: Spark & Associates Corp
    • url: @firejune
    • url: Blog
    • url: More information

Comments

역시나, 기업 요구사항은 파일 교환보다는 문서 관리 쪽으로 많이 치우쳐져 있더군요. 그래서 문서관련 기능을 강화하기 위해 매시업할 수 있는 서비스들을 찾아보던 중 Scribd라는 서비스를 알게 되었습니다. 이 서비스는 업로드한 문서를 HTML5(또는 플래시)에서 출력할 수 있도록 컨버전해주는 서비스였습니다. 변환된 문서는 원본 문서와 다른 점을 찾아보기 어려울 정도로 품질이 좋더군요. 그리고 자신들이 가진 기술을 공유에 목적을 두고 마음껏 사용해 주기를 바라는 착한 회사였습니다.

Scribd의 API는 문서를 웹페이지에 임베드하기 위한 자바스크립트 API와 문서를 등록하거나 메타데이터를 조회하거나 검색 등을 할 수 있는 플랫폼 API로 나뉩니다. 플랫폼 API에는 Ruby, Java, PHP, Python 등의 라이브러리가 있었지만 아쉽게도 Node.JS용 라이브러리만 쏙 빠져있어서 래핑 모듈을 만들고 배포합니다. 아래는 GitHub에 공개한 scribd 모듈의 API 문서입니다.

Scribd Platform API binding for Node.JS

Installing:

$ npm install scribd

Usage:

var Scribd = require('scribd');

var key = "ENTER-YOUR-API-KEY-HERE"
  , secret = "ENTER-YOUR-API-SECRET-HERE"; 

var scribd = new Scribd(key, secret);

// or (>= 0.1.5)

var scribd = new Scribd({
    apikey: key
  , secret: secret
});


/**
 * docs.upload
 */

scribd.upload(function(err, res) {
  console.log("\n scribd.upload", err, res);
}, "./my.docx", "doc", "private");

// or (>= 0.1.5)

scribd.upload({
    file: "./my.docx"
  , docType: "doc"
  , access: "private"
}, function(err, res) {
  console.log("\n scribd.upload", err, res);
});

Methods:

/**
 * Docs Method
 */

// docs.upload (callback, file, [docType], [access], [revId])
scribd.upload(function(err, res) {
  console.log('\n scribd.upload', err, res);
}, './document.path');

// docs.uploadFromUrl (callback, url, [docType], [access], [revId])
scribd.uploadFromUrl(function(err, res) {
  console.log('\n scribd.uploadFromUrl', err, res);
}, 'url');

// docs.getList (callback)
scribd.getList(function(err, res) {
  console.log('\n scribd.getList', err, res);
});

// docs.getConversionStatus (callback, docId)
scribd.getConversionStatus(function(err, res) {
  console.log('\n scribd.getConversionStatus', err, res);
}, 'docId');

// docs.getSettings (callback, docId)
scribd.getSettings(function(err, res) {
  console.log('\n scribd.getSettings', err, res);
}, 'docId');

// docs.changeSettings (callback, docId, [title], [description], [access], [license], [showAds], [tags])
scribd.changeSettings(function(err, res) {
  console.log('\n scribd.changeSettings', err, res);
}, 'docId', 'title');

// docs.getDownloadUrl (callback, docId)
scribd.getDownloadUrl(function(err, res) {
  console.log('\n scribd.getDownloadUrl', err, res);
}, 'docId');

// docs.getStats (callback, docId)
scribd.getStats(function(err, res) {
  console.log('\n scribd.getStats', err, res);
}, 'docId');

// docs.delete (callback, docId)
scribd.delete(function(err, res) {
  console.log('\n scribd.remove', err, res);
}, 'docId');

// docs.search (callback, query, [numResults], [numStart], [scope])
scribd.search(function(err, res) {
  console.log('\n scribd.search', err, res);
}, 'Node.JS', 1);

// docs.getCategories (callback, docId)
scribd.getCategories(function(err, res) {
  console.log('\n scribd.getCategories', err, res);
}, 'docId');

// docs.featured (callback, [limit], [offset], [scope])
scribd.featured(function(err, res) {
  console.log('\n scribd.featured', err, res);
});

// docs.browse (callback, [limit], [offset], [categoryId], [sort])
scribd.browse(function(err, res) {
  console.log('\n scribd.browse', err, res);
});

// docs.uploadThumb (callback, file, docId)
scribd.uploadThumb(function(err, res) {
  console.log('\n scribd.uploadThumb', err, res);
}, 'thumbnail.path', 'docId');


/**
 * Thumbnail Method
 */

// thumbnail.get (callback, docId, [width], [height])
scribd.getThumbnail(function(err, res) {
  console.log('\n scribd.getThumbnail', err, res);
}, 'docId', 256);


/**
 * User Method
 */

// user.login (callback, username, password)
scribd.login(function(err, res) {
  console.log('\n scribd.login', err, res);
}, 'username', 'password');

// user.signup (callback, username, password, email, [name])
scribd.signup(function(err, res) {
  console.log('\n scribd.signup', err, res);
}, 'username', 'password', 'email', 'name');

// user.getAutoSigninUrl (callback, [nextUrl])
scribd.getAutoSigninUrl(function(err, res) {
  console.log('\n scribd.getAutoSigninUrl', err, res);
}, '/');

Have fun!

License

MIT <3

Comments

CodeMirror는 웹 브라우저에서 코드 편집 기능을 제공할 수 있게 하는 자바스크립트 컴포넌트입니다. 자바스크립트, CSS, HTML은 물론 C, Java, PHP, Python, Ruby 등 50여 종의 언어 모드(Mode)를 지원하며, 문법 강조, 단축키, 자동포맷, 코드 폴딩, 테마, 검색 및 바꾸기 등의 유틸리티를 제공합니다. JSBin, Google Apps Script, Zen Coding등의 사이트에서 CodeMirror를 이용하여 코드 편집 기능을 제공하고 있습니다. JSBin을 포크 해서 고쳐 사용 중인 FireJSBin(코드네임)의 라이브러리를 업데이트하려다가 CodeMirror 3의 정식 버전이 최근에 릴리즈되었다는 사실을 알게 되었습니다. 그래서 버전 2.x에 비해 어떤 점들이 달라지고 어떻게 업그레이드하는지 살펴보도록 하겠습니다.

CodeMirror 버전 3은 2.x의 API에서 크게 벗어나지 않았습니다. 단순한 방법으로 CodeMirror를 이용한 사이트는 별다른 문제 없이 업그레이드할 수 있습니다. 애석하게도 버전 3부터는 인터넷 익스플로러 7을 완전히 지원하는 것을 포기합니다. IE7을 지원하는 코드들이 효율성을 떨어트리기 때문일까요? 아무튼, 그렇습니다.

DOM structure

편집기 내부에 사용되는 새로운 스크롤링 모델을 구현하기 위해 꽤 많은 DOM 구조가 변경되었습니다. 그래서 codemirror.css를 변경해서 사용하는 경우에는 문제를 일으킬 가능성이 큽니다. 편집기의 높이를 처리하는 요소가 스크롤러 요소(CSS class CodeMirror-scroll)에서 래퍼(Wrapper) 요소(CSS class CodeMirror)로 변경되었습니다. 그 외 다른 요소들이 이동되거나 제거되었고 추가되었습니다. 만약 편집기 내부의 DOM 요소를 제어하는 코드를 작성했다면 버전 3에서는 그 코드들을 다시 테스트해야 할 것입니다. CodeMirror 메뉴얼의 스타일링 섹션에서 더 많은 정보를 얻을 수 있습니다.

Gutter model

CodeMirror 2.x에서는 싱글 거터(Gutter, 라인 넘버가 출력되는 영역)만 제공되어 라인을 마킹하거나 할 때 좁은 공간에 줄 번호를 비롯한 추가적인 정보가 공존해야 했었지만, 버전 3부터는 거터를 클래스네임의 배열로 지정함으로써 복수로 사용할 수 있게 되었습니다. setGutterMarker, clearGutter 등의 추가적인 메서드를 이용하여 거터단위 마커를 추가 및 제거할 수 있고, HTML 스니펫이 아닌 DOM 노드로 지정됩니다.

수평으로 스크롤할 때 거터가 들쭉날쭉하는 문제가 사라졌으며, fixedGutter 옵션은 삭제되었습니다.

<style>
  /* Define a gutter style */
  .note-gutter { width: 3em; background: cyan; }
</style>
<script>
  // Create an instance with two gutters -- line numbers and notes
  var cm = new CodeMirror(document.body, {
    gutters: ["note-gutter", "CodeMirror-linenumbers"],
    lineNumbers: true
  });
  // Add a note to line 0
  cm.setGutterMarker(0, "note-gutter", document.createTextNode("hi"));
</script>

Event handling

onXYZ 옵션이 대부분 삭제되었습니다. 같은 효과로 이벤트 유형을 식별하는 문자열에서 입수할 수 있습니다. 여러 개의 핸들러를 하나의 이벤트에 할당합니다. 이러한 방식으로 라인 핸들러는 더 쉽게 이벤트를 받습니다. onKeyEventonDragEvent 옵션은 이벤트 핸들러를 후크하는 방식으로 작동하며 이전과 마찬가지로 사용할 수 있습니다.

cm.on("change", function(cm, change) {
  console.log("something changed! (" + change.origin + ")");
});

markText method arguments

markText 메서드는 이제 CSS 클래스명을 인자로 받지 않습니다. 이것은 선택 옵션이며, 옵션 개체를 통하여 전달할 수 있습니다.

// Style first ten lines, and forbid the cursor from entering them
cm.markText({line: 0, ch: 0}, {line: 10, ch: 0}, {
  className: "magic-text",
  inclusiveLeft: true,
  atomic: true
});

Line folding

라인을 숨기는 인터페이스가 제거되었습니다. markText를 이용하여 지금보다 더 유연하고 강력한 방법으로 동일한 작업을 수행하는 데 사용할 수 있습니다. 폴딩 스크립트는 새로운 인터페이스를 사용되도록 견고하게 업데이트되었습니다.

// Fold a range, replacing it with the text "??"
var range = cm.markText({line: 4, ch: 2}, {line: 8, ch: 1}, {
  replacedWith: document.createTextNode("??"),
  // Auto-unfold when cursor moves into the range
  clearOnEnter: true
});
// Get notified when auto-unfolding
CodeMirror.on(range, "clear", function() {
  console.log("boom");
});

Line CSS classes

setLineClass 메서드는 addLineClassremoveLineClass으로 대체되었습니다.

var marked = cm.addLineClass(10, "background", "highlighted-line");
setTimeout(function() {
  cm.removeLineClass(marked, "background", "highlighted-line");
});

Position Properties

모든 포지션 메서드는 화면에 표시하는 위치 개체를 반환합니다. {left, top, bottom, right} 속성을 항상 사용할 수 있으며, 버전 2.x에서 사용하던 {x, y, yBot} 속성을 사용하고 있다면 수정해야 합니다. 포지션 속성을 반환하는 메서드는 cursorCoords, charCoords, coordsChar 그리고 getScrollInfo 입니다.

Bracket matching no longer in core

matchBrackets 옵션은 이제 코어 에디터에 정의되지 않으며 lib/util/matchbrackets.js를 로드합니다.

Mode management

정의된 모드(Mode)의 목록을 반환하던 CodeMirror.listModesCodeMirror.listMIMEs 함수는 이제 없어졌습니다. 대신 CodeMirror.modesCodeMirror.mimeModes로 간단하게 확인할 수 있습니다.

New features

버전 3으로 업그레이드하면 다음과 같은 이점이 있습니다.

  • 양 방향(Bi-directional) 텍스트 지원, 아랍어 또는 히브리어 텍스트를 편집할 수 있습니다.
  • 임의의 행 높이 처리, 에디터 내부에서 높이가 서로다른 글꼴이 사용되는 경우 이제 우아하게 처리합니다.
  • 인라인-위젯 지원, 이 데모문서를 참고하세요.
  • CodeMirror.defineOption으로 사용자 정의 옵션을 지정할 수 있습니다.

이상으로 CodeMirror 버전 3으로의 업그래이드 방법에 대하여 알아보았습니다. 스크롤이 수평으로 이동할때 거터가 들락날락하는 현상이 수정된 거 빼고는 그리 업그레이드의 필요성을 못느끼겠네요. 아랍어를 다룰것도 아니고; 이 기존 2.x 버전은 버그를 수정하는 수준으로 업데이트가 이루어 진다고 하니, 너무 성급하게 3으로 갈아탈 필요는 없어 보입니다.

Comments