vault backup: 2026-04-14 14:01:52
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"userName": "",
|
"userName": "",
|
||||||
"permissionMode": "yolo",
|
"permissionMode": "yolo",
|
||||||
"model": "haiku",
|
"model": "kimi-k2-turbo-preview",
|
||||||
"thinkingBudget": "off",
|
"thinkingBudget": "medium",
|
||||||
"effortLevel": "high",
|
"effortLevel": "high",
|
||||||
"serviceTier": "default",
|
"serviceTier": "default",
|
||||||
"enableAutoTitleGeneration": true,
|
"enableAutoTitleGeneration": true,
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
"enableOpus1M": false,
|
"enableOpus1M": false,
|
||||||
"enableSonnet1M": false,
|
"enableSonnet1M": false,
|
||||||
"lastModel": "haiku",
|
"lastModel": "haiku",
|
||||||
"environmentVariables": "",
|
"environmentVariables": "ANTHROPIC_API_KEY=sk-Ij8lzrJtUIj958RCWHA1A9fnjlrYZImddNkISfeLA8vHkC3m\nANTHROPIC_BASE_URL=https://api.moonshot.cn/anthropic\nANTHROPIC_MODEL=kimi-k2-turbo-preview",
|
||||||
"environmentHash": ""
|
"environmentHash": "ANTHROPIC_BASE_URL=https://api.moonshot.cn/anthropic|ANTHROPIC_MODEL=kimi-k2-turbo-preview"
|
||||||
},
|
},
|
||||||
"codex": {
|
"codex": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
@@ -42,24 +42,24 @@
|
|||||||
"reasoningSummary": "detailed",
|
"reasoningSummary": "detailed",
|
||||||
"environmentVariables": "",
|
"environmentVariables": "",
|
||||||
"environmentHash": "",
|
"environmentHash": "",
|
||||||
"installationMethod": "native-windows",
|
"installationMethodsByHost": {
|
||||||
"installationMethodsByHost": {},
|
"DESKTOP-RG8Q1D2": "native-windows"
|
||||||
"wslDistroOverride": "",
|
},
|
||||||
"wslDistroOverridesByHost": {}
|
"wslDistroOverridesByHost": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"settingsProvider": "claude",
|
"settingsProvider": "claude",
|
||||||
"savedProviderModel": {
|
"savedProviderModel": {
|
||||||
"claude": "haiku"
|
"claude": "kimi-k2-turbo-preview"
|
||||||
},
|
},
|
||||||
"savedProviderEffort": {
|
"savedProviderEffort": {
|
||||||
"claude": "high"
|
"claude": "high"
|
||||||
},
|
},
|
||||||
"savedProviderServiceTier": {},
|
"savedProviderServiceTier": {},
|
||||||
"savedProviderThinkingBudget": {
|
"savedProviderThinkingBudget": {
|
||||||
"claude": "off"
|
"claude": "medium"
|
||||||
},
|
},
|
||||||
"lastCustomModel": "",
|
"lastCustomModel": "kimi-k2-turbo-preview",
|
||||||
"maxTabs": 3,
|
"maxTabs": 3,
|
||||||
"tabBarPosition": "input",
|
"tabBarPosition": "input",
|
||||||
"enableAutoScroll": true,
|
"enableAutoScroll": true,
|
||||||
|
|||||||
27
.claudian/sessions/conv-1776074120254-v83qe13hb.meta.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"id": "conv-1776074120254-v83qe13hb",
|
||||||
|
"providerId": "claude",
|
||||||
|
"title": "I have added new skills in the",
|
||||||
|
"titleGenerationStatus": "failed",
|
||||||
|
"createdAt": 1776074120254,
|
||||||
|
"updatedAt": 1776074751208,
|
||||||
|
"lastResponseAt": 1776074751208,
|
||||||
|
"sessionId": "0dd9dd0d-acfc-4060-9da1-afb2dd26dfca",
|
||||||
|
"providerState": {
|
||||||
|
"providerSessionId": "0dd9dd0d-acfc-4060-9da1-afb2dd26dfca"
|
||||||
|
},
|
||||||
|
"currentNote": "创建链接.md",
|
||||||
|
"externalContextPaths": [
|
||||||
|
"E:\\my-vault\\.obsidian\\plugins\\skills\\defuddle"
|
||||||
|
],
|
||||||
|
"usage": {
|
||||||
|
"model": "kimi-k2-turbo-preview",
|
||||||
|
"inputTokens": 33034,
|
||||||
|
"cacheCreationInputTokens": 0,
|
||||||
|
"cacheReadInputTokens": 0,
|
||||||
|
"contextWindow": 200000,
|
||||||
|
"contextTokens": 33034,
|
||||||
|
"percentage": 17,
|
||||||
|
"contextWindowIsAuthoritative": true
|
||||||
|
}
|
||||||
|
}
|
||||||
1
.obsidian/app.json
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
1
.obsidian/appearance.json
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
3
.obsidian/community-plugins.json
vendored
@@ -2,5 +2,6 @@
|
|||||||
"obsidian-git",
|
"obsidian-git",
|
||||||
"copilot",
|
"copilot",
|
||||||
"obsidian42-brat",
|
"obsidian42-brat",
|
||||||
"claudian"
|
"claudian",
|
||||||
|
"obsidian-excalidraw-plugin"
|
||||||
]
|
]
|
||||||
33
.obsidian/core-plugins.json
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"file-explorer": true,
|
||||||
|
"global-search": true,
|
||||||
|
"switcher": true,
|
||||||
|
"graph": true,
|
||||||
|
"backlink": true,
|
||||||
|
"canvas": true,
|
||||||
|
"outgoing-link": true,
|
||||||
|
"tag-pane": true,
|
||||||
|
"footnotes": false,
|
||||||
|
"properties": true,
|
||||||
|
"page-preview": true,
|
||||||
|
"daily-notes": true,
|
||||||
|
"templates": true,
|
||||||
|
"note-composer": true,
|
||||||
|
"command-palette": true,
|
||||||
|
"slash-command": false,
|
||||||
|
"editor-status": true,
|
||||||
|
"bookmarks": true,
|
||||||
|
"markdown-importer": false,
|
||||||
|
"zk-prefixer": false,
|
||||||
|
"random-note": false,
|
||||||
|
"outline": true,
|
||||||
|
"word-count": true,
|
||||||
|
"slides": false,
|
||||||
|
"audio-recorder": false,
|
||||||
|
"workspaces": false,
|
||||||
|
"file-recovery": true,
|
||||||
|
"publish": false,
|
||||||
|
"sync": true,
|
||||||
|
"bases": true,
|
||||||
|
"webviewer": false
|
||||||
|
}
|
||||||
11
.obsidian/plugins/claudian/data.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"tabManagerState": {
|
||||||
|
"openTabs": [
|
||||||
|
{
|
||||||
|
"tabId": "tab-1776064705187-wgfvajr",
|
||||||
|
"conversationId": "conv-1776074120254-v83qe13hb"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"activeTabId": "tab-1776064705187-wgfvajr"
|
||||||
|
}
|
||||||
|
}
|
||||||
820
.obsidian/plugins/obsidian-excalidraw-plugin/data.json
vendored
Normal file
@@ -0,0 +1,820 @@
|
|||||||
|
{
|
||||||
|
"copyLinkToElemenetAnchorTo100": false,
|
||||||
|
"copyFrameLinkByName": false,
|
||||||
|
"disableDoubleClickTextEditing": false,
|
||||||
|
"folder": "Excalidraw",
|
||||||
|
"cropFolder": "",
|
||||||
|
"annotateFolder": "",
|
||||||
|
"embedUseExcalidrawFolder": false,
|
||||||
|
"templateFilePath": "Excalidraw/Template.excalidraw",
|
||||||
|
"scriptFolderPath": "Excalidraw/Scripts",
|
||||||
|
"fontAssetsPath": "Excalidraw/CJK Fonts",
|
||||||
|
"loadChineseFonts": false,
|
||||||
|
"loadJapaneseFonts": false,
|
||||||
|
"loadKoreanFonts": false,
|
||||||
|
"compress": true,
|
||||||
|
"decompressForMDView": false,
|
||||||
|
"onceOffCompressFlagReset": true,
|
||||||
|
"onceOffGPTVersionReset": true,
|
||||||
|
"autosave": true,
|
||||||
|
"autosaveIntervalDesktop": 60000,
|
||||||
|
"autosaveIntervalMobile": 30000,
|
||||||
|
"drawingFilenamePrefix": "Drawing ",
|
||||||
|
"drawingEmbedPrefixWithFilename": true,
|
||||||
|
"drawingFilnameEmbedPostfix": " ",
|
||||||
|
"drawingFilenameDateTime": "YYYY-MM-DD HH.mm.ss",
|
||||||
|
"useExcalidrawExtension": true,
|
||||||
|
"cropSuffix": "",
|
||||||
|
"cropPrefix": "cropped_",
|
||||||
|
"annotateSuffix": "",
|
||||||
|
"annotatePrefix": "annotated_",
|
||||||
|
"annotatePreserveSize": false,
|
||||||
|
"previewImageType": "SVGIMG",
|
||||||
|
"renderingConcurrency": 3,
|
||||||
|
"allowImageCache": true,
|
||||||
|
"allowImageCacheInScene": true,
|
||||||
|
"displayExportedImageIfAvailable": false,
|
||||||
|
"previewMatchObsidianTheme": false,
|
||||||
|
"width": "400",
|
||||||
|
"height": "",
|
||||||
|
"overrideObsidianFontSize": false,
|
||||||
|
"dynamicStyling": "colorful",
|
||||||
|
"isLeftHanded": false,
|
||||||
|
"desktopUIMode": "tray",
|
||||||
|
"tabletUIMode": "compact",
|
||||||
|
"phoneUIMode": "mobile",
|
||||||
|
"iframeMatchExcalidrawTheme": true,
|
||||||
|
"matchTheme": false,
|
||||||
|
"matchThemeAlways": false,
|
||||||
|
"matchThemeTrigger": false,
|
||||||
|
"defaultMode": "normal",
|
||||||
|
"defaultPenMode": "never",
|
||||||
|
"penModeDoubleTapEraser": true,
|
||||||
|
"penModeSingleFingerPanning": true,
|
||||||
|
"penModeCrosshairVisible": true,
|
||||||
|
"panWithRightMouseButton": false,
|
||||||
|
"renderImageInMarkdownReadingMode": false,
|
||||||
|
"renderImageInHoverPreviewForMDNotes": false,
|
||||||
|
"renderImageInMarkdownToPDF": false,
|
||||||
|
"allowPinchZoom": false,
|
||||||
|
"allowWheelZoom": false,
|
||||||
|
"zoomToFitOnOpen": true,
|
||||||
|
"zoomToFitOnResize": false,
|
||||||
|
"zoomToFitMaxLevel": 2,
|
||||||
|
"zoomStep": 0.05,
|
||||||
|
"zoomMin": 0.1,
|
||||||
|
"zoomMax": 30,
|
||||||
|
"linkPrefix": "📍",
|
||||||
|
"urlPrefix": "🌐",
|
||||||
|
"parseTODO": false,
|
||||||
|
"todo": "☐",
|
||||||
|
"done": "🗹",
|
||||||
|
"hoverPreviewWithoutCTRL": false,
|
||||||
|
"linkOpacity": 1,
|
||||||
|
"openInAdjacentPane": true,
|
||||||
|
"showSecondOrderLinks": true,
|
||||||
|
"focusOnFileTab": true,
|
||||||
|
"openInMainWorkspace": true,
|
||||||
|
"showLinkBrackets": false,
|
||||||
|
"syncElementLinkWithText": false,
|
||||||
|
"allowCtrlClick": true,
|
||||||
|
"forceWrap": false,
|
||||||
|
"pageTransclusionCharLimit": 200,
|
||||||
|
"wordWrappingDefault": 0,
|
||||||
|
"removeTransclusionQuoteSigns": true,
|
||||||
|
"iframelyAllowed": true,
|
||||||
|
"pngExportScale": 1,
|
||||||
|
"exportWithTheme": true,
|
||||||
|
"exportWithBackground": true,
|
||||||
|
"exportPaddingSVG": 10,
|
||||||
|
"exportEmbedScene": false,
|
||||||
|
"keepInSync": false,
|
||||||
|
"autoexportSVG": false,
|
||||||
|
"autoexportPNG": false,
|
||||||
|
"autoExportLightAndDark": false,
|
||||||
|
"autoexportExcalidraw": false,
|
||||||
|
"embedType": "excalidraw",
|
||||||
|
"embedMarkdownCommentLinks": true,
|
||||||
|
"embedWikiLink": true,
|
||||||
|
"syncExcalidraw": false,
|
||||||
|
"experimentalFileType": false,
|
||||||
|
"experimentalFileTag": "✏️",
|
||||||
|
"experimentalLivePreview": true,
|
||||||
|
"fadeOutExcalidrawMarkup": false,
|
||||||
|
"loadPropertySuggestions": false,
|
||||||
|
"experimentalEnableFourthFont": false,
|
||||||
|
"experimantalFourthFont": "Virgil",
|
||||||
|
"addDummyTextElement": false,
|
||||||
|
"zoteroCompatibility": false,
|
||||||
|
"fieldSuggester": true,
|
||||||
|
"compatibilityMode": false,
|
||||||
|
"drawingOpenCount": 0,
|
||||||
|
"library": "deprecated",
|
||||||
|
"library2": {
|
||||||
|
"type": "excalidrawlib",
|
||||||
|
"version": 2,
|
||||||
|
"source": "https://github.com/zsviczian/obsidian-excalidraw-plugin/releases/tag/2.22.0",
|
||||||
|
"libraryItems": []
|
||||||
|
},
|
||||||
|
"imageElementNotice": true,
|
||||||
|
"mdSVGwidth": 500,
|
||||||
|
"mdSVGmaxHeight": 800,
|
||||||
|
"mdFont": "Virgil",
|
||||||
|
"mdFontColor": "Black",
|
||||||
|
"mdBorderColor": "Black",
|
||||||
|
"mdCSS": "",
|
||||||
|
"scriptEngineSettings": {},
|
||||||
|
"previousRelease": "2.22.0",
|
||||||
|
"showReleaseNotes": true,
|
||||||
|
"compareManifestToPluginVersion": true,
|
||||||
|
"showNewVersionNotification": true,
|
||||||
|
"latexBoilerplate": "\\color{blue}",
|
||||||
|
"latexPreambleLocation": "preamble.sty",
|
||||||
|
"taskboneEnabled": false,
|
||||||
|
"taskboneAPIkey": "",
|
||||||
|
"pinnedScripts": [],
|
||||||
|
"sidepanelTabs": [],
|
||||||
|
"customPens": [
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"freedrawOnly": false,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 0,
|
||||||
|
"roughness": 0,
|
||||||
|
"penOptions": {
|
||||||
|
"highlighter": false,
|
||||||
|
"constantPressure": false,
|
||||||
|
"hasOutline": false,
|
||||||
|
"outlineWidth": 1,
|
||||||
|
"options": {
|
||||||
|
"thinning": 0.6,
|
||||||
|
"smoothing": 0.5,
|
||||||
|
"streamline": 0.5,
|
||||||
|
"easing": "easeOutSine",
|
||||||
|
"start": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": 0,
|
||||||
|
"easing": "linear"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": 0,
|
||||||
|
"easing": "linear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "highlighter",
|
||||||
|
"freedrawOnly": true,
|
||||||
|
"strokeColor": "#FFC47C",
|
||||||
|
"backgroundColor": "#FFC47C",
|
||||||
|
"fillStyle": "solid",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"roughness": null,
|
||||||
|
"penOptions": {
|
||||||
|
"highlighter": true,
|
||||||
|
"constantPressure": true,
|
||||||
|
"hasOutline": true,
|
||||||
|
"outlineWidth": 4,
|
||||||
|
"options": {
|
||||||
|
"thinning": 1,
|
||||||
|
"smoothing": 0.5,
|
||||||
|
"streamline": 0.5,
|
||||||
|
"easing": "linear",
|
||||||
|
"start": {
|
||||||
|
"taper": 0,
|
||||||
|
"cap": true,
|
||||||
|
"easing": "linear"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"taper": 0,
|
||||||
|
"cap": true,
|
||||||
|
"easing": "linear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "finetip",
|
||||||
|
"freedrawOnly": false,
|
||||||
|
"strokeColor": "#3E6F8D",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 0.5,
|
||||||
|
"roughness": 0,
|
||||||
|
"penOptions": {
|
||||||
|
"highlighter": false,
|
||||||
|
"hasOutline": false,
|
||||||
|
"outlineWidth": 1,
|
||||||
|
"constantPressure": true,
|
||||||
|
"options": {
|
||||||
|
"smoothing": 0.4,
|
||||||
|
"thinning": -0.5,
|
||||||
|
"streamline": 0.4,
|
||||||
|
"easing": "linear",
|
||||||
|
"start": {
|
||||||
|
"taper": 5,
|
||||||
|
"cap": false,
|
||||||
|
"easing": "linear"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"taper": 5,
|
||||||
|
"cap": false,
|
||||||
|
"easing": "linear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "fountain",
|
||||||
|
"freedrawOnly": false,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"roughness": 0,
|
||||||
|
"penOptions": {
|
||||||
|
"highlighter": false,
|
||||||
|
"constantPressure": false,
|
||||||
|
"hasOutline": false,
|
||||||
|
"outlineWidth": 1,
|
||||||
|
"options": {
|
||||||
|
"smoothing": 0.2,
|
||||||
|
"thinning": 0.6,
|
||||||
|
"streamline": 0.2,
|
||||||
|
"easing": "easeInOutSine",
|
||||||
|
"start": {
|
||||||
|
"taper": 150,
|
||||||
|
"cap": true,
|
||||||
|
"easing": "linear"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"taper": 1,
|
||||||
|
"cap": true,
|
||||||
|
"easing": "linear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "marker",
|
||||||
|
"freedrawOnly": true,
|
||||||
|
"strokeColor": "#B83E3E",
|
||||||
|
"backgroundColor": "#FF7C7C",
|
||||||
|
"fillStyle": "dashed",
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"roughness": 3,
|
||||||
|
"penOptions": {
|
||||||
|
"highlighter": false,
|
||||||
|
"constantPressure": true,
|
||||||
|
"hasOutline": true,
|
||||||
|
"outlineWidth": 4,
|
||||||
|
"options": {
|
||||||
|
"thinning": 1,
|
||||||
|
"smoothing": 0.5,
|
||||||
|
"streamline": 0.5,
|
||||||
|
"easing": "linear",
|
||||||
|
"start": {
|
||||||
|
"taper": 0,
|
||||||
|
"cap": true,
|
||||||
|
"easing": "linear"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"taper": 0,
|
||||||
|
"cap": true,
|
||||||
|
"easing": "linear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "thick-thin",
|
||||||
|
"freedrawOnly": true,
|
||||||
|
"strokeColor": "#CECDCC",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 0,
|
||||||
|
"roughness": null,
|
||||||
|
"penOptions": {
|
||||||
|
"highlighter": true,
|
||||||
|
"constantPressure": true,
|
||||||
|
"hasOutline": false,
|
||||||
|
"outlineWidth": 1,
|
||||||
|
"options": {
|
||||||
|
"thinning": 1,
|
||||||
|
"smoothing": 0.5,
|
||||||
|
"streamline": 0.5,
|
||||||
|
"easing": "linear",
|
||||||
|
"start": {
|
||||||
|
"taper": 0,
|
||||||
|
"cap": true,
|
||||||
|
"easing": "linear"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": true,
|
||||||
|
"easing": "linear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "thin-thick-thin",
|
||||||
|
"freedrawOnly": true,
|
||||||
|
"strokeColor": "#CECDCC",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 0,
|
||||||
|
"roughness": null,
|
||||||
|
"penOptions": {
|
||||||
|
"highlighter": true,
|
||||||
|
"constantPressure": true,
|
||||||
|
"hasOutline": false,
|
||||||
|
"outlineWidth": 1,
|
||||||
|
"options": {
|
||||||
|
"thinning": 1,
|
||||||
|
"smoothing": 0.5,
|
||||||
|
"streamline": 0.5,
|
||||||
|
"easing": "linear",
|
||||||
|
"start": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": true,
|
||||||
|
"easing": "linear"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": true,
|
||||||
|
"easing": "linear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"freedrawOnly": false,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 0,
|
||||||
|
"roughness": 0,
|
||||||
|
"penOptions": {
|
||||||
|
"highlighter": false,
|
||||||
|
"constantPressure": false,
|
||||||
|
"hasOutline": false,
|
||||||
|
"outlineWidth": 1,
|
||||||
|
"options": {
|
||||||
|
"thinning": 0.6,
|
||||||
|
"smoothing": 0.5,
|
||||||
|
"streamline": 0.5,
|
||||||
|
"easing": "easeOutSine",
|
||||||
|
"start": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": 0,
|
||||||
|
"easing": "linear"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": 0,
|
||||||
|
"easing": "linear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"freedrawOnly": false,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 0,
|
||||||
|
"roughness": 0,
|
||||||
|
"penOptions": {
|
||||||
|
"highlighter": false,
|
||||||
|
"constantPressure": false,
|
||||||
|
"hasOutline": false,
|
||||||
|
"outlineWidth": 1,
|
||||||
|
"options": {
|
||||||
|
"thinning": 0.6,
|
||||||
|
"smoothing": 0.5,
|
||||||
|
"streamline": 0.5,
|
||||||
|
"easing": "easeOutSine",
|
||||||
|
"start": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": 0,
|
||||||
|
"easing": "linear"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": 0,
|
||||||
|
"easing": "linear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "default",
|
||||||
|
"freedrawOnly": false,
|
||||||
|
"strokeColor": "#000000",
|
||||||
|
"backgroundColor": "transparent",
|
||||||
|
"fillStyle": "hachure",
|
||||||
|
"strokeWidth": 0,
|
||||||
|
"roughness": 0,
|
||||||
|
"penOptions": {
|
||||||
|
"highlighter": false,
|
||||||
|
"constantPressure": false,
|
||||||
|
"hasOutline": false,
|
||||||
|
"outlineWidth": 1,
|
||||||
|
"options": {
|
||||||
|
"thinning": 0.6,
|
||||||
|
"smoothing": 0.5,
|
||||||
|
"streamline": 0.5,
|
||||||
|
"easing": "easeOutSine",
|
||||||
|
"start": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": 0,
|
||||||
|
"easing": "linear"
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"cap": true,
|
||||||
|
"taper": 0,
|
||||||
|
"easing": "linear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"numberOfCustomPens": 0,
|
||||||
|
"pdfScale": 4,
|
||||||
|
"pdfBorderBox": true,
|
||||||
|
"pdfFrame": false,
|
||||||
|
"pdfGapSize": 20,
|
||||||
|
"pdfGroupPages": false,
|
||||||
|
"pdfLockAfterImport": true,
|
||||||
|
"pdfNumColumns": 1,
|
||||||
|
"pdfNumRows": 1,
|
||||||
|
"pdfDirection": "right",
|
||||||
|
"pdfImportScale": 0.3,
|
||||||
|
"gridSettings": {
|
||||||
|
"DYNAMIC_COLOR": true,
|
||||||
|
"COLOR": "#000000",
|
||||||
|
"OPACITY": 50,
|
||||||
|
"GRID_DIRECTION": {
|
||||||
|
"horizontal": true,
|
||||||
|
"vertical": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"laserSettings": {
|
||||||
|
"DECAY_LENGTH": 50,
|
||||||
|
"DECAY_TIME": 1000,
|
||||||
|
"COLOR": "#ff0000"
|
||||||
|
},
|
||||||
|
"embeddableMarkdownDefaults": {
|
||||||
|
"useObsidianDefaults": false,
|
||||||
|
"backgroundMatchCanvas": false,
|
||||||
|
"backgroundMatchElement": true,
|
||||||
|
"backgroundColor": "#fff",
|
||||||
|
"backgroundOpacity": 60,
|
||||||
|
"borderMatchElement": true,
|
||||||
|
"borderColor": "#fff",
|
||||||
|
"borderOpacity": 0,
|
||||||
|
"filenameVisible": false
|
||||||
|
},
|
||||||
|
"markdownNodeOneClickEditing": false,
|
||||||
|
"canvasImmersiveEmbed": true,
|
||||||
|
"startupScriptPath": "",
|
||||||
|
"aiEnabled": true,
|
||||||
|
"openAIAPIToken": "",
|
||||||
|
"openAIDefaultTextModel": "gpt-5-mini",
|
||||||
|
"openAIDefaultTextModelMaxTokens": 4096,
|
||||||
|
"openAIDefaultVisionModel": "gpt-5-mini",
|
||||||
|
"openAIDefaultImageGenerationModel": "gpt-image-1",
|
||||||
|
"openAIURL": "https://api.openai.com/v1/chat/completions",
|
||||||
|
"openAIImageGenerationURL": "https://api.openai.com/v1/images/generations",
|
||||||
|
"openAIImageEditsURL": "https://api.openai.com/v1/images/edits",
|
||||||
|
"openAIImageVariationURL": "https://api.openai.com/v1/images/variations",
|
||||||
|
"modifierKeyConfig": {
|
||||||
|
"Mac": {
|
||||||
|
"LocalFileDragAction": {
|
||||||
|
"defaultAction": "image-import",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image-import"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": true,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image-url"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": true,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "embeddable"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"WebBrowserDragAction": {
|
||||||
|
"defaultAction": "image-url",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image-url"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": true,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": true,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "embeddable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image-import"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"InternalDragAction": {
|
||||||
|
"defaultAction": "link",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": true,
|
||||||
|
"result": "embeddable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": true,
|
||||||
|
"result": "image-fullsize"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LinkClickAction": {
|
||||||
|
"defaultAction": "new-tab",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "active-pane"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "new-tab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": true,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "new-pane"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": true,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "popout-window"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": true,
|
||||||
|
"result": "md-properties"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Win": {
|
||||||
|
"LocalFileDragAction": {
|
||||||
|
"defaultAction": "image-import",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image-import"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image-url"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "embeddable"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"WebBrowserDragAction": {
|
||||||
|
"defaultAction": "image-url",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image-url"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "embeddable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image-import"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"InternalDragAction": {
|
||||||
|
"defaultAction": "link",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "embeddable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": true,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "image-fullsize"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"LinkClickAction": {
|
||||||
|
"defaultAction": "new-tab",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": false,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "active-pane"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "new-tab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": true,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "new-pane"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": true,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": true,
|
||||||
|
"meta_ctrl": false,
|
||||||
|
"result": "popout-window"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shift": false,
|
||||||
|
"ctrl_cmd": true,
|
||||||
|
"alt_opt": false,
|
||||||
|
"meta_ctrl": true,
|
||||||
|
"result": "md-properties"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"slidingPanesSupport": false,
|
||||||
|
"areaZoomLimit": 1,
|
||||||
|
"longPressDesktop": 500,
|
||||||
|
"longPressMobile": 500,
|
||||||
|
"doubleClickLinkOpenViewMode": true,
|
||||||
|
"isDebugMode": false,
|
||||||
|
"rank": "Bronze",
|
||||||
|
"modifierKeyOverrides": [
|
||||||
|
{
|
||||||
|
"modifiers": [
|
||||||
|
"Mod"
|
||||||
|
],
|
||||||
|
"key": "Enter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"modifiers": [
|
||||||
|
"Mod"
|
||||||
|
],
|
||||||
|
"key": "k"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"modifiers": [
|
||||||
|
"Mod"
|
||||||
|
],
|
||||||
|
"key": "G"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"showSplashscreen": true,
|
||||||
|
"pdfSettings": {
|
||||||
|
"pageSize": "A4",
|
||||||
|
"pageOrientation": "portrait",
|
||||||
|
"fitToPage": 1,
|
||||||
|
"paperColor": "white",
|
||||||
|
"customPaperColor": "#ffffff",
|
||||||
|
"alignment": "center",
|
||||||
|
"margin": "normal"
|
||||||
|
},
|
||||||
|
"disableContextMenu": false
|
||||||
|
}
|
||||||
10
.obsidian/plugins/obsidian-excalidraw-plugin/main.js
vendored
Normal file
12
.obsidian/plugins/obsidian-excalidraw-plugin/manifest.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"id": "obsidian-excalidraw-plugin",
|
||||||
|
"name": "Excalidraw",
|
||||||
|
"version": "2.22.0",
|
||||||
|
"minAppVersion": "1.5.7",
|
||||||
|
"description": "Sketch Your Mind. An Obsidian plugin to edit and view Excalidraw drawings. Enter the world of 4D Visual PKM.",
|
||||||
|
"author": "Zsolt Viczian",
|
||||||
|
"authorUrl": "https://excalidraw-obsidian.online",
|
||||||
|
"fundingUrl": "https://ko-fi.com/zsolt",
|
||||||
|
"helpUrl": "https://github.com/zsviczian/obsidian-excalidraw-plugin#readme",
|
||||||
|
"isDesktopOnly": false
|
||||||
|
}
|
||||||
1
.obsidian/plugins/obsidian-excalidraw-plugin/styles.css
vendored
Normal file
68
.obsidian/plugins/obsidian-git/data.json
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"commitMessage": "vault backup: {{date}}",
|
||||||
|
"autoCommitMessage": "vault backup: {{date}}",
|
||||||
|
"commitMessageScript": "",
|
||||||
|
"commitDateFormat": "YYYY-MM-DD HH:mm:ss",
|
||||||
|
"autoSaveInterval": 10,
|
||||||
|
"autoPushInterval": 0,
|
||||||
|
"autoPullInterval": 5,
|
||||||
|
"autoPullOnBoot": true,
|
||||||
|
"autoCommitOnlyStaged": false,
|
||||||
|
"disablePush": false,
|
||||||
|
"pullBeforePush": true,
|
||||||
|
"disablePopups": true,
|
||||||
|
"showErrorNotices": true,
|
||||||
|
"disablePopupsForNoChanges": false,
|
||||||
|
"listChangedFilesInMessageBody": false,
|
||||||
|
"showStatusBar": true,
|
||||||
|
"updateSubmodules": false,
|
||||||
|
"syncMethod": "merge",
|
||||||
|
"mergeStrategy": "none",
|
||||||
|
"customMessageOnAutoBackup": false,
|
||||||
|
"autoBackupAfterFileChange": true,
|
||||||
|
"treeStructure": false,
|
||||||
|
"refreshSourceControl": true,
|
||||||
|
"basePath": "",
|
||||||
|
"differentIntervalCommitAndPush": false,
|
||||||
|
"changedFilesInStatusBar": false,
|
||||||
|
"showedMobileNotice": true,
|
||||||
|
"refreshSourceControlTimer": 7000,
|
||||||
|
"showBranchStatusBar": true,
|
||||||
|
"setLastSaveToLastCommit": false,
|
||||||
|
"submoduleRecurseCheckout": false,
|
||||||
|
"gitDir": "",
|
||||||
|
"showFileMenu": true,
|
||||||
|
"authorInHistoryView": "hide",
|
||||||
|
"dateInHistoryView": false,
|
||||||
|
"diffStyle": "split",
|
||||||
|
"hunks": {
|
||||||
|
"showSigns": false,
|
||||||
|
"hunkCommands": false,
|
||||||
|
"statusBar": "disabled"
|
||||||
|
},
|
||||||
|
"lineAuthor": {
|
||||||
|
"show": false,
|
||||||
|
"followMovement": "inactive",
|
||||||
|
"authorDisplay": "initials",
|
||||||
|
"showCommitHash": false,
|
||||||
|
"dateTimeFormatOptions": "date",
|
||||||
|
"dateTimeFormatCustomString": "YYYY-MM-DD HH:mm",
|
||||||
|
"dateTimeTimezone": "viewer-local",
|
||||||
|
"coloringMaxAge": "1y",
|
||||||
|
"colorNew": {
|
||||||
|
"r": 255,
|
||||||
|
"g": 150,
|
||||||
|
"b": 150
|
||||||
|
},
|
||||||
|
"colorOld": {
|
||||||
|
"r": 120,
|
||||||
|
"g": 160,
|
||||||
|
"b": 255
|
||||||
|
},
|
||||||
|
"textColorCss": "var(--text-muted)",
|
||||||
|
"ignoreWhitespace": false,
|
||||||
|
"gutterSpacingFallbackLength": 5,
|
||||||
|
"lastShownAuthorDisplay": "initials",
|
||||||
|
"lastShownDateTimeFormatOptions": "date"
|
||||||
|
}
|
||||||
|
}
|
||||||
452
.obsidian/plugins/obsidian-git/main.js
vendored
Normal file
10
.obsidian/plugins/obsidian-git/manifest.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"author": "Vinzent",
|
||||||
|
"authorUrl": "https://github.com/Vinzent03",
|
||||||
|
"id": "obsidian-git",
|
||||||
|
"name": "Git",
|
||||||
|
"description": "Integrate Git version control with automatic backup and other advanced features.",
|
||||||
|
"isDesktopOnly": false,
|
||||||
|
"fundingUrl": "https://ko-fi.com/vinzent",
|
||||||
|
"version": "2.38.1"
|
||||||
|
}
|
||||||
710
.obsidian/plugins/obsidian-git/styles.css
vendored
Normal file
@@ -0,0 +1,710 @@
|
|||||||
|
@keyframes loading {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-signs-gutter {
|
||||||
|
.cm-gutterElement {
|
||||||
|
/* Needed to align the sign properly for different line heigts. Such as
|
||||||
|
* when having a heading or list item.
|
||||||
|
*/
|
||||||
|
padding-top: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-leaf-content[data-type="git-view"] .button-border {
|
||||||
|
border: 2px solid var(--interactive-accent);
|
||||||
|
border-radius: var(--radius-s);
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-leaf-content[data-type="git-view"] .view-content {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-leaf-content[data-type="git-history-view"] .view-content {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading > svg {
|
||||||
|
animation: 2s linear infinite loading;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.obsidian-git-center {
|
||||||
|
margin: auto;
|
||||||
|
text-align: center;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.obsidian-git-textarea {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.obsidian-git-disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.obsidian-git-center-button {
|
||||||
|
display: block;
|
||||||
|
margin: 20px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip.mod-left {
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip.mod-right {
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Limits the scrollbar to the view body */
|
||||||
|
.git-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Re-enable wrapping of nav buttns to prevent overflow on smaller screens #*/
|
||||||
|
.workspace-drawer .git-view .nav-buttons-container {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-tools {
|
||||||
|
display: flex;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
.git-tools .type {
|
||||||
|
padding-left: var(--size-2-1);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-tools .type[data-type="M"] {
|
||||||
|
color: orange;
|
||||||
|
}
|
||||||
|
.git-tools .type[data-type="D"] {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
.git-tools .buttons {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.git-tools .buttons > * {
|
||||||
|
padding: 0 0;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-leaf-content[data-type="git-view"] .tree-item-self,
|
||||||
|
.workspace-leaf-content[data-type="git-history-view"] .tree-item-self {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.workspace-leaf-content[data-type="git-view"]
|
||||||
|
.tree-item-self:hover
|
||||||
|
.clickable-icon,
|
||||||
|
.workspace-leaf-content[data-type="git-history-view"]
|
||||||
|
.tree-item-self:hover
|
||||||
|
.clickable-icon {
|
||||||
|
color: var(--icon-color-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Highlight an item as active if it's diff is currently opened */
|
||||||
|
.is-active .git-tools .buttons > * {
|
||||||
|
color: var(--nav-item-color-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-author {
|
||||||
|
color: var(--text-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-date {
|
||||||
|
color: var(--text-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-ref {
|
||||||
|
color: var(--text-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====== diff2html ======
|
||||||
|
The following styles are adapted from the obsidian-version-history plugin by
|
||||||
|
@kometenstaub https://github.com/kometenstaub/obsidian-version-history-diff/blob/main/src/styles.scss
|
||||||
|
which itself is adapted from the diff2html library with the following original license:
|
||||||
|
|
||||||
|
https://github.com/rtfpessoa/diff2html/blob/master/LICENSE.md
|
||||||
|
|
||||||
|
Copyright 2014-2016 Rodrigo Fernandes https://rtfpessoa.github.io/
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
|
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
|
||||||
|
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||||
|
persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
|
||||||
|
Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||||
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.theme-dark,
|
||||||
|
.theme-light {
|
||||||
|
--git-delete-bg: #ff475040;
|
||||||
|
--git-delete-hl: #96050a75;
|
||||||
|
--git-insert-bg: #68d36840;
|
||||||
|
--git-insert-hl: #23c02350;
|
||||||
|
--git-change-bg: #ffd55840;
|
||||||
|
--git-selected: #3572b0;
|
||||||
|
|
||||||
|
--git-delete: #c33;
|
||||||
|
--git-insert: #399839;
|
||||||
|
--git-change: #d0b44c;
|
||||||
|
--git-move: #3572b0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-diff {
|
||||||
|
.d2h-d-none {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.d2h-wrapper {
|
||||||
|
text-align: left;
|
||||||
|
border-radius: 0.25em;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.d2h-file-header.d2h-file-header {
|
||||||
|
background-color: var(--background-secondary);
|
||||||
|
border-bottom: 1px solid var(--background-modifier-border);
|
||||||
|
font-family:
|
||||||
|
Source Sans Pro,
|
||||||
|
Helvetica Neue,
|
||||||
|
Helvetica,
|
||||||
|
Arial,
|
||||||
|
sans-serif;
|
||||||
|
height: 35px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
.d2h-file-header,
|
||||||
|
.d2h-file-stats {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.d2h-file-header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.d2h-file-stats {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
.d2h-lines-added {
|
||||||
|
border: 1px solid var(--color-green);
|
||||||
|
border-radius: 5px 0 0 5px;
|
||||||
|
color: var(--color-green);
|
||||||
|
padding: 2px;
|
||||||
|
text-align: right;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.d2h-lines-deleted {
|
||||||
|
border: 1px solid var(--color-red);
|
||||||
|
border-radius: 0 5px 5px 0;
|
||||||
|
color: var(--color-red);
|
||||||
|
margin-left: 1px;
|
||||||
|
padding: 2px;
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.d2h-file-name-wrapper {
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
font-size: 15px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.d2h-file-name {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: var(--text-normal);
|
||||||
|
font-size: var(--h5-size);
|
||||||
|
}
|
||||||
|
.d2h-file-wrapper {
|
||||||
|
border: 1px solid var(--background-secondary-alt);
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
.d2h-file-collapse {
|
||||||
|
-webkit-box-pack: end;
|
||||||
|
-ms-flex-pack: end;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid var(--background-secondary-alt);
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: none;
|
||||||
|
font-size: 12px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
.d2h-file-collapse.d2h-selected {
|
||||||
|
background-color: var(--git-selected);
|
||||||
|
}
|
||||||
|
.d2h-file-collapse-input {
|
||||||
|
margin: 0 4px 0 0;
|
||||||
|
}
|
||||||
|
.d2h-diff-table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-family: var(--font-monospace);
|
||||||
|
font-size: var(--code-size);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.d2h-files-diff {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.d2h-file-diff {
|
||||||
|
/*
|
||||||
|
overflow-y: scroll;
|
||||||
|
*/
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: var(--font-text-size);
|
||||||
|
line-height: var(--line-height-normal);
|
||||||
|
}
|
||||||
|
.d2h-file-side-diff {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: -8px;
|
||||||
|
margin-right: -4px;
|
||||||
|
overflow-x: scroll;
|
||||||
|
overflow-y: hidden;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
.d2h-code-line {
|
||||||
|
padding-left: 6em;
|
||||||
|
padding-right: 1.5em;
|
||||||
|
}
|
||||||
|
.d2h-code-line,
|
||||||
|
.d2h-code-side-line {
|
||||||
|
display: inline-block;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.d2h-code-side-line {
|
||||||
|
/* needed to be changed */
|
||||||
|
padding-left: 0.5em;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
.d2h-code-line-ctn {
|
||||||
|
word-wrap: normal;
|
||||||
|
background: none;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0;
|
||||||
|
-webkit-user-select: text;
|
||||||
|
-moz-user-select: text;
|
||||||
|
-ms-user-select: text;
|
||||||
|
user-select: text;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 100%;
|
||||||
|
/* only works for line-by-line */
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
.d2h-code-line del,
|
||||||
|
.d2h-code-side-line del {
|
||||||
|
background-color: var(--git-delete-hl);
|
||||||
|
color: var(--text-normal);
|
||||||
|
}
|
||||||
|
.d2h-code-line del,
|
||||||
|
.d2h-code-line ins,
|
||||||
|
.d2h-code-side-line del,
|
||||||
|
.d2h-code-side-line ins {
|
||||||
|
border-radius: 0.2em;
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: -1px;
|
||||||
|
text-decoration: none;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.d2h-code-line ins,
|
||||||
|
.d2h-code-side-line ins {
|
||||||
|
background-color: var(--git-insert-hl);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.d2h-code-line-prefix {
|
||||||
|
word-wrap: normal;
|
||||||
|
background: none;
|
||||||
|
display: inline;
|
||||||
|
padding: 0;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
.line-num1 {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.line-num1,
|
||||||
|
.line-num2 {
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
/*
|
||||||
|
padding: 0 0.5em;
|
||||||
|
*/
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 2.5em;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
.line-num2 {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.d2h-code-linenumber {
|
||||||
|
background-color: var(--background-primary);
|
||||||
|
border: solid var(--background-modifier-border);
|
||||||
|
border-width: 0 1px;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: var(--text-faint);
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
text-align: right;
|
||||||
|
width: 5.5em;
|
||||||
|
}
|
||||||
|
.d2h-code-linenumber:after {
|
||||||
|
content: "\200b";
|
||||||
|
}
|
||||||
|
.d2h-code-side-linenumber {
|
||||||
|
background-color: var(--background-primary);
|
||||||
|
border: solid var(--background-modifier-border);
|
||||||
|
border-width: 0 1px;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: var(--text-faint);
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0 0.5em;
|
||||||
|
text-align: right;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 4em;
|
||||||
|
/* needed to be changed */
|
||||||
|
display: table-cell;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.d2h-code-side-linenumber:after {
|
||||||
|
content: "\200b";
|
||||||
|
}
|
||||||
|
.d2h-code-side-emptyplaceholder,
|
||||||
|
.d2h-emptyplaceholder {
|
||||||
|
background-color: var(--background-primary);
|
||||||
|
border-color: var(--background-modifier-border);
|
||||||
|
}
|
||||||
|
.d2h-code-line-prefix,
|
||||||
|
.d2h-code-linenumber,
|
||||||
|
.d2h-code-side-linenumber,
|
||||||
|
.d2h-emptyplaceholder {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.d2h-code-linenumber,
|
||||||
|
.d2h-code-side-linenumber {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
.d2h-del {
|
||||||
|
background-color: var(--git-delete-bg);
|
||||||
|
border-color: var(--git-delete-hl);
|
||||||
|
}
|
||||||
|
.d2h-ins {
|
||||||
|
background-color: var(--git-insert-bg);
|
||||||
|
border-color: var(--git-insert-hl);
|
||||||
|
}
|
||||||
|
.d2h-info {
|
||||||
|
background-color: var(--background-primary);
|
||||||
|
border-color: var(--background-modifier-border);
|
||||||
|
color: var(--text-faint);
|
||||||
|
}
|
||||||
|
.d2h-del,
|
||||||
|
.d2h-ins,
|
||||||
|
.d2h-file-diff .d2h-change {
|
||||||
|
color: var(--text-normal);
|
||||||
|
}
|
||||||
|
.d2h-file-diff .d2h-del.d2h-change {
|
||||||
|
background-color: var(--git-change-bg);
|
||||||
|
}
|
||||||
|
.d2h-file-diff .d2h-ins.d2h-change {
|
||||||
|
background-color: var(--git-insert-bg);
|
||||||
|
}
|
||||||
|
.d2h-file-list-wrapper {
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: default;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.d2h-file-list-header {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.d2h-file-list-title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.d2h-file-list-line {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.d2h-file-list {
|
||||||
|
}
|
||||||
|
.d2h-file-list > li {
|
||||||
|
border-bottom: 1px solid var(--background-modifier-border);
|
||||||
|
margin: 0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
.d2h-file-list > li:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.d2h-file-switch {
|
||||||
|
cursor: pointer;
|
||||||
|
display: none;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
.d2h-icon {
|
||||||
|
fill: currentColor;
|
||||||
|
margin-right: 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.d2h-deleted {
|
||||||
|
color: var(--git-delete);
|
||||||
|
}
|
||||||
|
.d2h-added {
|
||||||
|
color: var(--git-insert);
|
||||||
|
}
|
||||||
|
.d2h-changed {
|
||||||
|
color: var(--git-change);
|
||||||
|
}
|
||||||
|
.d2h-moved {
|
||||||
|
color: var(--git-move);
|
||||||
|
}
|
||||||
|
.d2h-tag {
|
||||||
|
background-color: var(--background-secondary);
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
font-size: 10px;
|
||||||
|
margin-left: 5px;
|
||||||
|
padding: 0 2px;
|
||||||
|
}
|
||||||
|
.d2h-deleted-tag {
|
||||||
|
border: 1px solid var(--git-delete);
|
||||||
|
}
|
||||||
|
.d2h-added-tag {
|
||||||
|
border: 1px solid var(--git-insert);
|
||||||
|
}
|
||||||
|
.d2h-changed-tag {
|
||||||
|
border: 1px solid var(--git-change);
|
||||||
|
}
|
||||||
|
.d2h-moved-tag {
|
||||||
|
border: 1px solid var(--git-move);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* needed for line-by-line*/
|
||||||
|
|
||||||
|
.d2h-diff-tbody {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ====================== Line Authoring Information ====================== */
|
||||||
|
|
||||||
|
.cm-gutterElement.obs-git-blame-gutter {
|
||||||
|
/* Add background color to spacing inbetween and around the gutter for better aesthetics */
|
||||||
|
border-width: 0px 2px 0.2px 2px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: var(--background-secondary);
|
||||||
|
background-color: var(--background-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-gutterElement.obs-git-blame-gutter > div,
|
||||||
|
.line-author-settings-preview {
|
||||||
|
/* delegate text color to settings */
|
||||||
|
color: var(--obs-git-gutter-text);
|
||||||
|
font-family: monospace;
|
||||||
|
height: 100%; /* ensure, that age-based background color occupies entire parent */
|
||||||
|
text-align: right;
|
||||||
|
padding: 0px 6px 0px 6px;
|
||||||
|
white-space: pre; /* Keep spaces and do not collapse them. */
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
/* hide git blame gutter not to superpose text */
|
||||||
|
.cm-gutterElement.obs-git-blame-gutter {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-unified-diff-view,
|
||||||
|
.git-split-diff-view .cm-deletedLine .cm-changedText {
|
||||||
|
background-color: #ee443330;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-unified-diff-view,
|
||||||
|
.git-split-diff-view .cm-insertedLine .cm-changedText {
|
||||||
|
background-color: #22bb2230;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-obscure-prompt[git-is-obscured="true"] #git-show-password:after {
|
||||||
|
-webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-eye"><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"></path><circle cx="12" cy="12" r="3"></circle></svg>');
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-obscure-prompt[git-is-obscured="false"] #git-show-password:after {
|
||||||
|
-webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="svg-icon lucide-eye-off"><path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"></path><path d="M14.084 14.158a3 3 0 0 1-4.242-4.242"></path><path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"></path><path d="m2 2 20 20"></path></svg>');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Override styling of Codemirror merge view "collapsed lines" indicator */
|
||||||
|
.git-split-diff-view .ͼ2 .cm-collapsedLines {
|
||||||
|
background: var(--interactive-normal);
|
||||||
|
border-radius: var(--radius-m);
|
||||||
|
color: var(--text-accent);
|
||||||
|
font-size: var(--font-small);
|
||||||
|
padding: var(--size-4-1) var(--size-4-1);
|
||||||
|
}
|
||||||
|
.git-split-diff-view .ͼ2 .cm-collapsedLines:hover {
|
||||||
|
background: var(--interactive-hover);
|
||||||
|
color: var(--text-accent-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-signs-gutter {
|
||||||
|
.cm-gutterElement {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-gutter-marker:hover {
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-gutter-marker.git-add {
|
||||||
|
background-color: var(--color-green);
|
||||||
|
justify-self: center;
|
||||||
|
height: inherit;
|
||||||
|
width: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-gutter-marker.git-change {
|
||||||
|
background-color: var(--color-yellow);
|
||||||
|
justify-self: center;
|
||||||
|
height: inherit;
|
||||||
|
width: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-gutter-marker.git-changedelete {
|
||||||
|
color: var(--color-yellow);
|
||||||
|
font-weight: var(--font-bold);
|
||||||
|
font-size: 1rem;
|
||||||
|
justify-self: center;
|
||||||
|
height: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-gutter-marker.git-delete {
|
||||||
|
background-color: var(--color-red);
|
||||||
|
height: 0.2rem;
|
||||||
|
width: 0.8rem;
|
||||||
|
align-self: end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-gutter-marker.git-topdelete {
|
||||||
|
background-color: var(--color-red);
|
||||||
|
height: 0.2rem;
|
||||||
|
width: 0.8rem;
|
||||||
|
align-self: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:hover > .git-gutter-marker.git-change {
|
||||||
|
width: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:hover > .git-gutter-marker.git-add {
|
||||||
|
width: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:hover > .git-gutter-marker.git-delete {
|
||||||
|
height: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:hover > .git-gutter-marker.git-topdelete {
|
||||||
|
height: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
div:hover > .git-gutter-marker.git-changedelete {
|
||||||
|
font-weight: var(--font-bold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-gutter-marker.staged {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-diff {
|
||||||
|
.cm-merge-revert {
|
||||||
|
width: 4em;
|
||||||
|
}
|
||||||
|
/* Ensure that merge revert markers are positioned correctly */
|
||||||
|
.cm-merge-revert > * {
|
||||||
|
position: absolute;
|
||||||
|
background-color: var(--background-secondary);
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prevent shifting of the editor when git signs gutter is the only gutter present */
|
||||||
|
.cm-gutters.cm-gutters-before:has(> .git-signs-gutter:only-child) {
|
||||||
|
margin-inline-end: 0;
|
||||||
|
.git-signs-gutter {
|
||||||
|
margin-inline-start: -1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-changes-status-bar-colored {
|
||||||
|
.git-add {
|
||||||
|
color: var(--color-green);
|
||||||
|
}
|
||||||
|
.git-change {
|
||||||
|
color: var(--color-yellow);
|
||||||
|
}
|
||||||
|
.git-delete {
|
||||||
|
color: var(--color-red);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-changes-status-bar .git-add {
|
||||||
|
margin-right: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.git-changes-status-bar .git-change {
|
||||||
|
margin-right: 0.3em;
|
||||||
|
}
|
||||||
1
.obsidian/plugins/skills/academic-research-skills
vendored
Submodule
41
.obsidian/plugins/skills/defuddle/SKILL.md
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
name: defuddle
|
||||||
|
description: Extract clean markdown content from web pages using Defuddle CLI, removing clutter and navigation to save tokens. Use instead of WebFetch when the user provides a URL to read or analyze, for online documentation, articles, blog posts, or any standard web page. Do NOT use for URLs ending in .md — those are already markdown, use WebFetch directly.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Defuddle
|
||||||
|
|
||||||
|
Use Defuddle CLI to extract clean readable content from web pages. Prefer over WebFetch for standard web pages — it removes navigation, ads, and clutter, reducing token usage.
|
||||||
|
|
||||||
|
If not installed: `npm install -g defuddle`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Always use `--md` for markdown output:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
defuddle parse <url> --md
|
||||||
|
```
|
||||||
|
|
||||||
|
Save to file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
defuddle parse <url> --md -o content.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Extract specific metadata:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
defuddle parse <url> -p title
|
||||||
|
defuddle parse <url> -p description
|
||||||
|
defuddle parse <url> -p domain
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output formats
|
||||||
|
|
||||||
|
| Flag | Format |
|
||||||
|
|------|--------|
|
||||||
|
| `--md` | Markdown (default choice) |
|
||||||
|
| `--json` | JSON with both HTML and markdown |
|
||||||
|
| (none) | HTML |
|
||||||
|
| `-p <name>` | Specific metadata property |
|
||||||
497
.obsidian/plugins/skills/obsidian-bases/SKILL.md
vendored
Normal file
@@ -0,0 +1,497 @@
|
|||||||
|
---
|
||||||
|
name: obsidian-bases
|
||||||
|
description: Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with .base files, creating database-like views of notes, or when the user mentions Bases, table views, card views, filters, or formulas in Obsidian.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Obsidian Bases Skill
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. **Create the file**: Create a `.base` file in the vault with valid YAML content
|
||||||
|
2. **Define scope**: Add `filters` to select which notes appear (by tag, folder, property, or date)
|
||||||
|
3. **Add formulas** (optional): Define computed properties in the `formulas` section
|
||||||
|
4. **Configure views**: Add one or more views (`table`, `cards`, `list`, or `map`) with `order` specifying which properties to display
|
||||||
|
5. **Validate**: Verify the file is valid YAML with no syntax errors. Check that all referenced properties and formulas exist. Common issues: unquoted strings containing special YAML characters, mismatched quotes in formula expressions, referencing `formula.X` without defining `X` in `formulas`
|
||||||
|
6. **Test in Obsidian**: Open the `.base` file in Obsidian to confirm the view renders correctly. If it shows a YAML error, check quoting rules below
|
||||||
|
|
||||||
|
## Schema
|
||||||
|
|
||||||
|
Base files use the `.base` extension and contain valid YAML.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Global filters apply to ALL views in the base
|
||||||
|
filters:
|
||||||
|
# Can be a single filter string
|
||||||
|
# OR a recursive filter object with and/or/not
|
||||||
|
and: []
|
||||||
|
or: []
|
||||||
|
not: []
|
||||||
|
|
||||||
|
# Define formula properties that can be used across all views
|
||||||
|
formulas:
|
||||||
|
formula_name: 'expression'
|
||||||
|
|
||||||
|
# Configure display names and settings for properties
|
||||||
|
properties:
|
||||||
|
property_name:
|
||||||
|
displayName: "Display Name"
|
||||||
|
formula.formula_name:
|
||||||
|
displayName: "Formula Display Name"
|
||||||
|
file.ext:
|
||||||
|
displayName: "Extension"
|
||||||
|
|
||||||
|
# Define custom summary formulas
|
||||||
|
summaries:
|
||||||
|
custom_summary_name: 'values.mean().round(3)'
|
||||||
|
|
||||||
|
# Define one or more views
|
||||||
|
views:
|
||||||
|
- type: table | cards | list | map
|
||||||
|
name: "View Name"
|
||||||
|
limit: 10 # Optional: limit results
|
||||||
|
groupBy: # Optional: group results
|
||||||
|
property: property_name
|
||||||
|
direction: ASC | DESC
|
||||||
|
filters: # View-specific filters
|
||||||
|
and: []
|
||||||
|
order: # Properties to display in order
|
||||||
|
- file.name
|
||||||
|
- property_name
|
||||||
|
- formula.formula_name
|
||||||
|
summaries: # Map properties to summary formulas
|
||||||
|
property_name: Average
|
||||||
|
```
|
||||||
|
|
||||||
|
## Filter Syntax
|
||||||
|
|
||||||
|
Filters narrow down results. They can be applied globally or per-view.
|
||||||
|
|
||||||
|
### Filter Structure
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Single filter
|
||||||
|
filters: 'status == "done"'
|
||||||
|
|
||||||
|
# AND - all conditions must be true
|
||||||
|
filters:
|
||||||
|
and:
|
||||||
|
- 'status == "done"'
|
||||||
|
- 'priority > 3'
|
||||||
|
|
||||||
|
# OR - any condition can be true
|
||||||
|
filters:
|
||||||
|
or:
|
||||||
|
- 'file.hasTag("book")'
|
||||||
|
- 'file.hasTag("article")'
|
||||||
|
|
||||||
|
# NOT - exclude matching items
|
||||||
|
filters:
|
||||||
|
not:
|
||||||
|
- 'file.hasTag("archived")'
|
||||||
|
|
||||||
|
# Nested filters
|
||||||
|
filters:
|
||||||
|
or:
|
||||||
|
- file.hasTag("tag")
|
||||||
|
- and:
|
||||||
|
- file.hasTag("book")
|
||||||
|
- file.hasLink("Textbook")
|
||||||
|
- not:
|
||||||
|
- file.hasTag("book")
|
||||||
|
- file.inFolder("Required Reading")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Filter Operators
|
||||||
|
|
||||||
|
| Operator | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `==` | equals |
|
||||||
|
| `!=` | not equal |
|
||||||
|
| `>` | greater than |
|
||||||
|
| `<` | less than |
|
||||||
|
| `>=` | greater than or equal |
|
||||||
|
| `<=` | less than or equal |
|
||||||
|
| `&&` | logical and |
|
||||||
|
| `\|\|` | logical or |
|
||||||
|
| <code>!</code> | logical not |
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
### Three Types of Properties
|
||||||
|
|
||||||
|
1. **Note properties** - From frontmatter: `note.author` or just `author`
|
||||||
|
2. **File properties** - File metadata: `file.name`, `file.mtime`, etc.
|
||||||
|
3. **Formula properties** - Computed values: `formula.my_formula`
|
||||||
|
|
||||||
|
### File Properties Reference
|
||||||
|
|
||||||
|
| Property | Type | Description |
|
||||||
|
|----------|------|-------------|
|
||||||
|
| `file.name` | String | File name |
|
||||||
|
| `file.basename` | String | File name without extension |
|
||||||
|
| `file.path` | String | Full path to file |
|
||||||
|
| `file.folder` | String | Parent folder path |
|
||||||
|
| `file.ext` | String | File extension |
|
||||||
|
| `file.size` | Number | File size in bytes |
|
||||||
|
| `file.ctime` | Date | Created time |
|
||||||
|
| `file.mtime` | Date | Modified time |
|
||||||
|
| `file.tags` | List | All tags in file |
|
||||||
|
| `file.links` | List | Internal links in file |
|
||||||
|
| `file.backlinks` | List | Files linking to this file |
|
||||||
|
| `file.embeds` | List | Embeds in the note |
|
||||||
|
| `file.properties` | Object | All frontmatter properties |
|
||||||
|
|
||||||
|
### The `this` Keyword
|
||||||
|
|
||||||
|
- In main content area: refers to the base file itself
|
||||||
|
- When embedded: refers to the embedding file
|
||||||
|
- In sidebar: refers to the active file in main content
|
||||||
|
|
||||||
|
## Formula Syntax
|
||||||
|
|
||||||
|
Formulas compute values from properties. Defined in the `formulas` section.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
formulas:
|
||||||
|
# Simple arithmetic
|
||||||
|
total: "price * quantity"
|
||||||
|
|
||||||
|
# Conditional logic
|
||||||
|
status_icon: 'if(done, "✅", "⏳")'
|
||||||
|
|
||||||
|
# String formatting
|
||||||
|
formatted_price: 'if(price, price.toFixed(2) + " dollars")'
|
||||||
|
|
||||||
|
# Date formatting
|
||||||
|
created: 'file.ctime.format("YYYY-MM-DD")'
|
||||||
|
|
||||||
|
# Calculate days since created (use .days for Duration)
|
||||||
|
days_old: '(now() - file.ctime).days'
|
||||||
|
|
||||||
|
# Calculate days until due date
|
||||||
|
days_until_due: 'if(due_date, (date(due_date) - today()).days, "")'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Functions
|
||||||
|
|
||||||
|
Most commonly used functions. For the complete reference of all types (Date, String, Number, List, File, Link, Object, RegExp), see [FUNCTIONS_REFERENCE.md](references/FUNCTIONS_REFERENCE.md).
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `date()` | `date(string): date` | Parse string to date (`YYYY-MM-DD HH:mm:ss`) |
|
||||||
|
| `now()` | `now(): date` | Current date and time |
|
||||||
|
| `today()` | `today(): date` | Current date (time = 00:00:00) |
|
||||||
|
| `if()` | `if(condition, trueResult, falseResult?)` | Conditional |
|
||||||
|
| `duration()` | `duration(string): duration` | Parse duration string |
|
||||||
|
| `file()` | `file(path): file` | Get file object |
|
||||||
|
| `link()` | `link(path, display?): Link` | Create a link |
|
||||||
|
|
||||||
|
### Duration Type
|
||||||
|
|
||||||
|
When subtracting two dates, the result is a **Duration** type (not a number).
|
||||||
|
|
||||||
|
**Duration Fields:** `duration.days`, `duration.hours`, `duration.minutes`, `duration.seconds`, `duration.milliseconds`
|
||||||
|
|
||||||
|
**IMPORTANT:** Duration does NOT support `.round()`, `.floor()`, `.ceil()` directly. Access a numeric field first (like `.days`), then apply number functions.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# CORRECT: Calculate days between dates
|
||||||
|
"(date(due_date) - today()).days" # Returns number of days
|
||||||
|
"(now() - file.ctime).days" # Days since created
|
||||||
|
"(date(due_date) - today()).days.round(0)" # Rounded days
|
||||||
|
|
||||||
|
# WRONG - will cause error:
|
||||||
|
# "((date(due) - today()) / 86400000).round(0)" # Duration doesn't support division then round
|
||||||
|
```
|
||||||
|
|
||||||
|
### Date Arithmetic
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Duration units: y/year/years, M/month/months, d/day/days,
|
||||||
|
# w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds
|
||||||
|
"now() + \"1 day\"" # Tomorrow
|
||||||
|
"today() + \"7d\"" # A week from today
|
||||||
|
"now() - file.ctime" # Returns Duration
|
||||||
|
"(now() - file.ctime).days" # Get days as number
|
||||||
|
```
|
||||||
|
|
||||||
|
## View Types
|
||||||
|
|
||||||
|
### Table View
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
views:
|
||||||
|
- type: table
|
||||||
|
name: "My Table"
|
||||||
|
order:
|
||||||
|
- file.name
|
||||||
|
- status
|
||||||
|
- due_date
|
||||||
|
summaries:
|
||||||
|
price: Sum
|
||||||
|
count: Average
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cards View
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
views:
|
||||||
|
- type: cards
|
||||||
|
name: "Gallery"
|
||||||
|
order:
|
||||||
|
- file.name
|
||||||
|
- cover_image
|
||||||
|
- description
|
||||||
|
```
|
||||||
|
|
||||||
|
### List View
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
views:
|
||||||
|
- type: list
|
||||||
|
name: "Simple List"
|
||||||
|
order:
|
||||||
|
- file.name
|
||||||
|
- status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Map View
|
||||||
|
|
||||||
|
Requires latitude/longitude properties and the Maps community plugin.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
views:
|
||||||
|
- type: map
|
||||||
|
name: "Locations"
|
||||||
|
# Map-specific settings for lat/lng properties
|
||||||
|
```
|
||||||
|
|
||||||
|
## Default Summary Formulas
|
||||||
|
|
||||||
|
| Name | Input Type | Description |
|
||||||
|
|------|------------|-------------|
|
||||||
|
| `Average` | Number | Mathematical mean |
|
||||||
|
| `Min` | Number | Smallest number |
|
||||||
|
| `Max` | Number | Largest number |
|
||||||
|
| `Sum` | Number | Sum of all numbers |
|
||||||
|
| `Range` | Number | Max - Min |
|
||||||
|
| `Median` | Number | Mathematical median |
|
||||||
|
| `Stddev` | Number | Standard deviation |
|
||||||
|
| `Earliest` | Date | Earliest date |
|
||||||
|
| `Latest` | Date | Latest date |
|
||||||
|
| `Range` | Date | Latest - Earliest |
|
||||||
|
| `Checked` | Boolean | Count of true values |
|
||||||
|
| `Unchecked` | Boolean | Count of false values |
|
||||||
|
| `Empty` | Any | Count of empty values |
|
||||||
|
| `Filled` | Any | Count of non-empty values |
|
||||||
|
| `Unique` | Any | Count of unique values |
|
||||||
|
|
||||||
|
## Complete Examples
|
||||||
|
|
||||||
|
### Task Tracker Base
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
filters:
|
||||||
|
and:
|
||||||
|
- file.hasTag("task")
|
||||||
|
- 'file.ext == "md"'
|
||||||
|
|
||||||
|
formulas:
|
||||||
|
days_until_due: 'if(due, (date(due) - today()).days, "")'
|
||||||
|
is_overdue: 'if(due, date(due) < today() && status != "done", false)'
|
||||||
|
priority_label: 'if(priority == 1, "🔴 High", if(priority == 2, "🟡 Medium", "🟢 Low"))'
|
||||||
|
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
displayName: Status
|
||||||
|
formula.days_until_due:
|
||||||
|
displayName: "Days Until Due"
|
||||||
|
formula.priority_label:
|
||||||
|
displayName: Priority
|
||||||
|
|
||||||
|
views:
|
||||||
|
- type: table
|
||||||
|
name: "Active Tasks"
|
||||||
|
filters:
|
||||||
|
and:
|
||||||
|
- 'status != "done"'
|
||||||
|
order:
|
||||||
|
- file.name
|
||||||
|
- status
|
||||||
|
- formula.priority_label
|
||||||
|
- due
|
||||||
|
- formula.days_until_due
|
||||||
|
groupBy:
|
||||||
|
property: status
|
||||||
|
direction: ASC
|
||||||
|
summaries:
|
||||||
|
formula.days_until_due: Average
|
||||||
|
|
||||||
|
- type: table
|
||||||
|
name: "Completed"
|
||||||
|
filters:
|
||||||
|
and:
|
||||||
|
- 'status == "done"'
|
||||||
|
order:
|
||||||
|
- file.name
|
||||||
|
- completed_date
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reading List Base
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
filters:
|
||||||
|
or:
|
||||||
|
- file.hasTag("book")
|
||||||
|
- file.hasTag("article")
|
||||||
|
|
||||||
|
formulas:
|
||||||
|
reading_time: 'if(pages, (pages * 2).toString() + " min", "")'
|
||||||
|
status_icon: 'if(status == "reading", "📖", if(status == "done", "✅", "📚"))'
|
||||||
|
year_read: 'if(finished_date, date(finished_date).year, "")'
|
||||||
|
|
||||||
|
properties:
|
||||||
|
author:
|
||||||
|
displayName: Author
|
||||||
|
formula.status_icon:
|
||||||
|
displayName: ""
|
||||||
|
formula.reading_time:
|
||||||
|
displayName: "Est. Time"
|
||||||
|
|
||||||
|
views:
|
||||||
|
- type: cards
|
||||||
|
name: "Library"
|
||||||
|
order:
|
||||||
|
- cover
|
||||||
|
- file.name
|
||||||
|
- author
|
||||||
|
- formula.status_icon
|
||||||
|
filters:
|
||||||
|
not:
|
||||||
|
- 'status == "dropped"'
|
||||||
|
|
||||||
|
- type: table
|
||||||
|
name: "Reading List"
|
||||||
|
filters:
|
||||||
|
and:
|
||||||
|
- 'status == "to-read"'
|
||||||
|
order:
|
||||||
|
- file.name
|
||||||
|
- author
|
||||||
|
- pages
|
||||||
|
- formula.reading_time
|
||||||
|
```
|
||||||
|
|
||||||
|
### Daily Notes Index
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
filters:
|
||||||
|
and:
|
||||||
|
- file.inFolder("Daily Notes")
|
||||||
|
- '/^\d{4}-\d{2}-\d{2}$/.matches(file.basename)'
|
||||||
|
|
||||||
|
formulas:
|
||||||
|
word_estimate: '(file.size / 5).round(0)'
|
||||||
|
day_of_week: 'date(file.basename).format("dddd")'
|
||||||
|
|
||||||
|
properties:
|
||||||
|
formula.day_of_week:
|
||||||
|
displayName: "Day"
|
||||||
|
formula.word_estimate:
|
||||||
|
displayName: "~Words"
|
||||||
|
|
||||||
|
views:
|
||||||
|
- type: table
|
||||||
|
name: "Recent Notes"
|
||||||
|
limit: 30
|
||||||
|
order:
|
||||||
|
- file.name
|
||||||
|
- formula.day_of_week
|
||||||
|
- formula.word_estimate
|
||||||
|
- file.mtime
|
||||||
|
```
|
||||||
|
|
||||||
|
## Embedding Bases
|
||||||
|
|
||||||
|
Embed in Markdown files:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
![[MyBase.base]]
|
||||||
|
|
||||||
|
<!-- Specific view -->
|
||||||
|
![[MyBase.base#View Name]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## YAML Quoting Rules
|
||||||
|
|
||||||
|
- Use single quotes for formulas containing double quotes: `'if(done, "Yes", "No")'`
|
||||||
|
- Use double quotes for simple strings: `"My View Name"`
|
||||||
|
- Escape nested quotes properly in complex expressions
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### YAML Syntax Errors
|
||||||
|
|
||||||
|
**Unquoted special characters**: Strings containing `:`, `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` `` must be quoted.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# WRONG - colon in unquoted string
|
||||||
|
displayName: Status: Active
|
||||||
|
|
||||||
|
# CORRECT
|
||||||
|
displayName: "Status: Active"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Mismatched quotes in formulas**: When a formula contains double quotes, wrap the entire formula in single quotes.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# WRONG - double quotes inside double quotes
|
||||||
|
formulas:
|
||||||
|
label: "if(done, "Yes", "No")"
|
||||||
|
|
||||||
|
# CORRECT - single quotes wrapping double quotes
|
||||||
|
formulas:
|
||||||
|
label: 'if(done, "Yes", "No")'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common Formula Errors
|
||||||
|
|
||||||
|
**Duration math without field access**: Subtracting dates returns a Duration, not a number. Always access `.days`, `.hours`, etc.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# WRONG - Duration is not a number
|
||||||
|
"(now() - file.ctime).round(0)"
|
||||||
|
|
||||||
|
# CORRECT - access .days first, then round
|
||||||
|
"(now() - file.ctime).days.round(0)"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Missing null checks**: Properties may not exist on all notes. Use `if()` to guard.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# WRONG - crashes if due_date is empty
|
||||||
|
"(date(due_date) - today()).days"
|
||||||
|
|
||||||
|
# CORRECT - guard with if()
|
||||||
|
'if(due_date, (date(due_date) - today()).days, "")'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Referencing undefined formulas**: Ensure every `formula.X` in `order` or `properties` has a matching entry in `formulas`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# This will fail silently if 'total' is not defined in formulas
|
||||||
|
order:
|
||||||
|
- formula.total
|
||||||
|
|
||||||
|
# Fix: define it
|
||||||
|
formulas:
|
||||||
|
total: "price * quantity"
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Bases Syntax](https://help.obsidian.md/bases/syntax)
|
||||||
|
- [Functions](https://help.obsidian.md/bases/functions)
|
||||||
|
- [Views](https://help.obsidian.md/bases/views)
|
||||||
|
- [Formulas](https://help.obsidian.md/formulas)
|
||||||
|
- [Complete Functions Reference](references/FUNCTIONS_REFERENCE.md)
|
||||||
173
.obsidian/plugins/skills/obsidian-bases/references/FUNCTIONS_REFERENCE.md
vendored
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
# Functions Reference
|
||||||
|
|
||||||
|
## Global Functions
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `date()` | `date(string): date` | Parse string to date. Format: `YYYY-MM-DD HH:mm:ss` |
|
||||||
|
| `duration()` | `duration(string): duration` | Parse duration string |
|
||||||
|
| `now()` | `now(): date` | Current date and time |
|
||||||
|
| `today()` | `today(): date` | Current date (time = 00:00:00) |
|
||||||
|
| `if()` | `if(condition, trueResult, falseResult?)` | Conditional |
|
||||||
|
| `min()` | `min(n1, n2, ...): number` | Smallest number |
|
||||||
|
| `max()` | `max(n1, n2, ...): number` | Largest number |
|
||||||
|
| `number()` | `number(any): number` | Convert to number |
|
||||||
|
| `link()` | `link(path, display?): Link` | Create a link |
|
||||||
|
| `list()` | `list(element): List` | Wrap in list if not already |
|
||||||
|
| `file()` | `file(path): file` | Get file object |
|
||||||
|
| `image()` | `image(path): image` | Create image for rendering |
|
||||||
|
| `icon()` | `icon(name): icon` | Lucide icon by name |
|
||||||
|
| `html()` | `html(string): html` | Render as HTML |
|
||||||
|
| `escapeHTML()` | `escapeHTML(string): string` | Escape HTML characters |
|
||||||
|
|
||||||
|
## Any Type Functions
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `isTruthy()` | `any.isTruthy(): boolean` | Coerce to boolean |
|
||||||
|
| `isType()` | `any.isType(type): boolean` | Check type |
|
||||||
|
| `toString()` | `any.toString(): string` | Convert to string |
|
||||||
|
|
||||||
|
## Date Functions & Fields
|
||||||
|
|
||||||
|
**Fields:** `date.year`, `date.month`, `date.day`, `date.hour`, `date.minute`, `date.second`, `date.millisecond`
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `date()` | `date.date(): date` | Remove time portion |
|
||||||
|
| `format()` | `date.format(string): string` | Format with Moment.js pattern |
|
||||||
|
| `time()` | `date.time(): string` | Get time as string |
|
||||||
|
| `relative()` | `date.relative(): string` | Human-readable relative time |
|
||||||
|
| `isEmpty()` | `date.isEmpty(): boolean` | Always false for dates |
|
||||||
|
|
||||||
|
## Duration Type
|
||||||
|
|
||||||
|
When subtracting two dates, the result is a **Duration** type (not a number). Duration has its own properties and methods.
|
||||||
|
|
||||||
|
**Duration Fields:**
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `duration.days` | Number | Total days in duration |
|
||||||
|
| `duration.hours` | Number | Total hours in duration |
|
||||||
|
| `duration.minutes` | Number | Total minutes in duration |
|
||||||
|
| `duration.seconds` | Number | Total seconds in duration |
|
||||||
|
| `duration.milliseconds` | Number | Total milliseconds in duration |
|
||||||
|
|
||||||
|
**IMPORTANT:** Duration does NOT support `.round()`, `.floor()`, `.ceil()` directly. You must access a numeric field first (like `.days`), then apply number functions.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# CORRECT: Calculate days between dates
|
||||||
|
"(date(due_date) - today()).days" # Returns number of days
|
||||||
|
"(now() - file.ctime).days" # Days since created
|
||||||
|
|
||||||
|
# CORRECT: Round the numeric result if needed
|
||||||
|
"(date(due_date) - today()).days.round(0)" # Rounded days
|
||||||
|
"(now() - file.ctime).hours.round(0)" # Rounded hours
|
||||||
|
|
||||||
|
# WRONG - will cause error:
|
||||||
|
# "((date(due) - today()) / 86400000).round(0)" # Duration doesn't support division then round
|
||||||
|
```
|
||||||
|
|
||||||
|
## Date Arithmetic
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Duration units: y/year/years, M/month/months, d/day/days,
|
||||||
|
# w/week/weeks, h/hour/hours, m/minute/minutes, s/second/seconds
|
||||||
|
|
||||||
|
# Add/subtract durations
|
||||||
|
"date + \"1M\"" # Add 1 month
|
||||||
|
"date - \"2h\"" # Subtract 2 hours
|
||||||
|
"now() + \"1 day\"" # Tomorrow
|
||||||
|
"today() + \"7d\"" # A week from today
|
||||||
|
|
||||||
|
# Subtract dates returns Duration type
|
||||||
|
"now() - file.ctime" # Returns Duration
|
||||||
|
"(now() - file.ctime).days" # Get days as number
|
||||||
|
"(now() - file.ctime).hours" # Get hours as number
|
||||||
|
|
||||||
|
# Complex duration arithmetic
|
||||||
|
"now() + (duration('1d') * 2)"
|
||||||
|
```
|
||||||
|
|
||||||
|
## String Functions
|
||||||
|
|
||||||
|
**Field:** `string.length`
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `contains()` | `string.contains(value): boolean` | Check substring |
|
||||||
|
| `containsAll()` | `string.containsAll(...values): boolean` | All substrings present |
|
||||||
|
| `containsAny()` | `string.containsAny(...values): boolean` | Any substring present |
|
||||||
|
| `startsWith()` | `string.startsWith(query): boolean` | Starts with query |
|
||||||
|
| `endsWith()` | `string.endsWith(query): boolean` | Ends with query |
|
||||||
|
| `isEmpty()` | `string.isEmpty(): boolean` | Empty or not present |
|
||||||
|
| `lower()` | `string.lower(): string` | To lowercase |
|
||||||
|
| `title()` | `string.title(): string` | To Title Case |
|
||||||
|
| `trim()` | `string.trim(): string` | Remove whitespace |
|
||||||
|
| `replace()` | `string.replace(pattern, replacement): string` | Replace pattern |
|
||||||
|
| `repeat()` | `string.repeat(count): string` | Repeat string |
|
||||||
|
| `reverse()` | `string.reverse(): string` | Reverse string |
|
||||||
|
| `slice()` | `string.slice(start, end?): string` | Substring |
|
||||||
|
| `split()` | `string.split(separator, n?): list` | Split to list |
|
||||||
|
|
||||||
|
## Number Functions
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `abs()` | `number.abs(): number` | Absolute value |
|
||||||
|
| `ceil()` | `number.ceil(): number` | Round up |
|
||||||
|
| `floor()` | `number.floor(): number` | Round down |
|
||||||
|
| `round()` | `number.round(digits?): number` | Round to digits |
|
||||||
|
| `toFixed()` | `number.toFixed(precision): string` | Fixed-point notation |
|
||||||
|
| `isEmpty()` | `number.isEmpty(): boolean` | Not present |
|
||||||
|
|
||||||
|
## List Functions
|
||||||
|
|
||||||
|
**Field:** `list.length`
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `contains()` | `list.contains(value): boolean` | Element exists |
|
||||||
|
| `containsAll()` | `list.containsAll(...values): boolean` | All elements exist |
|
||||||
|
| `containsAny()` | `list.containsAny(...values): boolean` | Any element exists |
|
||||||
|
| `filter()` | `list.filter(expression): list` | Filter by condition (uses `value`, `index`) |
|
||||||
|
| `map()` | `list.map(expression): list` | Transform elements (uses `value`, `index`) |
|
||||||
|
| `reduce()` | `list.reduce(expression, initial): any` | Reduce to single value (uses `value`, `index`, `acc`) |
|
||||||
|
| `flat()` | `list.flat(): list` | Flatten nested lists |
|
||||||
|
| `join()` | `list.join(separator): string` | Join to string |
|
||||||
|
| `reverse()` | `list.reverse(): list` | Reverse order |
|
||||||
|
| `slice()` | `list.slice(start, end?): list` | Sublist |
|
||||||
|
| `sort()` | `list.sort(): list` | Sort ascending |
|
||||||
|
| `unique()` | `list.unique(): list` | Remove duplicates |
|
||||||
|
| `isEmpty()` | `list.isEmpty(): boolean` | No elements |
|
||||||
|
|
||||||
|
## File Functions
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `asLink()` | `file.asLink(display?): Link` | Convert to link |
|
||||||
|
| `hasLink()` | `file.hasLink(otherFile): boolean` | Has link to file |
|
||||||
|
| `hasTag()` | `file.hasTag(...tags): boolean` | Has any of the tags |
|
||||||
|
| `hasProperty()` | `file.hasProperty(name): boolean` | Has property |
|
||||||
|
| `inFolder()` | `file.inFolder(folder): boolean` | In folder or subfolder |
|
||||||
|
|
||||||
|
## Link Functions
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `asFile()` | `link.asFile(): file` | Get file object |
|
||||||
|
| `linksTo()` | `link.linksTo(file): boolean` | Links to file |
|
||||||
|
|
||||||
|
## Object Functions
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `isEmpty()` | `object.isEmpty(): boolean` | No properties |
|
||||||
|
| `keys()` | `object.keys(): list` | List of keys |
|
||||||
|
| `values()` | `object.values(): list` | List of values |
|
||||||
|
|
||||||
|
## Regular Expression Functions
|
||||||
|
|
||||||
|
| Function | Signature | Description |
|
||||||
|
|----------|-----------|-------------|
|
||||||
|
| `matches()` | `regexp.matches(string): boolean` | Test if matches |
|
||||||
106
.obsidian/plugins/skills/obsidian-cli/SKILL.md
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
---
|
||||||
|
name: obsidian-cli
|
||||||
|
description: Interact with Obsidian vaults using the Obsidian CLI to read, create, search, and manage notes, tasks, properties, and more. Also supports plugin and theme development with commands to reload plugins, run JavaScript, capture errors, take screenshots, and inspect the DOM. Use when the user asks to interact with their Obsidian vault, manage notes, search vault content, perform vault operations from the command line, or develop and debug Obsidian plugins and themes.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Obsidian CLI
|
||||||
|
|
||||||
|
Use the `obsidian` CLI to interact with a running Obsidian instance. Requires Obsidian to be open.
|
||||||
|
|
||||||
|
## Command reference
|
||||||
|
|
||||||
|
Run `obsidian help` to see all available commands. This is always up to date. Full docs: https://help.obsidian.md/cli
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
**Parameters** take a value with `=`. Quote values with spaces:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
obsidian create name="My Note" content="Hello world"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Flags** are boolean switches with no value:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
obsidian create name="My Note" silent overwrite
|
||||||
|
```
|
||||||
|
|
||||||
|
For multiline content use `\n` for newline and `\t` for tab.
|
||||||
|
|
||||||
|
## File targeting
|
||||||
|
|
||||||
|
Many commands accept `file` or `path` to target a file. Without either, the active file is used.
|
||||||
|
|
||||||
|
- `file=<name>` — resolves like a wikilink (name only, no path or extension needed)
|
||||||
|
- `path=<path>` — exact path from vault root, e.g. `folder/note.md`
|
||||||
|
|
||||||
|
## Vault targeting
|
||||||
|
|
||||||
|
Commands target the most recently focused vault by default. Use `vault=<name>` as the first parameter to target a specific vault:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
obsidian vault="My Vault" search query="test"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common patterns
|
||||||
|
|
||||||
|
```bash
|
||||||
|
obsidian read file="My Note"
|
||||||
|
obsidian create name="New Note" content="# Hello" template="Template" silent
|
||||||
|
obsidian append file="My Note" content="New line"
|
||||||
|
obsidian search query="search term" limit=10
|
||||||
|
obsidian daily:read
|
||||||
|
obsidian daily:append content="- [ ] New task"
|
||||||
|
obsidian property:set name="status" value="done" file="My Note"
|
||||||
|
obsidian tasks daily todo
|
||||||
|
obsidian tags sort=count counts
|
||||||
|
obsidian backlinks file="My Note"
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `--copy` on any command to copy output to clipboard. Use `silent` to prevent files from opening. Use `total` on list commands to get a count.
|
||||||
|
|
||||||
|
## Plugin development
|
||||||
|
|
||||||
|
### Develop/test cycle
|
||||||
|
|
||||||
|
After making code changes to a plugin or theme, follow this workflow:
|
||||||
|
|
||||||
|
1. **Reload** the plugin to pick up changes:
|
||||||
|
```bash
|
||||||
|
obsidian plugin:reload id=my-plugin
|
||||||
|
```
|
||||||
|
2. **Check for errors** — if errors appear, fix and repeat from step 1:
|
||||||
|
```bash
|
||||||
|
obsidian dev:errors
|
||||||
|
```
|
||||||
|
3. **Verify visually** with a screenshot or DOM inspection:
|
||||||
|
```bash
|
||||||
|
obsidian dev:screenshot path=screenshot.png
|
||||||
|
obsidian dev:dom selector=".workspace-leaf" text
|
||||||
|
```
|
||||||
|
4. **Check console output** for warnings or unexpected logs:
|
||||||
|
```bash
|
||||||
|
obsidian dev:console level=error
|
||||||
|
```
|
||||||
|
|
||||||
|
### Additional developer commands
|
||||||
|
|
||||||
|
Run JavaScript in the app context:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
obsidian eval code="app.vault.getFiles().length"
|
||||||
|
```
|
||||||
|
|
||||||
|
Inspect CSS values:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
obsidian dev:css selector=".workspace-leaf" prop=background-color
|
||||||
|
```
|
||||||
|
|
||||||
|
Toggle mobile emulation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
obsidian dev:mobile on
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `obsidian help` to see additional developer commands including CDP and debugger controls.
|
||||||
196
.obsidian/plugins/skills/obsidian-markdown/SKILL.md
vendored
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
---
|
||||||
|
name: obsidian-markdown
|
||||||
|
description: Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax. Use when working with .md files in Obsidian, or when the user mentions wikilinks, callouts, frontmatter, tags, embeds, or Obsidian notes.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Obsidian Flavored Markdown Skill
|
||||||
|
|
||||||
|
Create and edit valid Obsidian Flavored Markdown. Obsidian extends CommonMark and GFM with wikilinks, embeds, callouts, properties, comments, and other syntax. This skill covers only Obsidian-specific extensions -- standard Markdown (headings, bold, italic, lists, quotes, code blocks, tables) is assumed knowledge.
|
||||||
|
|
||||||
|
## Workflow: Creating an Obsidian Note
|
||||||
|
|
||||||
|
1. **Add frontmatter** with properties (title, tags, aliases) at the top of the file. See [PROPERTIES.md](references/PROPERTIES.md) for all property types.
|
||||||
|
2. **Write content** using standard Markdown for structure, plus Obsidian-specific syntax below.
|
||||||
|
3. **Link related notes** using wikilinks (`[[Note]]`) for internal vault connections, or standard Markdown links for external URLs.
|
||||||
|
4. **Embed content** from other notes, images, or PDFs using the `![[embed]]` syntax. See [EMBEDS.md](references/EMBEDS.md) for all embed types.
|
||||||
|
5. **Add callouts** for highlighted information using `> [!type]` syntax. See [CALLOUTS.md](references/CALLOUTS.md) for all callout types.
|
||||||
|
6. **Verify** the note renders correctly in Obsidian's reading view.
|
||||||
|
|
||||||
|
> When choosing between wikilinks and Markdown links: use `[[wikilinks]]` for notes within the vault (Obsidian tracks renames automatically) and `[text](url)` for external URLs only.
|
||||||
|
|
||||||
|
## Internal Links (Wikilinks)
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
[[Note Name]] Link to note
|
||||||
|
[[Note Name|Display Text]] Custom display text
|
||||||
|
[[Note Name#Heading]] Link to heading
|
||||||
|
[[Note Name#^block-id]] Link to block
|
||||||
|
[[#Heading in same note]] Same-note heading link
|
||||||
|
```
|
||||||
|
|
||||||
|
Define a block ID by appending `^block-id` to any paragraph:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
This paragraph can be linked to. ^my-block-id
|
||||||
|
```
|
||||||
|
|
||||||
|
For lists and quotes, place the block ID on a separate line after the block:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> A quote block
|
||||||
|
|
||||||
|
^quote-id
|
||||||
|
```
|
||||||
|
|
||||||
|
## Embeds
|
||||||
|
|
||||||
|
Prefix any wikilink with `!` to embed its content inline:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
![[Note Name]] Embed full note
|
||||||
|
![[Note Name#Heading]] Embed section
|
||||||
|
![[image.png]] Embed image
|
||||||
|
![[image.png|300]] Embed image with width
|
||||||
|
![[document.pdf#page=3]] Embed PDF page
|
||||||
|
```
|
||||||
|
|
||||||
|
See [EMBEDS.md](references/EMBEDS.md) for audio, video, search embeds, and external images.
|
||||||
|
|
||||||
|
## Callouts
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> [!note]
|
||||||
|
> Basic callout.
|
||||||
|
|
||||||
|
> [!warning] Custom Title
|
||||||
|
> Callout with a custom title.
|
||||||
|
|
||||||
|
> [!faq]- Collapsed by default
|
||||||
|
> Foldable callout (- collapsed, + expanded).
|
||||||
|
```
|
||||||
|
|
||||||
|
Common types: `note`, `tip`, `warning`, `info`, `example`, `quote`, `bug`, `danger`, `success`, `failure`, `question`, `abstract`, `todo`.
|
||||||
|
|
||||||
|
See [CALLOUTS.md](references/CALLOUTS.md) for the full list with aliases, nesting, and custom CSS callouts.
|
||||||
|
|
||||||
|
## Properties (Frontmatter)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: My Note
|
||||||
|
date: 2024-01-15
|
||||||
|
tags:
|
||||||
|
- project
|
||||||
|
- active
|
||||||
|
aliases:
|
||||||
|
- Alternative Name
|
||||||
|
cssclasses:
|
||||||
|
- custom-class
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
Default properties: `tags` (searchable labels), `aliases` (alternative note names for link suggestions), `cssclasses` (CSS classes for styling).
|
||||||
|
|
||||||
|
See [PROPERTIES.md](references/PROPERTIES.md) for all property types, tag syntax rules, and advanced usage.
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
#tag Inline tag
|
||||||
|
#nested/tag Nested tag with hierarchy
|
||||||
|
```
|
||||||
|
|
||||||
|
Tags can contain letters, numbers (not first character), underscores, hyphens, and forward slashes. Tags can also be defined in frontmatter under the `tags` property.
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
This is visible %%but this is hidden%% text.
|
||||||
|
|
||||||
|
%%
|
||||||
|
This entire block is hidden in reading view.
|
||||||
|
%%
|
||||||
|
```
|
||||||
|
|
||||||
|
## Obsidian-Specific Formatting
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
==Highlighted text== Highlight syntax
|
||||||
|
```
|
||||||
|
|
||||||
|
## Math (LaTeX)
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Inline: $e^{i\pi} + 1 = 0$
|
||||||
|
|
||||||
|
Block:
|
||||||
|
$$
|
||||||
|
\frac{a}{b} = c
|
||||||
|
$$
|
||||||
|
```
|
||||||
|
|
||||||
|
## Diagrams (Mermaid)
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
A[Start] --> B{Decision}
|
||||||
|
B -->|Yes| C[Do this]
|
||||||
|
B -->|No| D[Do that]
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
To link Mermaid nodes to Obsidian notes, add `class NodeName internal-link;`.
|
||||||
|
|
||||||
|
## Footnotes
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
Text with a footnote[^1].
|
||||||
|
|
||||||
|
[^1]: Footnote content.
|
||||||
|
|
||||||
|
Inline footnote.^[This is inline.]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
---
|
||||||
|
title: Project Alpha
|
||||||
|
date: 2024-01-15
|
||||||
|
tags:
|
||||||
|
- project
|
||||||
|
- active
|
||||||
|
status: in-progress
|
||||||
|
---
|
||||||
|
|
||||||
|
# Project Alpha
|
||||||
|
|
||||||
|
This project aims to [[improve workflow]] using modern techniques.
|
||||||
|
|
||||||
|
> [!important] Key Deadline
|
||||||
|
> The first milestone is due on ==January 30th==.
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
- [x] Initial planning
|
||||||
|
- [ ] Development phase
|
||||||
|
- [ ] Backend implementation
|
||||||
|
- [ ] Frontend design
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
The algorithm uses $O(n \log n)$ sorting. See [[Algorithm Notes#Sorting]] for details.
|
||||||
|
|
||||||
|
![[Architecture Diagram.png|600]]
|
||||||
|
|
||||||
|
Reviewed in [[Meeting Notes 2024-01-10#Decisions]].
|
||||||
|
````
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Obsidian Flavored Markdown](https://help.obsidian.md/obsidian-flavored-markdown)
|
||||||
|
- [Internal links](https://help.obsidian.md/links)
|
||||||
|
- [Embed files](https://help.obsidian.md/embeds)
|
||||||
|
- [Callouts](https://help.obsidian.md/callouts)
|
||||||
|
- [Properties](https://help.obsidian.md/properties)
|
||||||
58
.obsidian/plugins/skills/obsidian-markdown/references/CALLOUTS.md
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# Callouts Reference
|
||||||
|
|
||||||
|
## Basic Callout
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> [!note]
|
||||||
|
> This is a note callout.
|
||||||
|
|
||||||
|
> [!info] Custom Title
|
||||||
|
> This callout has a custom title.
|
||||||
|
|
||||||
|
> [!tip] Title Only
|
||||||
|
```
|
||||||
|
|
||||||
|
## Foldable Callouts
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> [!faq]- Collapsed by default
|
||||||
|
> This content is hidden until expanded.
|
||||||
|
|
||||||
|
> [!faq]+ Expanded by default
|
||||||
|
> This content is visible but can be collapsed.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Nested Callouts
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> [!question] Outer callout
|
||||||
|
> > [!note] Inner callout
|
||||||
|
> > Nested content
|
||||||
|
```
|
||||||
|
|
||||||
|
## Supported Callout Types
|
||||||
|
|
||||||
|
| Type | Aliases | Color / Icon |
|
||||||
|
|------|---------|-------------|
|
||||||
|
| `note` | - | Blue, pencil |
|
||||||
|
| `abstract` | `summary`, `tldr` | Teal, clipboard |
|
||||||
|
| `info` | - | Blue, info |
|
||||||
|
| `todo` | - | Blue, checkbox |
|
||||||
|
| `tip` | `hint`, `important` | Cyan, flame |
|
||||||
|
| `success` | `check`, `done` | Green, checkmark |
|
||||||
|
| `question` | `help`, `faq` | Yellow, question mark |
|
||||||
|
| `warning` | `caution`, `attention` | Orange, warning |
|
||||||
|
| `failure` | `fail`, `missing` | Red, X |
|
||||||
|
| `danger` | `error` | Red, zap |
|
||||||
|
| `bug` | - | Red, bug |
|
||||||
|
| `example` | - | Purple, list |
|
||||||
|
| `quote` | `cite` | Gray, quote |
|
||||||
|
|
||||||
|
## Custom Callouts (CSS)
|
||||||
|
|
||||||
|
```css
|
||||||
|
.callout[data-callout="custom-type"] {
|
||||||
|
--callout-color: 255, 0, 0;
|
||||||
|
--callout-icon: lucide-alert-circle;
|
||||||
|
}
|
||||||
|
```
|
||||||
63
.obsidian/plugins/skills/obsidian-markdown/references/EMBEDS.md
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# Embeds Reference
|
||||||
|
|
||||||
|
## Embed Notes
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
![[Note Name]]
|
||||||
|
![[Note Name#Heading]]
|
||||||
|
![[Note Name#^block-id]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Embed Images
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
![[image.png]]
|
||||||
|
![[image.png|640x480]] Width x Height
|
||||||
|
![[image.png|300]] Width only (maintains aspect ratio)
|
||||||
|
```
|
||||||
|
|
||||||
|
## External Images
|
||||||
|
|
||||||
|
```markdown
|
||||||
|

|
||||||
|

|
||||||
|
```
|
||||||
|
|
||||||
|
## Embed Audio
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
![[audio.mp3]]
|
||||||
|
![[audio.ogg]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Embed PDF
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
![[document.pdf]]
|
||||||
|
![[document.pdf#page=3]]
|
||||||
|
![[document.pdf#height=400]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Embed Lists
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
![[Note#^list-id]]
|
||||||
|
```
|
||||||
|
|
||||||
|
Where the list has a block ID:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
- Item 1
|
||||||
|
- Item 2
|
||||||
|
- Item 3
|
||||||
|
|
||||||
|
^list-id
|
||||||
|
```
|
||||||
|
|
||||||
|
## Embed Search Results
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```query
|
||||||
|
tag:#project status:done
|
||||||
|
```
|
||||||
|
````
|
||||||
61
.obsidian/plugins/skills/obsidian-markdown/references/PROPERTIES.md
vendored
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# Properties (Frontmatter) Reference
|
||||||
|
|
||||||
|
Properties use YAML frontmatter at the start of a note:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
title: My Note Title
|
||||||
|
date: 2024-01-15
|
||||||
|
tags:
|
||||||
|
- project
|
||||||
|
- important
|
||||||
|
aliases:
|
||||||
|
- My Note
|
||||||
|
- Alternative Name
|
||||||
|
cssclasses:
|
||||||
|
- custom-class
|
||||||
|
status: in-progress
|
||||||
|
rating: 4.5
|
||||||
|
completed: false
|
||||||
|
due: 2024-02-01T14:30:00
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
## Property Types
|
||||||
|
|
||||||
|
| Type | Example |
|
||||||
|
|------|---------|
|
||||||
|
| Text | `title: My Title` |
|
||||||
|
| Number | `rating: 4.5` |
|
||||||
|
| Checkbox | `completed: true` |
|
||||||
|
| Date | `date: 2024-01-15` |
|
||||||
|
| Date & Time | `due: 2024-01-15T14:30:00` |
|
||||||
|
| List | `tags: [one, two]` or YAML list |
|
||||||
|
| Links | `related: "[[Other Note]]"` |
|
||||||
|
|
||||||
|
## Default Properties
|
||||||
|
|
||||||
|
- `tags` - Note tags (searchable, shown in graph view)
|
||||||
|
- `aliases` - Alternative names for the note (used in link suggestions)
|
||||||
|
- `cssclasses` - CSS classes applied to the note in reading/editing view
|
||||||
|
|
||||||
|
## Tags
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
#tag
|
||||||
|
#nested/tag
|
||||||
|
#tag-with-dashes
|
||||||
|
#tag_with_underscores
|
||||||
|
```
|
||||||
|
|
||||||
|
Tags can contain: letters (any language), numbers (not first character), underscores `_`, hyphens `-`, forward slashes `/` (for nesting).
|
||||||
|
|
||||||
|
In frontmatter:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
tags:
|
||||||
|
- tag1
|
||||||
|
- nested/tag2
|
||||||
|
---
|
||||||
|
```
|
||||||
150
.obsidian/plugins/skills/tutor-setup/SKILL.md
vendored
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
---
|
||||||
|
name: tutor-setup
|
||||||
|
description: >
|
||||||
|
Transforms knowledge sources into an Obsidian StudyVault. Two modes:
|
||||||
|
(1) Document Mode — PDF/text/web sources → study notes with practice questions.
|
||||||
|
(2) Codebase Mode — source code project → onboarding vault for new developers.
|
||||||
|
Mode is auto-detected based on project markers in CWD.
|
||||||
|
argument-hint: "[source-path-or-url]"
|
||||||
|
allowed-tools: Read, Write, Edit, Glob, Grep, Bash, WebFetch
|
||||||
|
---
|
||||||
|
|
||||||
|
# Tutor Setup — Knowledge to Obsidian StudyVault
|
||||||
|
|
||||||
|
## CWD Boundary Rule (ALL MODES)
|
||||||
|
|
||||||
|
> **NEVER access files outside the current working directory (CWD).**
|
||||||
|
> All source scanning, reading, and vault output MUST stay within CWD and its subdirectories.
|
||||||
|
> If the user provides an external path, ask them to copy the files into CWD first.
|
||||||
|
|
||||||
|
## Mode Detection
|
||||||
|
|
||||||
|
On invocation, detect mode automatically:
|
||||||
|
|
||||||
|
1. **Check for project markers** in CWD:
|
||||||
|
- `package.json`, `pom.xml`, `build.gradle`, `Cargo.toml`, `go.mod`, `Makefile`,
|
||||||
|
`*.sln`, `pyproject.toml`, `setup.py`, `Gemfile`
|
||||||
|
2. **If any marker found** → **Codebase Mode**
|
||||||
|
3. **If no marker found** → **Document Mode**
|
||||||
|
4. **Tie-break**: If `.git/` is the sole indicator and no source code files (`*.ts`, `*.py`, `*.java`, `*.go`, `*.rs`, etc.) exist, default to Document Mode.
|
||||||
|
5. Announce detected mode and ask user to confirm or override.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Document Mode
|
||||||
|
|
||||||
|
> Transforms knowledge sources (PDF, text, web, epub) into study notes.
|
||||||
|
> Templates: [templates.md](references/templates.md)
|
||||||
|
|
||||||
|
### Phase D1: Source Discovery & Extraction
|
||||||
|
|
||||||
|
1. **Auto-scan CWD** for `**/*.pdf`, `**/*.txt`, `**/*.md`, `**/*.html`, `**/*.epub` (exclude `node_modules/`, `.git/`, `dist/`, `build/`, `StudyVault/`). Present for user confirmation.
|
||||||
|
2. **Extract text (MANDATORY tools)**:
|
||||||
|
- **PDF → `pdftotext` CLI ONLY** (run via Bash tool). NEVER use the Read tool directly on PDF files — it renders pages as images and wastes 10-50x more tokens. Convert to `.txt` first, then Read the `.txt` file.
|
||||||
|
```bash
|
||||||
|
pdftotext "source.pdf" "/tmp/source.txt"
|
||||||
|
```
|
||||||
|
- If `pdftotext` is not installed, install it first: `brew install poppler` (macOS) or `apt-get install poppler-utils` (Linux).
|
||||||
|
- URL → WebFetch
|
||||||
|
- Other formats (`.md`, `.txt`, `.html`) → Read directly.
|
||||||
|
3. **Read extracted `.txt` files** — understand scope, structure, depth. Work exclusively from the converted text, never from the raw PDF.
|
||||||
|
4. **Source Content Mapping (MANDATORY for multi-file sources)**:
|
||||||
|
- Read **cover page + TOC + 3+ sample pages from middle/end** for EVERY source file
|
||||||
|
- **NEVER assume content from filename** — file numbering often ≠ chapter numbering
|
||||||
|
- Build verified mapping: `{ source_file → actual_topics → page_ranges }`
|
||||||
|
- Flag non-academic files and missing sources
|
||||||
|
- Present mapping to user for verification before proceeding
|
||||||
|
|
||||||
|
### Phase D2: Content Analysis
|
||||||
|
|
||||||
|
1. Identify topic hierarchy — sections, chapters, domain divisions.
|
||||||
|
2. Separate concept content vs practice questions.
|
||||||
|
3. Map dependencies between topics.
|
||||||
|
4. Identify key patterns — comparisons, decision trees, formulas.
|
||||||
|
5. **Full topic checklist (MANDATORY)** — every topic/subtopic listed. Drives all subsequent phases.
|
||||||
|
|
||||||
|
> **Equal Depth Rule**: Even a briefly mentioned subtopic MUST get a full dedicated note supplemented with textbook-level knowledge.
|
||||||
|
|
||||||
|
6. **Classification completeness**: When source enumerates categories ("3 types of X"), every member gets a dedicated note. Scan for: "types of", "N가지", "categories", "there are N".
|
||||||
|
7. **Source-to-note cross-verification (MANDATORY)**: Record which source file(s) and page range(s) cover each topic. Flag untraceable topics as "source not available".
|
||||||
|
|
||||||
|
### Phase D3: Tag Standard
|
||||||
|
|
||||||
|
Define tag vocabulary before creating notes:
|
||||||
|
- **Format**: English, lowercase, kebab-case (e.g., `#data-hazard`)
|
||||||
|
- **Hierarchy**: top-level → domain → detail → technique → note-type
|
||||||
|
- **Registry**: Only registered tags allowed. Detail tags co-attach parent domain tag.
|
||||||
|
|
||||||
|
### Phase D4: Vault Structure
|
||||||
|
|
||||||
|
Create `StudyVault/` with numbered folders per [templates.md](references/templates.md). Group 3-5 related concepts per file.
|
||||||
|
|
||||||
|
### Phase D5: Dashboard Creation
|
||||||
|
|
||||||
|
Create `00-Dashboard/`: MOC, Quick Reference, Exam Traps. See [templates.md](references/templates.md).
|
||||||
|
|
||||||
|
- **MOC**: Topic Map + Practice Notes + Study Tools + Tag Index (with rules) + Weak Areas (with links) + Non-core Topic Policy
|
||||||
|
- **Quick Reference**: every heading includes `→ [[Concept Note]]` link; all key formulas
|
||||||
|
- **Exam Traps**: per-topic trap points in fold callouts, linked to concept notes
|
||||||
|
|
||||||
|
### Phase D6: Concept Notes
|
||||||
|
|
||||||
|
Per [templates.md](references/templates.md). Key rules:
|
||||||
|
- YAML frontmatter: `source_pdf`, `part`, `keywords` (MANDATORY)
|
||||||
|
- **source_pdf MUST match verified Phase D1 mapping** — never guess from filename
|
||||||
|
- If unavailable: `source_pdf: 원문 미보유`
|
||||||
|
- `[[wiki-links]]`, callouts (`[!tip]`, `[!important]`, `[!warning]`), comparison tables > prose
|
||||||
|
- ASCII diagrams for processes/flows/sequences
|
||||||
|
- **Simplification-with-exceptions**: general statements must note edge cases
|
||||||
|
|
||||||
|
### Phase D7: Practice Questions
|
||||||
|
|
||||||
|
Per [templates.md](references/templates.md). Key rules:
|
||||||
|
- Every topic folder MUST have a practice file (8+ questions)
|
||||||
|
- **Active recall**: answers use `> [!answer]- 정답 보기` fold callout
|
||||||
|
- Patterns use `> [!hint]-` / `> [!summary]-` fold callouts
|
||||||
|
- **Question type diversity**: ≥60% recall, ≥20% application, ≥2 analysis per file
|
||||||
|
- `## Related Concepts` with `[[wiki-links]]`
|
||||||
|
|
||||||
|
### Phase D8: Interlinking
|
||||||
|
|
||||||
|
1. `## Related Notes` on every concept note
|
||||||
|
2. MOC links to every concept + practice note
|
||||||
|
3. Cross-link concept ↔ practice; siblings reference each other
|
||||||
|
4. Quick Reference sections → `[[Concept Note]]` links
|
||||||
|
5. Weak Areas → relevant note + Exam Traps; Exam Traps → concept notes
|
||||||
|
|
||||||
|
### Phase D9: Self-Review (MANDATORY)
|
||||||
|
|
||||||
|
Verify against [quality-checklist.md](references/quality-checklist.md) **Document Mode** section. Fix and re-verify until all checks pass.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Codebase Mode
|
||||||
|
|
||||||
|
> Generates a new-developer onboarding StudyVault from a source code project.
|
||||||
|
> Full workflow: [codebase-workflow.md](references/codebase-workflow.md)
|
||||||
|
> Templates: [codebase-templates.md](references/codebase-templates.md)
|
||||||
|
|
||||||
|
### Phase Summary
|
||||||
|
|
||||||
|
| Phase | Name | Key Action |
|
||||||
|
|-------|------|------------|
|
||||||
|
| C1 | Project Exploration | Scan files, detect tech stack, read entry points, map directory layout |
|
||||||
|
| C2 | Architecture Analysis | Identify patterns, trace request flow, map module boundaries and data flow |
|
||||||
|
| C3 | Tag Standard | Define `#arch-*`, `#module-*`, `#pattern-*`, `#api-*` tag registry |
|
||||||
|
| C4 | Vault Structure | Create `StudyVault/` with Dashboard, Architecture, per-module, DevOps, Exercises folders |
|
||||||
|
| C5 | Dashboard | MOC (Module Map + API Surface + Getting Started + Onboarding Path) + Quick Reference |
|
||||||
|
| C6 | Module Notes | Per-module notes: Purpose, Key Files, Public Interface, Internal Flow, Dependencies |
|
||||||
|
| C7 | Onboarding Exercises | Code reading, configuration, debugging, extension exercises (5+ per major module) |
|
||||||
|
| C8 | Interlinking | Cross-link modules, architecture ↔ implementations, exercises ↔ modules |
|
||||||
|
| C9 | Self-Review | Verify against [quality-checklist.md](references/quality-checklist.md) **Codebase Mode** section |
|
||||||
|
|
||||||
|
See [codebase-workflow.md](references/codebase-workflow.md) for detailed per-phase instructions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Language
|
||||||
|
|
||||||
|
- Match source material language (Korean → Korean notes, etc.)
|
||||||
|
- **Tags/keywords**: ALWAYS English
|
||||||
276
.obsidian/plugins/skills/tutor-setup/references/codebase-templates.md
vendored
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
# Codebase Mode — Templates Reference
|
||||||
|
|
||||||
|
## Vault Folder Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
StudyVault/
|
||||||
|
00-Dashboard/ # MOC + Quick Reference + Getting Started
|
||||||
|
01-Architecture/ # System overview, request flow, data flow
|
||||||
|
02-<Module1>/ # Per-module notes
|
||||||
|
03-<Module2>/
|
||||||
|
...
|
||||||
|
NN-DevOps/ # Build, deploy, CI/CD, env config
|
||||||
|
NN+1-Exercises/ # Onboarding exercises
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dashboard MOC Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
module: dashboard
|
||||||
|
path: 00-Dashboard
|
||||||
|
keywords: MOC, onboarding, architecture, <project-name>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <Project Name> — Onboarding Map
|
||||||
|
|
||||||
|
#dashboard #onboarding
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
- Pattern: <architectural pattern>
|
||||||
|
- Tech stack: <languages, frameworks, key libraries>
|
||||||
|
- → [[System Architecture]]
|
||||||
|
- → [[Request Flow]]
|
||||||
|
|
||||||
|
## Module Map
|
||||||
|
| Module | Purpose | Key Entry Point | Notes |
|
||||||
|
|--------|---------|-----------------|-------|
|
||||||
|
| <name> | <1-line purpose> | `<path>` | [[Module Note]] |
|
||||||
|
|
||||||
|
## API Surface
|
||||||
|
| Method | Path / Command | Module | Notes |
|
||||||
|
|--------|---------------|--------|-------|
|
||||||
|
| GET | `/endpoint` | <module> | [[API Note]] |
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
1. Prerequisites: ...
|
||||||
|
2. Install: `<install command>`
|
||||||
|
3. Configure: copy `.env.example` → `.env`
|
||||||
|
4. Run: `<run command>`
|
||||||
|
5. Test: `<test command>`
|
||||||
|
|
||||||
|
## Tag Index
|
||||||
|
| Tag | Description | Rule |
|
||||||
|
|-----|-------------|------|
|
||||||
|
| `#arch-*` | Architecture concepts | Top-level pattern tags |
|
||||||
|
| `#module-*` | Module-specific | One per module |
|
||||||
|
|
||||||
|
## Onboarding Path
|
||||||
|
> Recommended reading order for new developers:
|
||||||
|
|
||||||
|
1. [[System Architecture]] — big picture
|
||||||
|
2. [[Request Flow]] — how a request moves through the system
|
||||||
|
3. [[Module A]] → [[Module B]] → ... — module deep dives
|
||||||
|
4. [[Exercises]] — hands-on practice
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Reference Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
module: dashboard
|
||||||
|
path: 00-Dashboard
|
||||||
|
keywords: quick-reference, commands, setup
|
||||||
|
---
|
||||||
|
|
||||||
|
# Quick Reference
|
||||||
|
|
||||||
|
#dashboard #quick-reference
|
||||||
|
|
||||||
|
## Key Commands
|
||||||
|
| Action | Command |
|
||||||
|
|--------|---------|
|
||||||
|
| Install deps | `<command>` |
|
||||||
|
| Run dev | `<command>` |
|
||||||
|
| Run tests | `<command>` |
|
||||||
|
| Build | `<command>` |
|
||||||
|
| Lint | `<command>` |
|
||||||
|
|
||||||
|
## Environment Setup
|
||||||
|
1. ...
|
||||||
|
|
||||||
|
## Important File Locations
|
||||||
|
| File / Dir | Purpose |
|
||||||
|
|------------|---------|
|
||||||
|
| `<path>` | <description> |
|
||||||
|
|
||||||
|
## Common Debugging
|
||||||
|
| Symptom | Where to Look | → Note |
|
||||||
|
|---------|---------------|--------|
|
||||||
|
| <problem> | `<file/log>` | [[Module Note]] |
|
||||||
|
```
|
||||||
|
|
||||||
|
## Module Note Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
module: <module-name>
|
||||||
|
path: <relative-path-from-project-root>
|
||||||
|
keywords: <3-5 English keywords>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <Module Name> (<Importance: ★~★★★>)
|
||||||
|
|
||||||
|
#module-<name> #<pattern-tag>
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
<1-3 sentences: what this module does and why it exists>
|
||||||
|
|
||||||
|
## Key Files
|
||||||
|
| File | Role |
|
||||||
|
|------|------|
|
||||||
|
| `<relative-path>` | <description> |
|
||||||
|
|
||||||
|
## Public Interface
|
||||||
|
| Export | Type | Description |
|
||||||
|
|--------|------|-------------|
|
||||||
|
| `<name>` | function/class/endpoint | <what it does> |
|
||||||
|
|
||||||
|
## Internal Flow
|
||||||
|
|
||||||
|
```text
|
||||||
|
<ASCII diagram showing data/control flow within this module>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
| Direction | Module / Service | Via |
|
||||||
|
|-----------|-----------------|-----|
|
||||||
|
| **Uses** | <dependency> | `<import/call>` |
|
||||||
|
| **Used by** | <dependent> | `<import/call>` |
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
| Env Var / Config Key | Purpose | Default |
|
||||||
|
|---------------------|---------|---------|
|
||||||
|
| `<VAR>` | <description> | `<default>` |
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
- Run: `<test command for this module>`
|
||||||
|
- Pattern: <unit/integration/e2e>
|
||||||
|
- Coverage notes: ...
|
||||||
|
|
||||||
|
## Related Notes
|
||||||
|
- [[Other Module]]
|
||||||
|
- [[Architecture Note]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## API Note Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
module: <module-name>
|
||||||
|
path: <relative-path>
|
||||||
|
keywords: API, <endpoint-keywords>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <Endpoint Group> API
|
||||||
|
|
||||||
|
#api-<group> #module-<name>
|
||||||
|
|
||||||
|
## Endpoints
|
||||||
|
| Method | Path | Auth | Description |
|
||||||
|
|--------|------|------|-------------|
|
||||||
|
| GET | `/path` | required | <description> |
|
||||||
|
|
||||||
|
## Request / Response
|
||||||
|
|
||||||
|
### <Endpoint Name>
|
||||||
|
|
||||||
|
**Request**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"field": "type — description"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response (success)**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"field": "type — description"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Error cases**:
|
||||||
|
| Status | Condition | Response |
|
||||||
|
|--------|-----------|----------|
|
||||||
|
| 400 | <condition> | `{ "error": "..." }` |
|
||||||
|
|
||||||
|
## Related Notes
|
||||||
|
- [[Module Note]]
|
||||||
|
- [[Other API Note]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Onboarding Exercise Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
module: exercises
|
||||||
|
path: <NN+1>-Exercises
|
||||||
|
keywords: practice, onboarding, <topic>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <Topic> — Onboarding Exercises
|
||||||
|
|
||||||
|
#practice #onboarding #module-<name>
|
||||||
|
|
||||||
|
## Related Modules
|
||||||
|
- [[Module Note 1]]
|
||||||
|
- [[Module Note 2]]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercise 1 — Code Reading [trace]
|
||||||
|
> Trace what happens when <specific trigger>. List the files and functions involved in order.
|
||||||
|
|
||||||
|
> [!answer]- View Answer
|
||||||
|
> 1. `<file>` → `<function>` — <what happens>
|
||||||
|
> 2. `<file>` → `<function>` — <what happens>
|
||||||
|
> 3. ...
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercise 2 — Configuration [config]
|
||||||
|
> How would you change <specific setting>? Which files need modification?
|
||||||
|
|
||||||
|
> [!answer]- View Answer
|
||||||
|
> - File: `<path>`
|
||||||
|
> - Change: <description>
|
||||||
|
> - Related env var: `<VAR>`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercise 3 — Debugging [debug]
|
||||||
|
> If <symptom> occurs, where would you look first? Describe your investigation steps.
|
||||||
|
|
||||||
|
> [!answer]- View Answer
|
||||||
|
> 1. Check `<file/log>` for ...
|
||||||
|
> 2. Verify `<config>` is ...
|
||||||
|
> 3. Common cause: ...
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exercise 4 — Extension [extend]
|
||||||
|
> How would you add <new feature/endpoint>? Describe the files you'd create or modify.
|
||||||
|
|
||||||
|
> [!answer]- View Answer
|
||||||
|
> 1. Create `<path>` — <purpose>
|
||||||
|
> 2. Modify `<path>` — <what to add>
|
||||||
|
> 3. Add test in `<path>` — <what to test>
|
||||||
|
> 4. Register in `<path>` — <wiring>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> [!summary]- 학습 포인트 요약
|
||||||
|
> | Topic | Key Takeaway |
|
||||||
|
> |-------|-------------|
|
||||||
|
> | <topic> | <insight> |
|
||||||
|
```
|
||||||
|
|
||||||
|
## Formatting Rules
|
||||||
|
|
||||||
|
- `[[wiki-links]]` for all cross-references
|
||||||
|
- `> [!tip]`, `> [!important]`, `> [!warning]` callouts for key information
|
||||||
|
- ASCII diagrams for flows, architecture, and module interactions
|
||||||
|
- Tables over prose for structured information
|
||||||
|
- **Bold** for critical terms and file paths in descriptions
|
||||||
|
- Code blocks with language hints for commands and snippets
|
||||||
|
- **Localization**: Fold callout labels (e.g., `View Answer`) should match team language. Korean: `정답 보기`, English: `View Answer`
|
||||||
96
.obsidian/plugins/skills/tutor-setup/references/codebase-workflow.md
vendored
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# Codebase Mode — Onboarding Vault Workflow
|
||||||
|
|
||||||
|
> Generates a StudyVault that helps new developers understand and navigate a source code project.
|
||||||
|
> All scanning and output MUST stay within CWD.
|
||||||
|
|
||||||
|
## Phase C1: Project Exploration
|
||||||
|
|
||||||
|
1. **Scan project structure**: `Glob` for source files, config files, test files. Build a file tree.
|
||||||
|
2. **Identify tech stack**: Detect languages, frameworks, build tools, package managers from config files.
|
||||||
|
3. **Read key files**: README, CONTRIBUTING, entry points (`main.*`, `index.*`, `app.*`), config files.
|
||||||
|
4. **Map project layout**: Record directory purposes (e.g., `src/`, `test/`, `config/`, `scripts/`).
|
||||||
|
5. **Present findings** to user for confirmation before proceeding.
|
||||||
|
|
||||||
|
## Phase C2: Architecture Analysis
|
||||||
|
|
||||||
|
1. **Identify architectural patterns**: layered, hexagonal, microservice, monolith, serverless, etc.
|
||||||
|
2. **Map module boundaries**: Which directories/packages form distinct modules or domains?
|
||||||
|
3. **Trace request flow**: For a typical request (HTTP, event, CLI), trace the path through the code.
|
||||||
|
4. **Identify key abstractions**: Interfaces, base classes, shared utilities, middleware, interceptors.
|
||||||
|
5. **Map dependencies**: Internal module dependencies + external service integrations.
|
||||||
|
6. **Document data flow**: How data enters, transforms, persists, and exits the system.
|
||||||
|
7. **Build architecture summary**: Create a concise diagram (ASCII) + description for the vault.
|
||||||
|
|
||||||
|
## Phase C3: Tag Standard
|
||||||
|
|
||||||
|
Define tag vocabulary before creating notes:
|
||||||
|
- **Format**: English, lowercase, kebab-case
|
||||||
|
- **Categories**: `#arch-*` (architecture), `#module-*` (modules), `#pattern-*` (patterns), `#config-*` (config), `#api-*` (API), `#test-*` (testing)
|
||||||
|
- **Registry**: Only registered tags allowed. Present registry to user for approval.
|
||||||
|
|
||||||
|
## Phase C4: Vault Structure
|
||||||
|
|
||||||
|
Create `StudyVault/` per [codebase-templates.md](codebase-templates.md) folder structure:
|
||||||
|
- `00-Dashboard/` — MOC, Quick Reference, Getting Started
|
||||||
|
- `01-Architecture/` — System overview, request flow, data flow
|
||||||
|
- `02-XX/` through `NN-XX/` — One folder per module/domain
|
||||||
|
- `NN+1-DevOps/` — Build, deploy, CI/CD, environment config
|
||||||
|
- `NN+2-Exercises/` — Onboarding exercises
|
||||||
|
|
||||||
|
## Phase C5: Dashboard Creation
|
||||||
|
|
||||||
|
Create `00-Dashboard/` with:
|
||||||
|
|
||||||
|
### MOC (Map of Content)
|
||||||
|
- **Architecture Overview**: Link to architecture notes
|
||||||
|
- **Module Map**: Table of all modules with purpose + links
|
||||||
|
- **API Surface**: Summary of endpoints/commands/events
|
||||||
|
- **Getting Started**: Setup instructions, dev workflow, key commands
|
||||||
|
- **Tag Index**: Tag registry with hierarchy rules
|
||||||
|
- **Onboarding Path**: Recommended reading order for new developers
|
||||||
|
|
||||||
|
### Quick Reference
|
||||||
|
- Key commands (build, test, deploy, lint)
|
||||||
|
- Environment setup steps
|
||||||
|
- Common debugging tips
|
||||||
|
- Important file locations
|
||||||
|
|
||||||
|
## Phase C6: Module Notes
|
||||||
|
|
||||||
|
One note per module/domain. Per [codebase-templates.md](codebase-templates.md). Key rules:
|
||||||
|
|
||||||
|
- YAML frontmatter: `module`, `path`, `keywords` (MANDATORY)
|
||||||
|
- **Purpose**: What this module does (1-3 sentences)
|
||||||
|
- **Key Files**: Table of important files with descriptions
|
||||||
|
- **Public Interface**: Exported functions/classes/endpoints
|
||||||
|
- **Internal Flow**: How data moves through this module (ASCII diagram)
|
||||||
|
- **Dependencies**: What this module depends on + what depends on it
|
||||||
|
- **Configuration**: Relevant env vars, config keys
|
||||||
|
- **Testing**: How to run tests for this module, test patterns used
|
||||||
|
- **Related Notes**: Links to related modules and architecture notes
|
||||||
|
|
||||||
|
For API-heavy modules, create separate API notes per [codebase-templates.md](codebase-templates.md).
|
||||||
|
|
||||||
|
## Phase C7: Onboarding Exercises
|
||||||
|
|
||||||
|
Create exercises that guide new developers through the codebase. Per [codebase-templates.md](codebase-templates.md).
|
||||||
|
|
||||||
|
- **Code Reading**: "Trace what happens when X occurs" — answer in fold callout
|
||||||
|
- **Configuration**: "How would you change Y?" — answer with file paths + snippets
|
||||||
|
- **Debugging**: "Where would you look if Z breaks?" — answer with investigation steps
|
||||||
|
- **Extension**: "How would you add feature W?" — answer with architectural approach
|
||||||
|
- Minimum 5 exercises per major module
|
||||||
|
- All answers use `> [!answer]- <label>` fold callout (localize label to team language, e.g., "정답 보기" for Korean, "View Answer" for English)
|
||||||
|
|
||||||
|
## Phase C8: Interlinking
|
||||||
|
|
||||||
|
1. `## Related Notes` on every module note
|
||||||
|
2. MOC links to every module note + exercise file
|
||||||
|
3. Cross-link modules that depend on each other
|
||||||
|
4. Architecture notes reference specific module implementations
|
||||||
|
5. Exercises reference the modules they cover
|
||||||
|
6. Quick Reference links to relevant module notes
|
||||||
|
|
||||||
|
## Phase C9: Self-Review (MANDATORY)
|
||||||
|
|
||||||
|
Verify against [quality-checklist.md](quality-checklist.md) **Codebase Mode** section. Fix and re-verify until all checks pass.
|
||||||
106
.obsidian/plugins/skills/tutor-setup/references/quality-checklist.md
vendored
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# Quality Checklist — Self-Review
|
||||||
|
|
||||||
|
Before reporting completion, verify every item in the relevant mode's section. Fix and re-verify if any check fails.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Document Mode
|
||||||
|
|
||||||
|
### Source Traceability
|
||||||
|
- [ ] Every source file's content verified (not filename-based assumption)
|
||||||
|
- [ ] Source content mapping table built and verified in Phase D1
|
||||||
|
- [ ] Every `source_pdf` frontmatter matches verified mapping
|
||||||
|
- [ ] Non-academic files excluded and documented
|
||||||
|
- [ ] Missing sources marked as `원문 미보유`
|
||||||
|
- [ ] Non-core topic policy documented in MOC
|
||||||
|
|
||||||
|
### Coverage
|
||||||
|
- [ ] Every topic from Phase D2 checklist has a concept note
|
||||||
|
- [ ] Every enumerated category member has its own note
|
||||||
|
- [ ] No source topic missing or underrepresented
|
||||||
|
|
||||||
|
### Tags
|
||||||
|
- [ ] All tags: English kebab-case, from registry only
|
||||||
|
- [ ] Tag Index includes hierarchy rules
|
||||||
|
- [ ] Detail tags co-attached with parent domain tags
|
||||||
|
|
||||||
|
### Structure & Formatting
|
||||||
|
- [ ] Every note has YAML frontmatter: `source_pdf`, `part`, `keywords`
|
||||||
|
- [ ] Every concept note has comparison table + exam/test patterns section
|
||||||
|
- [ ] Process/flow topics have ASCII diagrams
|
||||||
|
- [ ] Notes are concise (tables > prose)
|
||||||
|
- [ ] Simplified statements include exception caveats
|
||||||
|
|
||||||
|
### Dashboard
|
||||||
|
- [ ] MOC: Topic Map + Practice Notes + Study Tools + Tag Index + Weak Areas + Non-core Policy
|
||||||
|
- [ ] MOC links to every concept note AND practice note
|
||||||
|
- [ ] Weak Areas link to `→ [[note]]` AND `→ [[Exam Traps]]`
|
||||||
|
- [ ] Exam Traps exists with per-topic fold callouts and bidirectional links
|
||||||
|
|
||||||
|
### Quick Reference
|
||||||
|
- [ ] All key formulas and condition expressions included
|
||||||
|
- [ ] Every section links to concept note via `→ [[Note]]`
|
||||||
|
|
||||||
|
### Practice — Active Recall
|
||||||
|
- [ ] Every topic folder has practice file (8+ questions)
|
||||||
|
- [ ] All answers use `> [!answer]- 정답 보기` fold — never immediately visible
|
||||||
|
- [ ] Key Patterns: `> [!hint]-` fold; Pattern Summary: `> [!summary]-` fold
|
||||||
|
- [ ] `## Related Concepts` with backlinks in every practice file
|
||||||
|
- [ ] Question type diversity: ≥60% recall, ≥20% application, ≥2 analysis per file
|
||||||
|
|
||||||
|
### Interlinking
|
||||||
|
- [ ] Every concept note has `## Related Notes`
|
||||||
|
- [ ] `[[wiki-links]]` for all cross-references
|
||||||
|
- [ ] Siblings reference each other; concept ↔ practice cross-linked
|
||||||
|
- [ ] Exam Traps ↔ Concept notes bidirectionally linked
|
||||||
|
|
||||||
|
### CWD Boundary
|
||||||
|
- [ ] No source files accessed outside CWD
|
||||||
|
- [ ] No absolute file paths in notes or frontmatter
|
||||||
|
- [ ] External URLs accessed only via WebFetch, not file paths
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Codebase Mode
|
||||||
|
|
||||||
|
### Project Coverage
|
||||||
|
- [ ] All major modules/domains identified and documented
|
||||||
|
- [ ] Architecture pattern documented with ASCII diagram
|
||||||
|
- [ ] Request flow traced end-to-end
|
||||||
|
- [ ] Data flow documented (input → processing → persistence → output)
|
||||||
|
- [ ] External dependencies and integrations listed
|
||||||
|
|
||||||
|
### Module Completeness
|
||||||
|
- [ ] Every module has a dedicated note with YAML frontmatter (`module`, `path`, `keywords`)
|
||||||
|
- [ ] Every module note includes: Purpose, Key Files, Public Interface, Internal Flow, Dependencies
|
||||||
|
- [ ] Configuration section lists relevant env vars / config keys
|
||||||
|
- [ ] Testing section includes commands and patterns
|
||||||
|
|
||||||
|
### Tags
|
||||||
|
- [ ] All tags: English kebab-case, from registry only
|
||||||
|
- [ ] Tag Index in MOC with hierarchy rules
|
||||||
|
- [ ] Tags cover: `#arch-*`, `#module-*`, `#pattern-*`, `#api-*`
|
||||||
|
|
||||||
|
### Dashboard
|
||||||
|
- [ ] MOC: Architecture Overview + Module Map + API Surface + Getting Started + Tag Index + Onboarding Path
|
||||||
|
- [ ] MOC links to every module note and exercise file
|
||||||
|
- [ ] Quick Reference: key commands, env setup, file locations, debugging tips
|
||||||
|
- [ ] Getting Started section is actionable (copy-paste commands)
|
||||||
|
|
||||||
|
### Onboarding Exercises
|
||||||
|
- [ ] Minimum 5 exercises per major module
|
||||||
|
- [ ] Exercise types: code reading (trace), configuration, debugging, extension
|
||||||
|
- [ ] All answers use `> [!answer]- 정답 보기` fold callout
|
||||||
|
- [ ] Exercises reference relevant module notes via `[[wiki-links]]`
|
||||||
|
|
||||||
|
### Interlinking
|
||||||
|
- [ ] Every module note has `## Related Notes`
|
||||||
|
- [ ] `[[wiki-links]]` for all cross-references
|
||||||
|
- [ ] Dependent modules cross-linked bidirectionally
|
||||||
|
- [ ] Architecture notes reference specific module implementations
|
||||||
|
- [ ] Exercises link back to the modules they cover
|
||||||
|
|
||||||
|
### CWD Boundary
|
||||||
|
- [ ] No references to files outside the project directory
|
||||||
|
- [ ] All file paths in notes are relative to project root
|
||||||
|
- [ ] No hardcoded absolute paths
|
||||||
213
.obsidian/plugins/skills/tutor-setup/references/templates.md
vendored
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
# Templates Reference
|
||||||
|
|
||||||
|
## Vault Folder Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
StudyVault/
|
||||||
|
00-Dashboard/ # MOC + cheat sheets + Exam Traps
|
||||||
|
01-<Topic1>/ # Concept notes per domain
|
||||||
|
02-<Topic2>/
|
||||||
|
...
|
||||||
|
NN-문제풀이/ (or Practice/)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dashboard MOC Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
source_pdf: <list all source files>
|
||||||
|
part: <part numbers or "all">
|
||||||
|
keywords: MOC, study map, <subject>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <Subject> Study Map
|
||||||
|
|
||||||
|
#dashboard #<subject-tag>
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
- Exam/certification info (if applicable)
|
||||||
|
- Domain weights or topic importance
|
||||||
|
|
||||||
|
## Topic Map
|
||||||
|
| Section | Source | Notes | Status |
|
||||||
|
|---------|--------|-------|--------|
|
||||||
|
| Topic 1 | Part 1 | [[Note 1]], [[Note 2]] | [ ] |
|
||||||
|
|
||||||
|
## Practice Notes
|
||||||
|
| 문제셋 | 문항 수 | 링크 |
|
||||||
|
|--------|---------|------|
|
||||||
|
| Topic 1 | N문제 | [[Topic 1 Practice]] |
|
||||||
|
|
||||||
|
## Study Tools
|
||||||
|
| 도구 | 설명 | 링크 |
|
||||||
|
|------|------|------|
|
||||||
|
| Exam Traps | 시험 함정/오답 포인트 모음 | [[Exam Traps]] |
|
||||||
|
| Quick Reference | 전체 치트시트 | [[빠른 참조]] |
|
||||||
|
|
||||||
|
## Tag Index
|
||||||
|
| Tag | 관련 주제 | 규칙 |
|
||||||
|
|-----|-----------|------|
|
||||||
|
| `#tag-name` | Brief description | 상위/도메인/세부/기법/유형 |
|
||||||
|
|
||||||
|
> **태그 규칙**: <1-line summary of hierarchy rule>
|
||||||
|
|
||||||
|
## Weak Areas
|
||||||
|
- [ ] Area needing review → [[Relevant Note]] → [[Exam Traps]]
|
||||||
|
|
||||||
|
## Non-core Topic Policy
|
||||||
|
| Source | Content | Handling |
|
||||||
|
|--------|---------|----------|
|
||||||
|
| <file> | <description> | **Excluded** — reason |
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Reference Template
|
||||||
|
|
||||||
|
- **Every section heading MUST include `→ [[Concept Note]]` link**
|
||||||
|
- One-line summary table per concept/term
|
||||||
|
- Grouped by category
|
||||||
|
- All key formulas and condition expressions
|
||||||
|
- "Must-know formulas/patterns" section at bottom with `→ [[Note]]` links
|
||||||
|
|
||||||
|
## Exam Traps Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
keywords: exam traps, weak areas, common mistakes
|
||||||
|
---
|
||||||
|
|
||||||
|
# Exam Traps (시험 함정 포인트)
|
||||||
|
|
||||||
|
#dashboard #exam-traps
|
||||||
|
|
||||||
|
> [!warning] 이 노트의 목적
|
||||||
|
> 시험에서 자주 틀리거나 헷갈리는 포인트만 모은 **오답/함정 노트**입니다.
|
||||||
|
|
||||||
|
## <Topic 1>
|
||||||
|
|
||||||
|
> [!danger]- Trap: <Short description>
|
||||||
|
> - <What the trap is>
|
||||||
|
> - <Why it's confusing>
|
||||||
|
> - <The correct answer/approach>
|
||||||
|
> - [[Related Concept Note]]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Related
|
||||||
|
- [[MOC - <Subject>]] → Weak Areas 섹션
|
||||||
|
- [[빠른 참조]]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Concept Note Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
source_pdf: <filename.pdf — MUST match verified Phase 1 mapping>
|
||||||
|
part: <part number>
|
||||||
|
keywords: <3-5 English keywords>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <Title> (<Importance: ★~★★★>)
|
||||||
|
|
||||||
|
#<tag-from-registry> #<tag-from-registry>
|
||||||
|
|
||||||
|
## Overview Table (한눈에 비교)
|
||||||
|
| Item | Key Point |
|
||||||
|
|------|-----------|
|
||||||
|
| A | ... |
|
||||||
|
|
||||||
|
## <Concept 1>
|
||||||
|
Concise explanation (3-5 lines max).
|
||||||
|
- Bullet points for key facts
|
||||||
|
- Use **bold** for critical terms
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Exam/Test Patterns (시험 빈출 패턴)
|
||||||
|
| Scenario/Keyword | Answer |
|
||||||
|
|-------------------|--------|
|
||||||
|
| "keyword X" | **Solution Y** |
|
||||||
|
|
||||||
|
## Related Notes
|
||||||
|
- [[Other Note 1]]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Formatting Rules
|
||||||
|
|
||||||
|
- `[[wiki-links]]` for cross-references
|
||||||
|
- `> [!tip]`, `> [!important]`, `> [!warning]` callouts
|
||||||
|
- Comparison tables over prose; bold for key vocabulary
|
||||||
|
|
||||||
|
### Visualization Rule
|
||||||
|
|
||||||
|
Include ASCII diagrams when applicable:
|
||||||
|
- Processes/stages → timeline or sequence diagram
|
||||||
|
- Signal/data flow → flow DAG
|
||||||
|
- Strategy comparisons → quantitative table
|
||||||
|
- State-based behavior → state transition diagram
|
||||||
|
|
||||||
|
### Simplification-with-Exceptions Rule
|
||||||
|
|
||||||
|
General statements must check for edge cases — add `> [!warning]` or link to exception details.
|
||||||
|
|
||||||
|
## Practice Question Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
source_pdf: <filename.pdf — MUST match verified Phase 1 mapping>
|
||||||
|
part: <part number>
|
||||||
|
keywords: practice, <topic keywords>
|
||||||
|
---
|
||||||
|
|
||||||
|
# <Topic> Practice (N questions)
|
||||||
|
|
||||||
|
#practice #<topic-tag>
|
||||||
|
|
||||||
|
## Related Concepts
|
||||||
|
- [[Concept Note 1]]
|
||||||
|
|
||||||
|
> [!hint]- 핵심 패턴 (클릭하여 보기)
|
||||||
|
> | Keyword | Answer |
|
||||||
|
> |---------|--------|
|
||||||
|
> | pattern 1 | **Solution** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question 1 - <Short Label> [recall]
|
||||||
|
> Scenario summary in one line
|
||||||
|
|
||||||
|
> [!answer]- 정답 보기
|
||||||
|
> Answer text here with explanation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question 2 - <Short Label> [application]
|
||||||
|
> Given this scenario, what would you do?
|
||||||
|
|
||||||
|
> [!answer]- 정답 보기
|
||||||
|
> Answer with applied reasoning.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Question 3 - <Short Label> [analysis]
|
||||||
|
> Compare X and Y in this context. Which is better and why?
|
||||||
|
|
||||||
|
> [!answer]- 정답 보기
|
||||||
|
> Comparative analysis answer.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
> [!summary]- 패턴 요약 (클릭하여 보기)
|
||||||
|
> | Keyword | Answer |
|
||||||
|
> |---------|--------|
|
||||||
|
> | ... | ... |
|
||||||
|
```
|
||||||
|
|
||||||
|
### Practice Question Rules
|
||||||
|
|
||||||
|
- Every topic folder MUST have a practice file (8+ questions)
|
||||||
|
- **Answer hiding**: ALL answers use `> [!answer]- 정답 보기` fold callout
|
||||||
|
- **Patterns**: `> [!hint]-` / `> [!summary]-` fold callouts (MANDATORY)
|
||||||
|
- **Question type diversity**: tag `[recall]`, `[application]`, `[analysis]` in heading
|
||||||
|
- ≥60% recall, ≥20% application, ≥2 analysis per file
|
||||||
|
- Scenario in one `>` blockquote line; answer 1-3 lines in fold
|
||||||
|
- `## Related Concepts` with `[[wiki-links]]` (MANDATORY)
|
||||||
166
.obsidian/plugins/skills/tutor/SKILL.md
vendored
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
---
|
||||||
|
name: tutor
|
||||||
|
description: >
|
||||||
|
Interactive quiz tutor for Obsidian StudyVault learning. Use when the user wants to:
|
||||||
|
(1) Take a diagnostic assessment of their knowledge,
|
||||||
|
(2) Study or review specific sections/topics,
|
||||||
|
(3) Drill weak areas identified in previous sessions,
|
||||||
|
(4) Check their learning progress or dashboard,
|
||||||
|
or says things like "quiz me", "test me", "let's study", "/tutor", "학습", "퀴즈", "평가".
|
||||||
|
---
|
||||||
|
|
||||||
|
# Tutor Skill
|
||||||
|
|
||||||
|
Quiz-based tutor that tracks what the user knows and doesn't know at the **concept level**. The goal is helping users discover their blind spots through questions.
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
StudyVault/
|
||||||
|
├── *dashboard* ← Compact overview: proficiency table + stats
|
||||||
|
└── concepts/
|
||||||
|
├── {area-name}.md ← Per-area concept tracking (attempts, status, error notes)
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Dashboard**: Only aggregated numbers. Links to concept files. Stays small forever.
|
||||||
|
- **Concept files**: One per area. Tracks each concept with attempts, correct count, date, status, and error notes. Grows proportionally to unique concepts tested (bounded).
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
### Phase 0: Detect Language
|
||||||
|
|
||||||
|
Detect user's language from their message → `{LANG}`. All output and file content in `{LANG}`.
|
||||||
|
|
||||||
|
### Phase 1: Discover Vault
|
||||||
|
|
||||||
|
1. Glob `**/StudyVault/` in project
|
||||||
|
2. List section directories
|
||||||
|
3. Glob `**/StudyVault/*dashboard*` to find dashboard
|
||||||
|
4. If found, read it. Preserve existing file path regardless of language.
|
||||||
|
5. If not found, create from template (see Dashboard Template below)
|
||||||
|
|
||||||
|
If no StudyVault exists, inform user and stop.
|
||||||
|
|
||||||
|
### Phase 2: Ask Session Type
|
||||||
|
|
||||||
|
**MANDATORY**: Use AskUserQuestion to let the user choose what to do. Analyze the dashboard to build context-aware options, then present them.
|
||||||
|
|
||||||
|
Read the dashboard proficiency table and build options based on current state:
|
||||||
|
|
||||||
|
1. If unmeasured areas (⬜) exist → include "Diagnostic" option targeting those areas
|
||||||
|
2. If weak areas (🟥/🟨) exist → include "Drill weak areas" option naming the weakest area(s)
|
||||||
|
3. Always include "Choose a section" option so the user can pick any area
|
||||||
|
4. If all areas are 🟩/🟦 → include "Hard-mode review" option
|
||||||
|
|
||||||
|
Present these as an AskUserQuestion with header "Session" and concise descriptions showing which areas each option targets. The user MUST select before proceeding.
|
||||||
|
|
||||||
|
### Phase 3: Build Questions
|
||||||
|
|
||||||
|
1. Read markdown files in target section(s)
|
||||||
|
2. If drilling weak area: also read `concepts/{area}.md` to find 🔴 unresolved concepts — rephrase these in new contexts (don't repeat the same question)
|
||||||
|
3. Craft exactly 4 questions following `references/quiz-rules.md`
|
||||||
|
|
||||||
|
**CRITICAL**: Read `references/quiz-rules.md` before crafting ANY question. Zero hints allowed.
|
||||||
|
|
||||||
|
### Phase 4: Present Quiz
|
||||||
|
|
||||||
|
Use AskUserQuestion:
|
||||||
|
- 4 questions, 4 options each, single-select
|
||||||
|
- Header: "Q1. Topic" (max 12 chars)
|
||||||
|
- Descriptions: neutral, no hints
|
||||||
|
|
||||||
|
### Phase 5: Grade & Explain
|
||||||
|
|
||||||
|
1. Show results table (question / correct answer / user answer / result)
|
||||||
|
2. Wrong answers: concise explanation
|
||||||
|
3. Map each question to its area
|
||||||
|
|
||||||
|
### Phase 6: Update Files
|
||||||
|
|
||||||
|
#### 1. Update concept file (`concepts/{area}.md`)
|
||||||
|
|
||||||
|
For each question answered:
|
||||||
|
- **New concept**: Add row to table + if wrong, add error note under `### 오답 메모` (or localized equivalent)
|
||||||
|
- **Existing 🔴 concept answered correctly**: Increment attempts & correct, change status to 🟢, keep error note (learning history)
|
||||||
|
- **Existing 🟢 concept answered wrong again**: Increment attempts, change status back to 🔴, update error note
|
||||||
|
|
||||||
|
Table format:
|
||||||
|
```markdown
|
||||||
|
| Concept | Attempts | Correct | Last Tested | Status |
|
||||||
|
|---------|----------|---------|-------------|--------|
|
||||||
|
| concept name | 2 | 1 | 2026-02-24 | 🔴 |
|
||||||
|
```
|
||||||
|
|
||||||
|
Error notes format (only for wrong answers):
|
||||||
|
```markdown
|
||||||
|
### Error Notes
|
||||||
|
|
||||||
|
**concept name**
|
||||||
|
- Confusion: what the user mixed up
|
||||||
|
- Key point: the correct understanding
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Update dashboard
|
||||||
|
|
||||||
|
- Recalculate per-area stats from concept files (sum attempts/correct across all concepts in that area)
|
||||||
|
- Update proficiency badges: 🟥 0-39% · 🟨 40-69% · 🟩 70-89% · 🟦 90-100% · ⬜ no data
|
||||||
|
- Update stats: total questions, cumulative rate, unresolved/resolved counts, weakest/strongest
|
||||||
|
|
||||||
|
Dashboard stays compact — no session logs, no per-question details.
|
||||||
|
|
||||||
|
## Dashboard Template
|
||||||
|
|
||||||
|
Create when no dashboard exists. Filename localized to `{LANG}`. Example in English:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Learning Dashboard
|
||||||
|
|
||||||
|
> Concept-based metacognition tracking. See linked files for details.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Proficiency by Area
|
||||||
|
|
||||||
|
| Area | Correct | Wrong | Rate | Level | Details |
|
||||||
|
|------|---------|-------|------|-------|---------|
|
||||||
|
(one row per section, last column = [[concepts/{area}]] link)
|
||||||
|
| **Total** | **0** | **0** | **-** | ⬜ Unmeasured | |
|
||||||
|
|
||||||
|
> 🟥 Weak (0-39%) · 🟨 Fair (40-69%) · 🟩 Good (70-89%) · 🟦 Mastered (90-100%) · ⬜ Unmeasured
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Stats
|
||||||
|
|
||||||
|
- **Total Questions**: 0
|
||||||
|
- **Cumulative Rate**: -
|
||||||
|
- **Unresolved Concepts**: 0
|
||||||
|
- **Resolved Concepts**: 0
|
||||||
|
- **Weakest Area**: -
|
||||||
|
- **Strongest Area**: -
|
||||||
|
```
|
||||||
|
|
||||||
|
## Concept File Template
|
||||||
|
|
||||||
|
Create per area when first question is asked. Example:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# {Area Name} — Concept Tracker
|
||||||
|
|
||||||
|
| Concept | Attempts | Correct | Last Tested | Status |
|
||||||
|
|---------|----------|---------|-------------|--------|
|
||||||
|
|
||||||
|
### Error Notes
|
||||||
|
|
||||||
|
(added as concepts are missed)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Important Reminders
|
||||||
|
|
||||||
|
- ALWAYS read `references/quiz-rules.md` before creating questions
|
||||||
|
- NEVER include hints in option labels or descriptions
|
||||||
|
- NEVER use "(Recommended)" on any option
|
||||||
|
- Randomize correct answer position
|
||||||
|
- After grading, ALWAYS update both concept file AND dashboard
|
||||||
|
- Communicate in user's language
|
||||||
56
.obsidian/plugins/skills/tutor/references/quiz-rules.md
vendored
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Quiz Design Rules
|
||||||
|
|
||||||
|
## Zero-Hint Policy (CRITICAL)
|
||||||
|
|
||||||
|
Every question must be answerable ONLY by someone who actually knows the material.
|
||||||
|
|
||||||
|
1. **Option descriptions**: NEVER reveal correctness
|
||||||
|
- BAD: `label: "stderr"`, `description: "Error output stream used by Cloud Run for error classification"`
|
||||||
|
- GOOD: `label: "stderr"`, `description: "Standard error stream"`
|
||||||
|
|
||||||
|
2. **No "(Recommended)" tag** on any option
|
||||||
|
|
||||||
|
3. **Randomize** correct answer position — never always first or last
|
||||||
|
|
||||||
|
4. **Question phrasing**: Ask about behavior/purpose/output, don't hint at the answer
|
||||||
|
- BAD: "Which error stream does error() use?"
|
||||||
|
- GOOD: "Where does error() method output go?"
|
||||||
|
|
||||||
|
5. **Plausible distractors**: Wrong options must be real concepts from the domain, representing common misconceptions
|
||||||
|
|
||||||
|
## Question Types
|
||||||
|
|
||||||
|
1. **Factual recall**: "What HTTP status code is returned when...?"
|
||||||
|
2. **Conceptual understanding**: "Why does the system use X pattern?"
|
||||||
|
3. **Behavioral prediction**: "What happens when X fails?"
|
||||||
|
4. **Comparison/distinction**: "What is the difference between X and Y?"
|
||||||
|
5. **Debugging scenario**: "Given this error, what is the most likely cause?"
|
||||||
|
|
||||||
|
## Difficulty Balancing
|
||||||
|
|
||||||
|
- Diagnostic: easy 40%, medium 40%, hard 20%
|
||||||
|
- Weak-area drill: medium 30%, hard 70%
|
||||||
|
- Review: all levels evenly
|
||||||
|
|
||||||
|
## Drilling Unresolved Concepts
|
||||||
|
|
||||||
|
When targeting 🔴 concepts from concept files:
|
||||||
|
- Do NOT repeat the exact same question — rephrase in a new context
|
||||||
|
- Test the same underlying knowledge from a different angle
|
||||||
|
- E.g., if user confused "400 vs 422", ask a scenario question where they must choose the correct status code for a new situation
|
||||||
|
|
||||||
|
## AskUserQuestion Format
|
||||||
|
|
||||||
|
- 4 questions per round, 4 options each, single-select
|
||||||
|
- Header: max 12 chars, "Q1. Topic"
|
||||||
|
|
||||||
|
## File Update Protocol
|
||||||
|
|
||||||
|
After grading:
|
||||||
|
1. Update `concepts/{area}.md` — add/update concept rows + error notes
|
||||||
|
2. Update dashboard — recalculate area stats from concept files
|
||||||
|
3. Badges: 🟥 0-39% · 🟨 40-69% · 🟩 70-89% · 🟦 90-100% · ⬜ no data
|
||||||
|
|
||||||
|
## Language Rule
|
||||||
|
|
||||||
|
All file content and output in the user's detected language. Badge emojis are universal.
|
||||||
205
.obsidian/workspace.json
vendored
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
{
|
||||||
|
"main": {
|
||||||
|
"id": "20ab3985534ea7db",
|
||||||
|
"type": "split",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "1aaef1a93738f90e",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "5aba4d48771b46d1",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "markdown",
|
||||||
|
"state": {
|
||||||
|
"file": "创建链接.md",
|
||||||
|
"mode": "source",
|
||||||
|
"source": false
|
||||||
|
},
|
||||||
|
"icon": "lucide-file",
|
||||||
|
"title": "创建链接"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"direction": "vertical"
|
||||||
|
},
|
||||||
|
"left": {
|
||||||
|
"id": "a064bf8c683753c9",
|
||||||
|
"type": "split",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "b8bac1eb6b931e6f",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "48717814ec87547e",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "file-explorer",
|
||||||
|
"state": {
|
||||||
|
"sortOrder": "alphabetical",
|
||||||
|
"autoReveal": false
|
||||||
|
},
|
||||||
|
"icon": "lucide-folder-closed",
|
||||||
|
"title": "文件列表"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6ae1f97d242450ab",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "search",
|
||||||
|
"state": {
|
||||||
|
"query": "",
|
||||||
|
"matchingCase": false,
|
||||||
|
"explainSearch": false,
|
||||||
|
"collapseAll": false,
|
||||||
|
"extraContext": false,
|
||||||
|
"sortOrder": "alphabetical"
|
||||||
|
},
|
||||||
|
"icon": "lucide-search",
|
||||||
|
"title": "搜索"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9800cac4ea8e1573",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "bookmarks",
|
||||||
|
"state": {},
|
||||||
|
"icon": "lucide-bookmark",
|
||||||
|
"title": "书签"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"direction": "horizontal",
|
||||||
|
"width": 300
|
||||||
|
},
|
||||||
|
"right": {
|
||||||
|
"id": "6dc9652859747502",
|
||||||
|
"type": "split",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "39931e98bc970ff1",
|
||||||
|
"type": "tabs",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "f93571f7e02595f8",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "backlink",
|
||||||
|
"state": {
|
||||||
|
"collapseAll": false,
|
||||||
|
"extraContext": false,
|
||||||
|
"sortOrder": "alphabetical",
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": "",
|
||||||
|
"backlinkCollapsed": false,
|
||||||
|
"unlinkedCollapsed": true
|
||||||
|
},
|
||||||
|
"icon": "links-coming-in",
|
||||||
|
"title": "反向链接"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "581590955e0bea90",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "outgoing-link",
|
||||||
|
"state": {
|
||||||
|
"linksCollapsed": false,
|
||||||
|
"unlinkedCollapsed": true
|
||||||
|
},
|
||||||
|
"icon": "links-going-out",
|
||||||
|
"title": "出链"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "1a4acbac03b03363",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "tag",
|
||||||
|
"state": {
|
||||||
|
"sortOrder": "frequency",
|
||||||
|
"useHierarchy": true,
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": ""
|
||||||
|
},
|
||||||
|
"icon": "lucide-tags",
|
||||||
|
"title": "标签"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7f042c9bd0f488d3",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "all-properties",
|
||||||
|
"state": {
|
||||||
|
"sortOrder": "frequency",
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": ""
|
||||||
|
},
|
||||||
|
"icon": "lucide-archive",
|
||||||
|
"title": "添加笔记属性"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "60900b2eac2af4b5",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "outline",
|
||||||
|
"state": {
|
||||||
|
"followCursor": false,
|
||||||
|
"showSearch": false,
|
||||||
|
"searchQuery": ""
|
||||||
|
},
|
||||||
|
"icon": "lucide-list",
|
||||||
|
"title": "大纲"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4aedff8fd103c92c",
|
||||||
|
"type": "leaf",
|
||||||
|
"state": {
|
||||||
|
"type": "claudian-view",
|
||||||
|
"state": {},
|
||||||
|
"icon": "bot",
|
||||||
|
"title": "Claudian"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"currentTab": 5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"direction": "horizontal",
|
||||||
|
"width": 439.5
|
||||||
|
},
|
||||||
|
"left-ribbon": {
|
||||||
|
"hiddenItems": {
|
||||||
|
"obsidian-git:Open Git source control": false,
|
||||||
|
"switcher:打开快速切换": false,
|
||||||
|
"graph:查看关系图谱": false,
|
||||||
|
"canvas:新建白板": false,
|
||||||
|
"daily-notes:打开/创建今天的日记": false,
|
||||||
|
"templates:插入模板": false,
|
||||||
|
"command-palette:打开命令面板": false,
|
||||||
|
"bases:新建数据库": false,
|
||||||
|
"claudian:Open Claudian": false,
|
||||||
|
"obsidian-excalidraw-plugin:新建绘图文件": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"active": "48717814ec87547e",
|
||||||
|
"lastOpenFiles": [
|
||||||
|
"Dehaze/translation-去雾.pdf",
|
||||||
|
"Dehaze/translation-去雾.md",
|
||||||
|
"创建链接.md",
|
||||||
|
"欢迎.md",
|
||||||
|
"Dehaze/translation-去雾.docx",
|
||||||
|
"Dehaze"
|
||||||
|
]
|
||||||
|
}
|
||||||
75
Dehaze/Mineru_api_client-V1.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import zipfile
|
||||||
|
import io
|
||||||
|
|
||||||
|
# 1. 配置基础参数
|
||||||
|
url = "http://10.168.1.103:4000/extract" # 请确保此处的 IP 和端口与服务端保持一致
|
||||||
|
source_dir = "./Papers/ORI_PDF"
|
||||||
|
target_dir = "./Papers/ORI_MD"
|
||||||
|
|
||||||
|
# 2. 确保源目录存在,避免报错
|
||||||
|
if not os.path.exists(source_dir):
|
||||||
|
print(f"错误: 找不到源文件夹 '{source_dir}'")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# 确保目标主文件夹存在
|
||||||
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# 3. 遍历源文件夹下的所有文件
|
||||||
|
for filename in os.listdir(source_dir):
|
||||||
|
# 只处理 PDF 文件
|
||||||
|
if not filename.lower().endswith(".pdf"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
file_path = os.path.join(source_dir, filename)
|
||||||
|
# 获取去掉 .pdf 后缀的文件名
|
||||||
|
pdf_name_no_ext = os.path.splitext(filename)[0]
|
||||||
|
|
||||||
|
# 对应的输出文件夹路径
|
||||||
|
output_folder = os.path.join(target_dir, pdf_name_no_ext)
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 【新增逻辑】:检查是否已经处理过
|
||||||
|
# 如果输出文件夹已存在,且内部有文件,则视为已转换,直接跳过
|
||||||
|
# ==========================================
|
||||||
|
if os.path.exists(output_folder) and len(os.listdir(output_folder)) > 0:
|
||||||
|
print(f"⏩ 已存在转换结果,跳过处理: {filename}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"正在上传并处理 {filename}...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 4. 发送请求
|
||||||
|
with open(file_path, "rb") as f:
|
||||||
|
files = {"file": (filename, f, "application/pdf")}
|
||||||
|
response = requests.post(url, files=files)
|
||||||
|
|
||||||
|
# 5. 处理响应结果
|
||||||
|
if response.status_code == 200:
|
||||||
|
# 【新增防护】:检查服务端是否返回了包含报错信息的 JSON
|
||||||
|
if response.headers.get('content-type') == 'application/json':
|
||||||
|
error_msg = response.json()
|
||||||
|
print(f"❌ 服务端处理失败 ({filename}):{error_msg.get('message', '未知错误')}")
|
||||||
|
continue # 跳过解压,处理下一个
|
||||||
|
|
||||||
|
# 确保该 PDF 专属的输出文件夹存在
|
||||||
|
os.makedirs(output_folder, exist_ok=True)
|
||||||
|
|
||||||
|
# 核心:使用 io.BytesIO 直接在内存中读取 zip 内容并解压
|
||||||
|
try:
|
||||||
|
with zipfile.ZipFile(io.BytesIO(response.content)) as zip_ref:
|
||||||
|
zip_ref.extractall(output_folder)
|
||||||
|
print(f"✅ 成功!已解压并保存至文件夹: {output_folder}")
|
||||||
|
except zipfile.BadZipFile:
|
||||||
|
print(f"❌ 失败!{filename} 返回的内容不是有效的 ZIP 格式。")
|
||||||
|
else:
|
||||||
|
print(f"❌ 失败!{filename} 状态码: {response.status_code}, 报错: {response.text}")
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
print(f"❌ 网络请求异常 ({filename}): {e}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 处理 {filename} 时发生未知错误: {e}")
|
||||||
|
|
||||||
|
print("-" * 30)
|
||||||
|
print("批量处理任务结束!")
|
||||||
104
Dehaze/Mineru_api_client-V2.py
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import zipfile
|
||||||
|
import io
|
||||||
|
import shutil # 【新增】用于删除非空文件夹
|
||||||
|
|
||||||
|
# 1. 配置基础参数
|
||||||
|
url = "http://10.168.1.103:4000/extract" # 请确保此处的 IP 和端口与服务端保持一致
|
||||||
|
source_dir = "./Papers/ORI_PDF"
|
||||||
|
target_dir = "./Papers/ORI_MD"
|
||||||
|
|
||||||
|
# 2. 确保源目录存在,避免报错
|
||||||
|
if not os.path.exists(source_dir):
|
||||||
|
print(f"错误: 找不到源文件夹 '{source_dir}'")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# 确保目标主文件夹存在
|
||||||
|
os.makedirs(target_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# 3. 遍历源文件夹下的所有文件进行上传处理
|
||||||
|
for filename in os.listdir(source_dir):
|
||||||
|
# 只处理 PDF 文件
|
||||||
|
if not filename.lower().endswith(".pdf"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
file_path = os.path.join(source_dir, filename)
|
||||||
|
# 获取去掉 .pdf 后缀的文件名
|
||||||
|
pdf_name_no_ext = os.path.splitext(filename)[0]
|
||||||
|
|
||||||
|
# 对应的输出文件夹路径
|
||||||
|
output_folder = os.path.join(target_dir, pdf_name_no_ext)
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 检查是否已经处理过
|
||||||
|
# 如果输出文件夹已存在,且内部有文件,则视为已转换,直接跳过
|
||||||
|
# ==========================================
|
||||||
|
if os.path.exists(output_folder) and len(os.listdir(output_folder)) > 0:
|
||||||
|
print(f"⏩ 已存在转换结果,跳过处理: {filename}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"正在上传并处理 {filename}...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 4. 发送请求
|
||||||
|
with open(file_path, "rb") as f:
|
||||||
|
files = {"file": (filename, f, "application/pdf")}
|
||||||
|
response = requests.post(url, files=files)
|
||||||
|
|
||||||
|
# 5. 处理响应结果
|
||||||
|
if response.status_code == 200:
|
||||||
|
# 检查服务端是否返回了包含报错信息的 JSON
|
||||||
|
if response.headers.get('content-type') == 'application/json':
|
||||||
|
error_msg = response.json()
|
||||||
|
print(f"❌ 服务端处理失败 ({filename}):{error_msg.get('message', '未知错误')}")
|
||||||
|
continue # 跳过解压,处理下一个
|
||||||
|
|
||||||
|
# 确保该 PDF 专属的输出文件夹存在
|
||||||
|
os.makedirs(output_folder, exist_ok=True)
|
||||||
|
|
||||||
|
# 核心:使用 io.BytesIO 直接在内存中读取 zip 内容并解压
|
||||||
|
try:
|
||||||
|
with zipfile.ZipFile(io.BytesIO(response.content)) as zip_ref:
|
||||||
|
zip_ref.extractall(output_folder)
|
||||||
|
print(f"✅ 成功!已解压并保存至文件夹: {output_folder}")
|
||||||
|
except zipfile.BadZipFile:
|
||||||
|
print(f"❌ 失败!{filename} 返回的内容不是有效的 ZIP 格式。")
|
||||||
|
else:
|
||||||
|
print(f"❌ 失败!{filename} 状态码: {response.status_code}, 报错: {response.text}")
|
||||||
|
|
||||||
|
except requests.exceptions.RequestException as e:
|
||||||
|
print(f"❌ 网络请求异常 ({filename}): {e}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 处理 {filename} 时发生未知错误: {e}")
|
||||||
|
|
||||||
|
print("-" * 30)
|
||||||
|
print("转换任务结束,开始进行文件夹同步清理...")
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# 【新增逻辑】:反向比对,清理多余的 MD 文件夹
|
||||||
|
# ==========================================
|
||||||
|
# 1. 收集当前 ORI_PDF 中所有有效的 PDF 名字(不含后缀)
|
||||||
|
valid_pdf_names = set()
|
||||||
|
for filename in os.listdir(source_dir):
|
||||||
|
if filename.lower().endswith(".pdf"):
|
||||||
|
valid_pdf_names.add(os.path.splitext(filename)[0])
|
||||||
|
|
||||||
|
# 2. 遍历 ORI_MD 文件夹
|
||||||
|
if os.path.exists(target_dir):
|
||||||
|
for folder_name in os.listdir(target_dir):
|
||||||
|
folder_path = os.path.join(target_dir, folder_name)
|
||||||
|
|
||||||
|
# 仅处理文件夹(以防里面有意外的独立文件)
|
||||||
|
if os.path.isdir(folder_path):
|
||||||
|
# 3. 如果这个文件夹的名字不在有效的 PDF 列表中,说明是被删掉的“孤儿”
|
||||||
|
if folder_name not in valid_pdf_names:
|
||||||
|
print(f"🧹 发现多余文件,正在清理: {folder_name}")
|
||||||
|
try:
|
||||||
|
# 使用 shutil.rmtree 删除整个文件夹及其内部所有内容
|
||||||
|
shutil.rmtree(folder_path)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 删除 {folder_name} 时发生错误: {e}")
|
||||||
|
|
||||||
|
print("-" * 30)
|
||||||
|
print("所有批量任务彻底完成!")
|
||||||
51
Dehaze/Mineru_api_server-V1.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import os
|
||||||
|
import uuid
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from fastapi import FastAPI, UploadFile, File
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
app = FastAPI(title="MinerU Extraction API")
|
||||||
|
|
||||||
|
@app.post("/extract")
|
||||||
|
def extract_document(file: UploadFile = File(...)):
|
||||||
|
# 1. 创建独立的任务文件夹,防止多个请求同时发生时文件冲突
|
||||||
|
task_id = str(uuid.uuid4())[:8]
|
||||||
|
work_dir = os.path.abspath(f"./api_workspace/{task_id}")
|
||||||
|
out_dir = os.path.join(work_dir, "OUT")
|
||||||
|
os.makedirs(work_dir, exist_ok=True)
|
||||||
|
|
||||||
|
input_file_path = os.path.join(work_dir, file.filename)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 2. 接收并保存客户端上传的文件
|
||||||
|
print(f"[Task {task_id}] 收到文件: {file.filename},开始处理...")
|
||||||
|
with open(input_file_path, "wb") as buffer:
|
||||||
|
shutil.copyfileobj(file.file, buffer)
|
||||||
|
|
||||||
|
# 3. 调用你刚刚跑通的 MinerU 命令行
|
||||||
|
# 相当于在终端执行 mineru -p xxx -o xxx
|
||||||
|
subprocess.run(["mineru", "-p", input_file_path, "-o", out_dir], check=True)
|
||||||
|
|
||||||
|
# 4. 将 MinerU 的输出结果打包成 ZIP 文件
|
||||||
|
print(f"[Task {task_id}] 解析完成,正在打包结果...")
|
||||||
|
zip_base_path = os.path.join(work_dir, "result")
|
||||||
|
shutil.make_archive(zip_base_path, 'zip', out_dir)
|
||||||
|
zip_file_path = f"{zip_base_path}.zip"
|
||||||
|
|
||||||
|
# 5. 将 ZIP 文件作为响应返回给客户端
|
||||||
|
return FileResponse(
|
||||||
|
zip_file_path,
|
||||||
|
media_type="application/zip",
|
||||||
|
filename=f"parsed_{file.filename}.zip"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return {"status": "error", "message": str(e)}
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 绑定到 0.0.0.0 代表监听本机所有 IP (包括 192.168.4.6)
|
||||||
|
# 端口设置为你要求的 5000
|
||||||
|
print("🚀 MinerU API 启动成功!监听地址: http://192.168.4.6:5000")
|
||||||
|
uvicorn.run(app, host="0.0.0.0", port=5000)
|
||||||
66
Dehaze/Mineru_api_server-V2.py
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import os
|
||||||
|
import uuid
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from fastapi import FastAPI, UploadFile, File, BackgroundTasks # 1. 导入 BackgroundTasks
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
app = FastAPI(title="MinerU Extraction API")
|
||||||
|
|
||||||
|
# 定义一个清理函数
|
||||||
|
def cleanup_task_dir(dir_path: str):
|
||||||
|
"""删除指定的文件夹及其所有内容"""
|
||||||
|
if os.path.exists(dir_path):
|
||||||
|
shutil.rmtree(dir_path)
|
||||||
|
print(f"🧹 已自动清理临时目录: {dir_path}")
|
||||||
|
|
||||||
|
@app.post("/extract")
|
||||||
|
async def extract_document(background_tasks: BackgroundTasks, file: UploadFile = File(...)): # 2. 注入后台任务参数
|
||||||
|
# 1. 创建独立的任务文件夹
|
||||||
|
task_id = str(uuid.uuid4())[:8]
|
||||||
|
work_dir = os.path.abspath(f"./api_workspace/{task_id}")
|
||||||
|
out_dir = os.path.join(work_dir, "OUT")
|
||||||
|
os.makedirs(work_dir, exist_ok=True)
|
||||||
|
|
||||||
|
input_file_path = os.path.join(work_dir, file.filename)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 2. 接收并保存文件
|
||||||
|
print(f"[Task {task_id}] 收到文件: {file.filename},开始处理...")
|
||||||
|
with open(input_file_path, "wb") as buffer:
|
||||||
|
shutil.copyfileobj(file.file, buffer)
|
||||||
|
|
||||||
|
# 3. 执行 MinerU 命令
|
||||||
|
subprocess.run(["mineru", "-p", input_file_path, "-o", out_dir], check=True)
|
||||||
|
|
||||||
|
# 4. 穿透外层冗余文件夹,寻找真实的输出目录
|
||||||
|
target_zip_dir = out_dir
|
||||||
|
for root, dirs, files in os.walk(out_dir):
|
||||||
|
if any(f.endswith('.md') for f in files):
|
||||||
|
target_zip_dir = root
|
||||||
|
break
|
||||||
|
|
||||||
|
# 5. 打包结果
|
||||||
|
zip_base_path = os.path.join(work_dir, "result")
|
||||||
|
shutil.make_archive(zip_base_path, 'zip', target_zip_dir)
|
||||||
|
zip_file_path = f"{zip_base_path}.zip"
|
||||||
|
|
||||||
|
# 6. 【核心改进】:添加后台任务,在响应发送后删除 work_dir
|
||||||
|
background_tasks.add_task(cleanup_task_dir, work_dir)
|
||||||
|
|
||||||
|
# 7. 返回给客户端
|
||||||
|
return FileResponse(
|
||||||
|
zip_file_path,
|
||||||
|
media_type="application/zip",
|
||||||
|
filename=f"parsed_{file.filename}.zip"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# 如果出错了,也尝试清理一下该任务的文件夹,防止空间占用
|
||||||
|
background_tasks.add_task(cleanup_task_dir, work_dir)
|
||||||
|
return {"status": "error", "message": str(e)}
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("🚀 MinerU API 启动成功!监听地址: http://192.168.4.6:5000")
|
||||||
|
uvicorn.run(app, host="0.0.0.0", port=5000)
|
||||||
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 194 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 5.6 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 42 KiB |