scrapbox-reference-maker
使い方
bookmarkletを押すとdialogが出てくる
こういうの
タイトル・URL
変更する必要があればいじる
説明文
textarea
一言メモを残すように促す
project
scrapを作成する先のproject
defaultは takker
confirm
を押すと作成される
2021-02-03 18:38:00 選択範囲を引用として取り込むようにした
bookmarklet.jsjavascript:(()=>{let s=document.createElement("script");s.src='https://scrapbox.io/api/code/takker/scrapbox-reference-maker/script2.js';document.body.appendChild(s);})()
Native JS版
script2.jsjavascript: (() => {
const dialogId = 'scrapbox-reference-maker';
const dialogHTML = `<dialog id="${dialogId}">
<form method="dialog">
<p>
<label>Title:
<input name="title" type="text" ></input>
</label>
</p>
<p>
<label>Project:
<input name="project" type="text" ></input>
</label>
</p>
<p>
<label>Description:
<textarea name="description"></textarea>
</label>
</p>
<menu>
<button value="cancel">Cancel</button>
<button value="default">Confirm</button>
</menu>
</form></dialog>`;
document.getElementById(dialogId)?.remove();
document.body.insertAdjacentHTML('beforeend',dialogHTML);
// 選択範囲を取得する
const quote = window.getSelection().toString().trim()
.split(/\n\r?|\r?\n|\r|\f/g) // 改行区切りで配列化
.filter(line => line !== '') // 空行は削除
.map(line => `>${line}`); // 引用記号
// utilities
const ng = text => text.trim().replace(/[\[\]\n]/g, ' ');
const e = text => encodeURIComponent(text);
const zero = n => String(n).padStart(2, '0');
const today = (d => `[${d.getFullYear()}-${zero(d.getMonth()+1)}-${zero(d.getDate())}] ${zero(d.getHours())}:${zero(d.getMinutes())}:${zero(d.getSeconds())}`)(new Date());
const dialog = document.getElementById(dialogId);
dialog.querySelector('input[name="title"]').value = ng(document.title).trim();
dialog.querySelector('input[name="project"]').value = 'takker';
dialog.addEventListener('close', () => {
if (dialog.returnValue !== 'default') return;
const elements = dialog.firstElementChild.elements;
const title = elements['title'].value;
const project = elements['project'].value;
const description = dialog.querySelector('textarea').value;
// scrap pageを作成する
const lines = [
`[${window.location.href} ${title}]`,
...quote,
description,
'',
`Added on ${today}`,
];
window.open(`https://scrapbox.io/${project}/${e(ng(title))}?body=${e(lines.join('\n'))}`);
});
dialog.showModal();
})();
↓うまく動かないので放置
↓のanswerのcodeに沿えば直るかもしれないが、流石に面倒になってきたので止めた
また独自にeventを生やす方法もよくわからなかった
cf.
本当にweb componentで作りたいときは、
Slim.jsを使ったほうが良さそう。
script.jsjavascript: (() => {
const dialogId = 'scrapbox-reference-maker';
const dialogHTML = `
<form method="dialog">
<label>Title:
<input id="title" type="text" ></input>
</label>
<label>Project:
<input id="project" type="text" ></input>
</label>
<label>Description:
<textarea id="description"></textarea>
</label>
<menu>
<button value="cancel">Cancel</button>
<button value="default">Confirm</button>
</menu>
</form>`;
customElements.define(dialogId,
class extends HTMLDialogElement {
constructor() {
super();
// dialogのDOMを作成
const shadowRoot = this.attachShadow({mode: 'open'});
const fragment = document.createDocumentFragment();
fragment.innerHTML = dialogHTML;
// 要素を取得
this.titleForm = fragment.querySelector('#title');
this.projectForm = fragment.querySelector('#project');
this.descriptionForm = fragment.querySelector('#description');
// 属性から初期値を設定する
const title = this.getAttribute('title');
const project = this.getAttribute('project');
const url = this.getAttribute('url');
const onConfirm = this.getAttribute('onConfirm');
this.titleForm.textContent = title;
this.projectForm.textContent = project;
// confirmを押されたらscrapのdataを返す
this.addEventListener('close', () =>{
if (this.returnValue === "cancel") return;
onConfirm({
title: this.titleForm.textContent,
url: url,
project: this.projectForm.textContent,
description: this.descriptionForm.textContent});
});
shadowRoot.appendChild(fragment);
this.rendered = false;
}
static get observedAttributes() {
return ['title','project','url'];
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (oldVal !== newVal) {
console.log('attributeChangedCallback', newVal);
this.root.querySelector('.name').textContent = newVal;
}
}
},{extends: 'dialog'});
// utilities
const ng = text => text.trim().replace(/[\[\]\n]/g, ' ');
const e = text => encodeURIComponent(text);
const zero = n => String(n).padStart(2, '0');
const today = (d => `${d.getFullYear()}-${zero(d.getMonth()+1)}-${zero(d.getDate())} ${zero(d.getHours())}:${zero(d.getMinutes())}:${zero(d.getSeconds())}`)(new Date());
document.body.insertAdjacentHTML('beforeend', `
<dialog is="${dialogId}"
id="${dialogId}"
title="${ng(document.title).trim()}"
project="takker"
url="${window.location.href}"></dialog>
`);
let result = {};
const dialog = document.getElementById(dialogId);
dialog.setAttribute('onConfirm', ({title,url,project,description})=>{
// scrap pageを作成する
const lines = [
`[${url} ${title}]`,
'',
description,
'',
`Added on [${today}]`,
];
window.open(`https://scrapbox.io/${project}/${e(ng(title))}?body=${e(lines.join('\n'))}`);
});
dialog.showModal();
})();