본문 바로가기
Tips

즐겨찾기 버튼으로 만드는 옵시디언 웹 클리퍼(Obsidian Web Clipper)

by Obsidianary 2022. 3. 31.

즐겨찾기 버튼으로 만드는 옵시디언 웹 클리퍼(Obsidian Web Clipper)

 

 

아직까지 공식적으로 웹 클리퍼가 없는 상황입니다. 그래서 많은 분들이 URL만 복사하거나 내용을 복사 붙여넣기하고 계실지도 모르겠습니다. 하지만 즐겨찾기에 추가 해서 쉽게 버튼 클릭만으로 스크랩을 할 수 있습니다. 옵시디언 커뮤니티 내에서 Minimal Theme 개발로 유명한 Kepano님이 개발한 북마크 방식의 옵시디언 웹 클리퍼입니다. 먼저 1분 30초 사용 관련 영상을 보시면 아마 깜짝 놀라실 겁니다.

Obsidian Web Clipper: How to capture web pages in one click with this bookmarklet - YouTube

Obsidian Web Clipper: How to capture web pages in one click with this bookmarklet - Youtube

 

자주 사용하는 브라우저에서 즐겨찾기를 만들고 URL에 아래 내용을 복사 붙여넣기하면 끝입니다. 즐겨찾기 버튼을 누르게 되면 자바스크립트가 동작하는 원리입니다. 저는 사파리, 엣지, 크롬, 네이버 웨일 등 다양한 곳에서 해봤는데 모두 잘 동작했습니다.

javascript:(function()%7Bjavascript%3A%20Promise.all(%5Bimport('https%3A%2F%2Funpkg.com%2Fturndown%406.0.0%3Fmodule')%2C%20import('https%3A%2F%2Funpkg.com%2F%40tehshrike%2Freadability%400.2.0')%2C%20%5D).then(async%20(%5B%7B%0A%20%20%20%20default%3A%20Turndown%0A%7D%2C%20%7B%0A%20%20%20%20default%3A%20Readability%0A%7D%5D)%20%3D%3E%20%7B%0A%0A%20%20%2F*%20Optional%20vault%20name%20*%2F%0A%20%20const%20vault%20%3D%20%22%22%3B%0A%0A%20%20%2F*%20Optional%20folder%20name%20such%20as%20%22Clippings%2F%22%20*%2F%0A%20%20const%20folder%20%3D%20%22%22%3B%0A%0A%20%20%2F*%20Optional%20tags%20%20*%2F%0A%20%20const%20tags%20%3D%20%22%23clippings%22%3B%0A%0A%20%20function%20getSelectionHtml()%20%7B%0A%20%20%20%20var%20html%20%3D%20%22%22%3B%0A%20%20%20%20if%20(typeof%20window.getSelection%20!%3D%20%22undefined%22)%20%7B%0A%20%20%20%20%20%20%20%20var%20sel%20%3D%20window.getSelection()%3B%0A%20%20%20%20%20%20%20%20if%20(sel.rangeCount)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20container%20%3D%20document.createElement(%22div%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20(var%20i%20%3D%200%2C%20len%20%3D%20sel.rangeCount%3B%20i%20%3C%20len%3B%20%2B%2Bi)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20container.appendChild(sel.getRangeAt(i).cloneContents())%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20html%20%3D%20container.innerHTML%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%20else%20if%20(typeof%20document.selection%20!%3D%20%22undefined%22)%20%7B%0A%20%20%20%20%20%20%20%20if%20(document.selection.type%20%3D%3D%20%22Text%22)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20html%20%3D%20document.selection.createRange().htmlText%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20return%20html%3B%0A%20%20%7D%0A%0A%20%20const%20selection%20%3D%20getSelectionHtml()%3B%0A%0A%20%20const%20%7B%0A%20%20%20%20%20%20title%2C%0A%20%20%20%20%20%20byline%2C%0A%20%20%20%20%20%20content%0A%20%20%7D%20%3D%20new%20Readability(document.cloneNode(true)).parse()%3B%0A%0A%20%20function%20getFileName(fileName)%20%7B%0A%20%20%20%20var%20userAgent%20%3D%20window.navigator.userAgent%2C%0A%20%20%20%20%20%20%20%20platform%20%3D%20window.navigator.platform%2C%0A%20%20%20%20%20%20%20%20windowsPlatforms%20%3D%20%5B'Win32'%2C%20'Win64'%2C%20'Windows'%2C%20'WinCE'%5D%3B%0A%0A%20%20%20%20if%20(windowsPlatforms.indexOf(platform)%20!%3D%3D%20-1)%20%7B%0A%20%20%20%20%20%20fileName%20%3D%20fileName.replace('%3A'%2C%20'').replace(%2F%5B%2F%5C%5C%3F%25*%7C%22%3C%3E%5D%2Fg%2C%20'-')%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20fileName%20%3D%20fileName.replace('%3A'%2C%20'').replace(%2F%5C%2F%2Fg%2C%20'-').replace(%2F%5C%5C%2Fg%2C%20'-')%3B%0A%20%20%20%20%7D%0A%20%20%20%20return%20fileName%3B%0A%20%20%7D%0A%20%20const%20fileName%20%3D%20getFileName(title)%3B%0A%0A%20%20if%20(selection)%20%7B%0A%20%20%20%20%20%20var%20markdownify%20%3D%20selection%3B%0A%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20var%20markdownify%20%3D%20content%3B%0A%20%20%7D%0A%0A%20%20if%20(vault)%20%7B%0A%20%20%20%20%20%20var%20vaultName%20%3D%20'%26vault%3D'%20%2B%20encodeURIComponent(%60%24%7Bvault%7D%60)%3B%0A%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20var%20vaultName%20%3D%20''%3B%0A%20%20%7D%0A%0A%20%20const%20markdownBody%20%3D%20new%20Turndown(%7B%0A%20%20%20%20%20%20headingStyle%3A%20'atx'%2C%0A%20%20%20%20%20%20hr%3A%20'---'%2C%0A%20%20%20%20%20%20bulletListMarker%3A%20'-'%2C%0A%20%20%20%20%20%20codeBlockStyle%3A%20'fenced'%2C%0A%20%20%20%20%20%20emDelimiter%3A%20'*'%2C%0A%20%20%7D).turndown(markdownify)%3B%0A%0A%20%20var%20date%20%3D%20new%20Date()%3B%0A%0A%20%20function%20convertDate(date)%20%7B%0A%20%20%20%20var%20yyyy%20%3D%20date.getFullYear().toString()%3B%0A%20%20%20%20var%20mm%20%3D%20(date.getMonth()%2B1).toString()%3B%0A%20%20%20%20var%20dd%20%20%3D%20date.getDate().toString()%3B%0A%20%20%20%20var%20mmChars%20%3D%20mm.split('')%3B%0A%20%20%20%20var%20ddChars%20%3D%20dd.split('')%3B%0A%20%20%20%20return%20yyyy%20%2B%20'-'%20%2B%20(mmChars%5B1%5D%3Fmm%3A%220%22%2BmmChars%5B0%5D)%20%2B%20'-'%20%2B%20(ddChars%5B1%5D%3Fdd%3A%220%22%2BddChars%5B0%5D)%3B%0A%20%20%7D%0A%0A%20%20const%20today%20%3D%20convertDate(date)%3B%0A%0A%20%20const%20fileContent%20%3D%20%0A%20%20%20%20%20%20%22author%3A%3A%20%22%20%2B%20byline%20%2B%20%22%5Cn%22%0A%20%20%20%20%20%20%2B%20%22source%3A%3A%20%5B%22%20%2B%20title%20%2B%20%22%5D(%22%20%2B%20document.URL%20%2B%20%22)%5Cn%22%0A%20%20%20%20%20%20%2B%20%22clipped%3A%3A%20%5B%5B%22%20%2B%20today%20%2B%20%22%5D%5D%5Cn%22%0A%20%20%20%20%20%20%2B%20%22published%3A%3A%20%5Cn%5Cn%22%20%0A%20%20%20%20%20%20%2B%20tags%20%2B%20%22%5Cn%5Cn%22%0A%20%20%20%20%20%20%2B%20markdownBody%20%3B%0A%20%20%0A%20%20document.location.href%20%3D%20%22obsidian%3A%2F%2Fnew%3F%22%0A%20%20%20%20%2B%20%22file%3D%22%20%2B%20encodeURIComponent(folder%20%2B%20fileName)%0A%20%20%20%20%2B%20%22%26content%3D%22%20%2B%20encodeURIComponent(fileContent)%0A%20%20%20%20%2B%20vaultName%20%3B%0A%7D)%7D)()%3B

 

커스터마이징

위에서 첨부한 URL로 하게되면 원하는 포맷이 나오지 않을 것입니다. #clipping이라는 원치 않는 태그도 생길 것이고 영어로 되어있기도 합니다. 다행히도 제작자는 커스터마이징 하는 방법도 알려주었습니다.
Obsidian Web Clipper Bookmarklet to save articles and pages from the web (for Safari, Chrome, Firefox, and mobile browsers) · GitHub

 

위의 URL은 “Bookmarklet Maker”라는 녀석을 통해서 자바스크립트 코드를 축약한 형태입니다. 그래서 커스터마이징 하기 위해서는 우리가 원본 자바스크립트 소스코드를 변경한 후에 축약을 해 새로운 즐겨찾기용 URL을 만들면 됩니다!

Bookmarklet Maker

 

커스터마이징 할 수 있는 부분이 있습니다.
첫째, 어떤 보관함에 할 것인지
둘째, 어떤 폴더에 넣을 것인지
셋째, 어떤 태그를 넣을 것인지
넷째, 노트에는 어떤 내용이 들어갈 것인지

 


위 사진은 초기 버전입니다. 저는 아래와 같이 제가 자주 사용하는 템플릿 형태로 변경했습니다.

javascript: Promise.all([import('https://unpkg.com/turndown@6.0.0?module'), import('https://unpkg.com/@tehshrike/readability@0.2.0'), ]).then(async ([{
    default: Turndown
}, {
    default: Readability
}]) => {

  /* Optional vault name */
  const vault = "ConnectingDots";

  /* Optional folder name such as "Clippings/" */
  const folder = "Inbox/";

  /* Optional tags  */
  const tags = "";

  function getSelectionHtml() {
    var html = "";
    if (typeof window.getSelection != "undefined") {
        var sel = window.getSelection();
        if (sel.rangeCount) {
            var container = document.createElement("div");
            for (var i = 0, len = sel.rangeCount; i < len; ++i) {
                container.appendChild(sel.getRangeAt(i).cloneContents());
            }
            html = container.innerHTML;
        }
    } else if (typeof document.selection != "undefined") {
        if (document.selection.type == "Text") {
            html = document.selection.createRange().htmlText;
        }
    }
    return html;
  }

  const selection = getSelectionHtml();

  const {
      title,
      byline,
      content
  } = new Readability(document.cloneNode(true)).parse();

  function getFileName(fileName) {
    var userAgent = window.navigator.userAgent,
        platform = window.navigator.platform,
        windowsPlatforms = ['Win32', 'Win64', 'Windows', 'WinCE'];

    if (windowsPlatforms.indexOf(platform) !== -1) {
      fileName = fileName.replace(':', '').replace(/[/\\?%*|"<>]/g, '-');
    } else {
      fileName = fileName.replace(':', '').replace(/\//g, '-').replace(/\\/g, '-');
    }
    return fileName;
  }
  const fileName = getFileName(title);

  if (selection) {
      var markdownify = selection;
  } else {
      var markdownify = content;
  }

  if (vault) {
      var vaultName = '&vault=' + encodeURIComponent(`${vault}`);
  } else {
      var vaultName = '';
  }

  const markdownBody = new Turndown({
      headingStyle: 'atx',
      hr: '---',
      bulletListMarker: '-',
      codeBlockStyle: 'fenced',
      emDelimiter: '*',
  }).turndown(markdownify);

  var date = new Date();

  function convertDate(date) {
    var yyyy = date.getFullYear().toString();
    var mm = (date.getMonth()+1).toString();
    var dd  = date.getDate().toString();
    var mmChars = mm.split('');
    var ddChars = dd.split('');
    return yyyy + '-' + (mmChars[1]?mm:"0"+mmChars[0]) + '-' + (ddChars[1]?dd:"0"+ddChars[0]);
  }

  const today = convertDate(date);

  const fileContent = 
      "---\n" 
      + "created:" + today + "\n"
      + "aliases: [] \n"
      + "---\n"
      + "종류:: #📥/📰 \n"
      + "상태:: #🌱 \n"
      + "출처:: [" + title + "](" + document.URL + ")\n"
      + "저자:: " + byline + "\n"
      + "주제:: \n"
      + "*** \n"
      + "# " + title + "\n\n\n\n\n"
      + "*** \n\n\n"
      + "*** \n"
      + markdownBody ;  

  document.location.href = "obsidian://new?"
    + "file=" + encodeURIComponent(folder + fileName)
    + "&content=" + encodeURIComponent(fileContent)
    + vaultName ;
})

Bookmarklet Maker에 적용한 모습입니다.

 

“Generate Bookmarklet” 버튼을 클릭하면 아래 처럼 축약한 형태의 URL 주소가 나오는 것을 보실 수 있습니다. 이 URL 주소를 아까처럼 똑같이 적용하시면 됩니다! 원하는 보관함, 폴더, 태그, 템플릿까지 붙여서 나오는 걸 보실 수 있습니다! 한가지 팁으로는 저는 tag 부분에 하기보다는 차라리 내용 부분에 “#태그”로 넣는 편이 훨씬 더 잘 됐습니다. 참고해주세요!

 

제가 만든 템플릿으로 만든 URL 주소입니다.

javascript:(function()%7Bjavascript%3A Promise.all(%5Bimport('https%3A%2F%2Funpkg.com%2Fturndown%406.0.0%3Fmodule')%2C import('https%3A%2F%2Funpkg.com%2F%40tehshrike%2Freadability%400.2.0')%2C %5D).then(async (%5B%7B%0A    default%3A Turndown%0A%7D%2C %7B%0A    default%3A Readability%0A%7D%5D) %3D> %7B%0A%0A  %2F* Optional vault name *%2F%0A  const vault %3D "ConnectingDots"%3B%0A%0A  %2F* Optional folder name such as "Clippings%2F" *%2F%0A  const folder %3D "Inbox%2F"%3B%0A%0A  %2F* Optional tags  *%2F%0A  const tags %3D ""%3B%0A%0A  function getSelectionHtml() %7B%0A    var html %3D ""%3B%0A    if (typeof window.getSelection !%3D "undefined") %7B%0A        var sel %3D window.getSelection()%3B%0A        if (sel.rangeCount) %7B%0A            var container %3D document.createElement("div")%3B%0A            for (var i %3D 0%2C len %3D sel.rangeCount%3B i < len%3B %2B%2Bi) %7B%0A                container.appendChild(sel.getRangeAt(i).cloneContents())%3B%0A            %7D%0A            html %3D container.innerHTML%3B%0A        %7D%0A    %7D else if (typeof document.selection !%3D "undefined") %7B%0A        if (document.selection.type %3D%3D "Text") %7B%0A            html %3D document.selection.createRange().htmlText%3B%0A        %7D%0A    %7D%0A    return html%3B%0A  %7D%0A%0A  const selection %3D getSelectionHtml()%3B%0A%0A  const %7B%0A      title%2C%0A      byline%2C%0A      content%0A  %7D %3D new Readability(document.cloneNode(true)).parse()%3B%0A%0A  function getFileName(fileName) %7B%0A    var userAgent %3D window.navigator.userAgent%2C%0A        platform %3D window.navigator.platform%2C%0A        windowsPlatforms %3D %5B'Win32'%2C 'Win64'%2C 'Windows'%2C 'WinCE'%5D%3B%0A%0A    if (windowsPlatforms.indexOf(platform) !%3D%3D -1) %7B%0A      fileName %3D fileName.replace('%3A'%2C '').replace(%2F%5B%2F%5C%5C%3F%25*%7C"<>%5D%2Fg%2C '-')%3B%0A    %7D else %7B%0A      fileName %3D fileName.replace('%3A'%2C '').replace(%2F%5C%2F%2Fg%2C '-').replace(%2F%5C%5C%2Fg%2C '-')%3B%0A    %7D%0A    return fileName%3B%0A  %7D%0A  const fileName %3D getFileName(title)%3B%0A%0A  if (selection) %7B%0A      var markdownify %3D selection%3B%0A  %7D else %7B%0A      var markdownify %3D content%3B%0A  %7D%0A%0A  if (vault) %7B%0A      var vaultName %3D '%26vault%3D' %2B encodeURIComponent(%60%24%7Bvault%7D%60)%3B%0A  %7D else %7B%0A      var vaultName %3D ''%3B%0A  %7D%0A%0A  const markdownBody %3D new Turndown(%7B%0A      headingStyle%3A 'atx'%2C%0A      hr%3A '---'%2C%0A      bulletListMarker%3A '-'%2C%0A      codeBlockStyle%3A 'fenced'%2C%0A      emDelimiter%3A '*'%2C%0A  %7D).turndown(markdownify)%3B%0A%0A  var date %3D new Date()%3B%0A%0A  function convertDate(date) %7B%0A    var yyyy %3D date.getFullYear().toString()%3B%0A    var mm %3D (date.getMonth()%2B1).toString()%3B%0A    var dd  %3D date.getDate().toString()%3B%0A    var mmChars %3D mm.split('')%3B%0A    var ddChars %3D dd.split('')%3B%0A    return yyyy %2B '-' %2B (mmChars%5B1%5D%3Fmm%3A"0"%2BmmChars%5B0%5D) %2B '-' %2B (ddChars%5B1%5D%3Fdd%3A"0"%2BddChars%5B0%5D)%3B%0A  %7D%0A%0A  const today %3D convertDate(date)%3B%0A%0A  const fileContent %3D %0A      "---%5Cn" %0A      %2B "created%3A" %2B today %2B "%5Cn"%0A      %2B "aliases%3A %5B%5D %5Cn"%0A      %2B "---%5Cn"%0A      %2B "종류%3A%3A %23📥%2F📰 %5Cn"%0A      %2B "상태%3A%3A %23🌱 %5Cn"%0A      %2B "출처%3A%3A %5B" %2B title %2B "%5D(" %2B document.URL %2B ")%5Cn"%0A      %2B "저자%3A%3A " %2B byline %2B "%5Cn"%0A      %2B "주제%3A%3A %5Cn"%0A      %2B "*** %5Cn"%0A      %2B "%23 " %2B title %2B "%5Cn%5Cn%5Cn%5Cn%5Cn"%0A      %2B "*** %5Cn%5Cn%5Cn"%0A      %2B "*** %5Cn"%0A      %2B markdownBody %3B  %0A   %0A  document.location.href %3D "obsidian%3A%2F%2Fnew%3F"%0A    %2B "file%3D" %2B encodeURIComponent(folder %2B fileName)%0A    %2B "%26content%3D" %2B encodeURIComponent(fileContent)%0A    %2B vaultName %3B%0A%7D)%7D)()%3B

 

시연영상

위에 설명은 Window, Edge 브라우저였으나 시연 영상은 Mac, Safari 입니다.

 

 

 

이렇게 웹에서 버튼 하나로 쉽게 스크랩할 수 있는 Bookmarklet을 이용한 웹 클리퍼에 대해서 알아보았습니다! 많이 사용하셨으면 좋겠습니다!

 


한국에서는 옵시디언에 대한 정보가 많이 부족합니다. 부족한 옵시디언에 대한 정보와 사용방법 그리고 꿀팁들을 "Obsidian 옵시디언 사용자 모임" 네이버 카페 "Obsidian 사용자모임" 오픈카톡방에서 소통을 하고 있습니다. 많이 참여해주세요! 😄

 

Obsidian 옵시디언 사용자 모임 : 네이버 카페

Second Brain을 만들기 위한 Obsidian에 관한 정보, 노하우, 꿀팁 등을 공유합니다.

cafe.naver.com

 

Obsidian 사용자 모임

#obsidian #옵시디언 #노션 #RoamResearch #스마트글쓰기 #세컨드브레인 #secondbrain #제텔카스텐

open.kakao.com

 

댓글