amp;"); } // Avoid multiple executions const insertFileNamesIntoCodeBlocks = () => { console.log("run"); document.querySelectorAll('pre[class*="language-"]').forEach((wrapperElm) => { let title; const classNames = wrapperElm.querySelector("code").className.split(" "); title = classNames.find((x) => x.startsWith(":"))?.replace(":", ""); if (title === "") { title = classNames .find((x) => x.startsWith("language-")) ?.replace("language-", ""); } if (!title) { return; } if (settings.substitutionTokenForSpace) { title = title.replace( new RegExp(escapeRegExp(settings.substitutionTokenForSpace), "g"), " " ); } wrapperElm.style.setProperty("position", "relative", "important"); wrapperElm.style.setProperty("padding-top", "30px", "important"); wrapperElm .querySelectorAll(".obsidian-embedded-code-title__code-block-title") .forEach((x) => x.remove()); let d = document.createElement("pre"); d.appendText(title); d.className = "obsidian-embedded-code-title__code-block-title"; d.style.color = settings.titleFontColor; d.style.backgroundColor = settings.titleBackgroundColor; wrapperElm.prepend(d); }); }; setInterval(insertFileNamesIntoCodeBlocks, 1000); ``` [[Notes/publish.css|publish.css]]も追加する。 ```css:publish.css .obsidian-embedded-code-title__code-block-title { position: absolute; top: 0; left: 0; font-size: 85% !important; padding: 3px !important; margin: 0 !important; background-color: #1c1c1c !important; color: darkgrey !important; border-radius: 0 !important; } ``` ### 以前のやり方 *MutationObserverの動作が不安定で表示されないときがあったため、無駄な処理が走っても確実に反映される方を選ぶことにした* ```js:publish.js // ***************************************************************************** // ページに出現するすべてのコードブロックに対して、ファイル名を取得しスタイルを付与して埋め込む // ***************************************************************************** function debounce(func, wait, immediate) { var timeout; return function () { var context = this, args = arguments; clearTimeout(timeout); timeout = setTimeout(function () { timeout = null; if (!immediate) func.apply(context, args); }, wait); if (immediate && !timeout) func.apply(context, args); }; } // MutationObserverに複数イベントが発生するため最後のみを実行 (waitは調整がいる) // ページ初回読込時もdebounceのdelayによって動作するが、動作しないこともある.. const insertFileNamesIntoCodeBlocks = debounce(() => { document.querySelectorAll('pre[class*="language-"]').forEach((wrapperElm) => { let fileName = wrapperElm .querySelector("code") .className.split(" ") .find((x) => x.startsWith(":")) ?.replace(":", ""); if (!fileName) { return; } wrapperElm.style.position = "relative"; wrapperElm.style.paddingTop = "30px"; wrapperElm .querySelectorAll(".obsidian-embedded-code-title__code-block-title") .forEach((x) => x.remove()); let d = document.createElement("pre"); d.appendText(fileName); d.className = "obsidian-embedded-code-title__code-block-title"; wrapperElm.prepend(d); }); }, 150); // ページ遷移したとき( = プレビューセクションのChild DOM Listが変更されたとき)に先ほどの処理を実行 let observer; function startObserve() { if (observer) { observer.disconnect(); } const target = document.querySelector(".markdown-preview-section"); observer = new MutationObserver(insertFileNamesIntoCodeBlocks); observer.observe(target, { childList: true, }); insertFileNamesIntoCodeBlocks(); } // 初期表示のページではMutationObserverは発火しないので個別に実行 setTimeout(insertFileNamesIntoCodeBlocks, 150); // 1発目では監視が不発に終わることがあるので間隔をあけて計4回実行する setTimeout(insertFileNamesIntoCodeBlocks, 1000); setTimeout(insertFileNamesIntoCodeBlocks, 2000); setTimeout(insertFileNamesIntoCodeBlocks, 4000); ``` ## 使い方 以下のように書くと ````markdown ```python:sample.py def main(): print("hoge") ``` ```` 以下のように表示される。 ```python:sample.py def main(): print("hoge") ```