tks
https://gyazo.com/433fdc7f465667137cb7a26ad600cf4a
https://gyazo.com/e5679737664c442ee1ee2d8fe5ae3b56
this is tks’s page
好きなこと
ラジオ・ポッドキャストを聴くこと
本を読む
関心事
知的生産、ナレッジマネジメント、情報管理
タスク管理
⏸️code:style.css
a.bidirectional-page-link{display:none}
ネタバレ防止
code:style.css
.deco-\#{ /* 記法のキーとして#を使ったけど何でもいいと思う */
background-color: #4a4a4a; /* 背景色をテキスト色と同じにする */ }
.line.cursor-line .deco-\#, .deco-\#:hover { /* カーソルがある行とマウスホバー時だけ背景を戻す */
background-color: inherit;
}
code:script.js
(function () {
// ボタンクリック時の処理
cosense.PageMenu.addMenu({
title: '見出し',
icon: 'fas fa-list',
onClick: generateHeadingMenu
})
// 見出しメニューを生成する関数
function generateHeadingMenu() {
try {
const menu = cosense.PageMenu('見出し')
menu.removeAllItems()
console.log('Generating heading menu...')
// すべての行をループ
for (let i = 0; i < cosense.Page.lines.length; i++) {
const line = cosense.Page.linesi // セクション開始でなければスキップ
if (!line.section || !line.section.start) continue
// 行のテキストを取得
const text = line.text || ''
// デバッグ: 各行のテキストを出力
if (text.length > 0) {
console.log(Checking line: "${text}")
}
let headingText = null
let headingLevel = 0
let prefixEmoji = null
// 1. 強調マークアップを探す
const strongMatch = text.match(strongRegex)
if (strongMatch && strongMatch1) { headingText = strongMatch1.trim() headingLevel = strongMatch0.match(/\*+/)0.length console.log(Found strong heading: "${headingText}" with level ${headingLevel})
}
// 2. 絵文字から始まる行を探す
else {
// 最初の文字を取得(トリムして空白を除去)
const trimmedText = text.trim()
if (trimmedText.length === 0) continue
// 最初の文字が絵文字かどうかをチェックする関数
function isFirstCharEmoji(text) {
// 指定された絵文字リスト(特に使用される絵文字)
const specificEmojis = ['📄', '📋', '✉️', '🤔', '🛒', '🗓️', '💡', '✅',
'☑️', '✓', '✔️', '📌', '📍', '🔍', '⭐', '★',
'☆', '⚡', '🔴', '🟠', '🟡', '🟢', '🔵', '🟣',
'⚫', '⚪', '📝', '📔', '📒', '📕', '📗', '📘',
'📙', '🔑', '🗝️', '👉', '👆', '☝️', '👇', '👈',
'❗', '❓', '‼️', '⁉️', '❕', '❔', '🚩', '🏁',
'🎯', '🔔', '🔖', '📑', '🛠️', '🔧', '🔨', '🗂️',
'📁', '📂', '💬', '🗣️', '📢', '📣'];
// テキストの最初の文字(絵文字は複数のコードポイントで構成されている可能性がある)
const firstTwoChars = text.slice(0, 2);
const firstThreeChars = text.slice(0, 3);
const firstFourChars = text.slice(0, 4);
// 明示的なリストチェック(最大4文字まで)
for (const emoji of specificEmojis) {
if (text.startsWith(emoji)) {
return emoji;
}
}
// 一般的な絵文字の範囲チェック(バックアップ)
const firstCharCode = text.codePointAt(0);
if ((firstCharCode >= 0x1F300 && firstCharCode <= 0x1F6FF) || // Miscellaneous Symbols and Pictographs
(firstCharCode >= 0x1F900 && firstCharCode <= 0x1F9FF) || // Supplemental Symbols and Pictographs
(firstCharCode >= 0x2600 && firstCharCode <= 0x26FF) || // Miscellaneous Symbols
(firstCharCode >= 0x2700 && firstCharCode <= 0x27BF) || // Dingbats
(firstCharCode >= 0x1F1E6 && firstCharCode <= 0x1F1FF) || // Flags
(firstCharCode >= 0x1F000 && firstCharCode <= 0x1F02F) || // Mahjong Tiles
(firstCharCode >= 0x1F0A0 && firstCharCode <= 0x1F0FF)) { // Playing Cards
// 絵文字の長さを判定
const firstCodePoint = String.fromCodePoint(firstCharCode);
return firstCodePoint;
}
return null; // 絵文字ではない
}
// 最初の文字が絵文字かチェック
const emoji = isFirstCharEmoji(trimmedText);
if (emoji) {
prefixEmoji = emoji;
// 絵文字の後のテキストを取得
const emojiLength = emoji.length;
let remainingText = trimmedText.slice(emojiLength).trim();
if (remainingText) {
headingText = remainingText;
headingLevel = 1; // 絵文字見出しは基本レベル1とする
console.log(Found emoji heading: "${headingText}" with emoji ${prefixEmoji});
}
}
}
// 見出しテキストが見つかった場合、メニューに追加
if (headingText) {
// クリックハンドラを定義
const lineId = line.id;
function jumpToLine() {
console.log('Jumping to line id:', lineId);
window.location.hash = lineId;
return false;
}
// メニュータイトルを作成
const menuTitle = prefixEmoji ? ${prefixEmoji} ${headingText} : headingText;
// メニューアイテムを追加
menu.addItem({
title: menuTitle,
onClick: jumpToLine
});
}
}
console.log('Heading menu generated successfully');
} catch (error) {
console.error('Error generating heading menu:', error);
}
}
})();
チェックボックス
⏸️code:script.js
(function () {
function cycleCheckboxState() {
const textarea = document.querySelector('textarea.text-input');
if (!textarea) {
alert('エディタが見つかりません');
return;
}
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
const selectedText = textarea.value.slice(start, end);
if (!selectedText) {
alert('テキストを選択してください');
return;
}
const lines = selectedText.split('\n');
const updatedLines = lines.map(line => {
const trimmed = line.trimStart();
if (trimmed.startsWith('o')) { return line.replace('o', 'v'); } else if (trimmed.startsWith('v')) { return line.replace('v', '').trimStart(); } else {
return [o] ${line};
}
});
const newText = updatedLines.join('\n');
const before = textarea.value.slice(0, start);
const after = textarea.value.slice(end);
textarea.value = before + newText + after;
const newCursor = before.length + newText.length;
textarea.setSelectionRange(newCursor, newCursor);
textarea.dispatchEvent(new Event('input', { bubbles: true }));
console.log('🔁 チェックボックス:4ステップループ完了');
}
// UIにボタン追加
if (typeof cosense !== 'undefined' && cosense.PopupMenu) {
cosense.PopupMenu.addButton({
title: 'チェックボックス',
onClick: cycleCheckboxState
});
} else {
const button = document.createElement('button');
button.textContent = 'チェックボックス4ステップ';
button.style.position = 'fixed';
button.style.top = '330px';
button.style.right = '10px';
button.style.zIndex = '9999';
button.onclick = cycleCheckboxState;
document.body.appendChild(button);
}
})();
⏸️code:style.css
/* チェックボックスになるタグ v2 Font Awesome版 */
.line:not(.cursor-line) ahref$='/o':not(.icon) span, .line:not(.cursor-line) ahref$='/v':not(.icon) span { display: inline-block; width: 0; text-indent: -9999px }
.line:not(.cursor-line) ahref$='/o':not(.icon)::after, .line:not(.cursor-line) ahref$='/v':not(.icon)::after { display: inline-block; min-width: 1.15em; padding-left: 1px;
font-family: 'Font Awesome 5 Free'; font-weight: 400;
font-size: 120%; text-align: center; vertical-align: middle }
.line:not(.cursor-line) ahref$='/o':not(.icon)::after { content: '\f0c8'; color: #08BDBD } .line:not(.cursor-line) ahref$='/v':not(.icon)::after { content: '\f14a'; color: #2489C5 }