Retasusan
https://scrapbox.io/files/6719d74e905a107deb40b468.png
ここはretasusanのページですCosense Beaver.icon
Retasusan
ゴトー
times一覧
2024/10 Retasusan times
code:script.js
$(() => {
$.getScript("https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.14.0/mermaid.min.js")
.done((script, textStatus) => {
mermaid.mermaidAPI.initialize({ startOnLoad: false })
const mermaidViewer = new MermaidViewer()
mermaidViewer.onScrapboxPageChanged()
scrapbox.on("page:changed", () => mermaidViewer.onScrapboxPageChanged())
scrapbox.on("lines:changed", () => mermaidViewer.onScrapboxLinesChanged())
})
.fail((jqxhr, settings, exception) => {
console.error(exception)
})
const MermaidViewer = function() {
const DEFAULT_SHOW_CODE = false
this.recentMermaidCodes = new Map()
this.codeViewStatusRepository = new MermaidCodeViewStatusRepository()
this.onScrapboxLinesChanged = function() {
if (scrapbox.Page.lines) {
this.updateDiagrams()
}
}
this.onScrapboxPageChanged = function() {
if (scrapbox.Page.lines) {
this.updateDiagrams()
this.setAllCodeViewStatus(DEFAULT_SHOW_CODE)
}
}
// すべてのコードブロックの表示ステータスを変更
// 引数: value 表示ステータス (true|false)
this.setAllCodeViewStatus = function(value) {
for (const id, code of this.recentMermaidCodes) {
code.setCodeViewStatus(value)
}
}
// 変更があればダイアグラムを更新
this.updateDiagrams = function() {
const newCodes = this.findMermaidCodes()
const diff = MermaidViewerUtils.diffMermaidCodes(this.recentMermaidCodes, newCodes)
for (const item of diff) {
if (item.op === "delete") {
item.code.deleteDiagram()
} else {
item.code.updateDiagram()
}
}
this.recentMermaidCodes = newCodes
}
// mermaidコードをページ内から検索
// 戻り値: Map型
// キー: コードブロックのID(最初の行ID)
// 値: MermaidCode
this.findMermaidCodes = function() {
const result = new Map()
var text, filename, id, lastLineId, lineIds
for (const line of scrapbox.Page.lines) {
if (line.codeBlock && line.codeBlock.lang === "mermaid") {
if (line.codeBlock.start) {
text = ""
id = line.id
lineIds = new Set()
} else {
text += "\n" + line.text
}
lineIds.add(line.id)
if (line.codeBlock.end) {
lastLineId = line.id
text = text.trim()
result.set(id, new MermaidCode(id, text, lastLineId, lineIds, this.codeViewStatusRepository))
}
}
}
return result
}
}
const MermaidCode = function(id, text, lastLineId, lineIds, codeViewStatusRepository) {
const MERMAID_SVG_ID_PREFIX = "mermaid-"
this.id = id
this.text = text
this.lastLineId = lastLineId
this.lineIds = lineIds
this.codeViewStatusRepository = codeViewStatusRepository
this.svgId = MERMAID_SVG_ID_PREFIX + id
// mermaidダイアグラムを更新
this.updateDiagram = function() {
try {
const svg = mermaid.mermaidAPI.render(this.svgId, this.text)
$("#" + this.svgId).remove()
$("#L" + this.lastLineId).after(svg)
} catch (e) {
console.error(e)
$("#L" + this.lastLineId).after($("#" + this.svgId))
}
$("#" + this.svgId)
.on("click", () => this.onSvgClicked())
.css("cursor","pointer")
}
// mermaidダイアグラムを削除
this.deleteDiagram = function() {
$("#" + this.svgId).remove()
}
// mermaidダイアグラム(SVG)がクリックされたときのイベントハンドラ
// コードブロックの表示ステータスを変更
this.onSvgClicked = function() {
this.codeViewStatusRepository.changeStatus(this.id)
this.applyCodeView()
}
// コードブロックの表示ステータスを適用
this.applyCodeView = function() {
const status = this.codeViewStatusRepository.getStatus(this.id)
for (const lineId of this.lineIds) {
if (status) {
$("#L" + lineId).show(100)
} else {
$("#L" + lineId).hide(100)
}
}
}
// コードブロックの表示ステータスを変更
this.setCodeViewStatus = function(value) {
this.codeViewStatusRepository.setStatus(this.id, value)
this.applyCodeView()
}
}
const MermaidCodeViewStatusRepository = function() {
this.status = new Map()
this.defaultValue = true
this.changeStatus = function(id) {
const old = this.status.has(id) ? this.status.get(id) : this.defaultValue
this.status.set(id, !old)
}
this.getStatus = function(id) {
return this.status.has(id) ? this.status.get(id) : this.defaultValue
}
this.setStatus = function(id, value) {
this.status.set(id, value)
}
}
const MermaidViewerUtils = {}
// 2つのMap型に格納されたコードの差分を返す
// 引数: oldMap 古い値(Map型)
// 引数: newMap 新しい値(Map型)
MermaidViewerUtils.diffMermaidCodes = function(oldMap, newMap) {
const result = []
const intersection = new Set()
for (const key, val of newMap) {
if (!oldMap.has(key)) {
result.push({ op: "new", key: key, code: newMap.get(key) })
} else {
intersection.add(key)
}
}
for (const key, val of oldMap) {
if (!newMap.has(key)) {
result.push({ op: "delete", key: key, code: oldMap.get(key) })
intersection.delete(key)
}
}
for (const key of intersection) {
const oldVal = oldMap.get(key)
const newVal = newMap.get(key)
if (oldVal.text !== newVal.text) {
result.push({ op: "changed", key: key, code: newMap.get(key) })
}
}
return result;
}
})
code:style.css
@import url('https://fonts.googleapis.com/css2?family=BIZ+UDPMincho&display=swap');
@import '/api/code/Mijinko/Streamボタンを表示するUserCSS/style.css';/* */
@import '/api/code/Mijinko/コードブロックの行番号を表示するUserCSS/style.css';/* */
@import '/api/code/Mijinko/ピン留めアイテムとそれ以外を分けるUserCSS/style.css';/* */
html, body {
background-image: radial-gradient(circle at top right, rgb(49, 157, 235) 0%, rgb(49, 157, 235) 13%,rgb(76, 166, 234) 13%, rgb(76, 166, 234) 23%,rgb(103, 176, 232) 23%, rgb(103, 176, 232) 33%,rgb(130, 185, 231) 33%, rgb(130, 185, 231) 46%,rgb(156, 194, 230) 46%, rgb(156, 194, 230) 48%,rgb(183, 203, 229) 48%, rgb(183, 203, 229) 63%,rgb(210, 213, 227) 63%, rgb(210, 213, 227) 83%,rgb(237, 222, 226) 83%, rgb(237, 222, 226) 100%);
min-height: 100vh;
margin-bottom: 0px;
}
/*共通部分*/
div div div a#dropdownMenuSort, div div div a#dropdownMenuFilter{
color: white !important;
}
.page-list-translation-menu .fas{
color: white;
}
.page-menu .tool-btn{
color: white;
}
strong{
border-left: 8px groove #67DBD3;
margin-left: 7px;
}
.line strong.level.level-1{
border-bottom: 2px solid #00ffff;
padding: 0px;
}
.line strong.level.level-2{
border-bottom: 2px solid #00bfff;
padding: 0px;
}
.line strong.level.level-3{
border-bottom: 2px solid #0000ff;
padding: 0px;
}
.line strong.level.level-4{
border-bottom: 2px solid #00008b;
padding: 0px;
}
.line.line-title,
.text-input.line-title{
font-family: "BIZ UDPMincho";
font-size: 35px;
}
.line .indent-mark .dot{
border-radius: 0%;
}
/* タグアイコンの共通スタイル (1) */
.line:not(.cursor-line) ahref$='/!'type='link':not(.icon) span,
.line:not(.cursor-line) ahref$='/%3F'type='link':not(.icon) span,
.line:not(.cursor-line) ahref$='/*'type='link':not(.icon) span,
.line:not(.cursor-line) ahref$='/_'type='link':not(.icon) span,
.line:not(.cursor-line) ahref$='/x'type='link':not(.icon) span,
.line:not(.cursor-line) ahref$='/o'type='link':not(.icon) span,
.line:not(.cursor-line) ahref$='/%3E'type='link':not(.icon) span,
.line:not(.cursor-line) ahref$='/%3C'type='link':not(.icon) span {
display: inline-block; width: 0; text-indent: -9999px }
/* タグアイコンの共通スタイル (2) */
.line:not(.cursor-line) ahref$='/!'type='link':not(.icon)::after,
.line:not(.cursor-line) ahref$='/%3F'type='link':not(.icon)::after,
.line:not(.cursor-line) ahref$='/*'type='link':not(.icon)::after,
.line:not(.cursor-line) ahref$='/_'type='link':not(.icon)::after,
.line:not(.cursor-line) ahref$='/x'type='link':not(.icon)::after,
.line:not(.cursor-line) ahref$='/o'type='link':not(.icon)::after,
.line:not(.cursor-line) ahref$='/%3E'type='link':not(.icon)::after,
.line:not(.cursor-line) ahref$='/%3C'type='link':not(.icon)::after {
display: inline-block; min-width: 1.15em; padding-left: 1px;
font: normal 110%/normal "Font Awesome 5 Free"; text-align: center }
/* ここから各アイコンの設定 */
.line:not(.cursor-line) ahref$='/!'type='link':not(.icon)::after { content: '\f06a'; color: #F6AE2D; font-weight:bold; }
/* ? */
.line:not(.cursor-line) ahref$='/%3F'type='link':not(.icon)::after { content: '\f059'; color: #758E4F; font-weight:bold; }
.line:not(.cursor-line) ahref$='/*'type='link':not(.icon)::after { content: '\f069'; color: #F26419; font-weight:bold; }
.line:not(.cursor-line) ahref$='/_'type='link':not(.icon)::after { content: '\f0c8'; color: #08BDBD; font-weight: 400; }
.line:not(.cursor-line) ahref$='/x'type='link':not(.icon)::after { content: '\f14a'; color: #2489C5; font-weight:400; }
.line:not(.cursor-line) ahref$='/o'type='link':not(.icon)::after { content: '\f111'; color: #F26419; font-weight: 400; }
/* > */
.line:not(.cursor-line) ahref$='/%3E'type='link':not(.icon)::after { content: '\f14d'; color: lightgrey; font-weight: 400; }
/* < */
.line:not(.cursor-line) ahref$='/%3C'type='link':not(.icon)::after { content: '\f274'; color: lightgrey; font-weight: 400; }
/* インデントの装飾 */
.line .indent-mark .dot {
}
.line .indent-mark .c-1 + .dot {
background-color: #fc034a;
}
.line .indent-mark .c-2 + .dot {
background-color: #00c96f;
}
.line .indent-mark .c-3 + .dot {
background-color: #fcc603;
}
/* 外部リンクにアイコンを付加する */
.line span:not(.modal-image):not(.pointing-device-map) > a.link:not(.icon)::after {
font-family: 'Font Awesome 5 Free';
content: ' \f35d';
font-weight: 900;
display: inline-block;
}
/* ピン留めされたページを独立した行にする */
.page-list-item.pin + .page-list-item:not(.pin) {
grid-column-start: 1;
}
#member