initial import
This commit is contained in:
commit
f475ec29b1
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.trash/
|
1
.obsidian/.nomedia
vendored
Normal file
1
.obsidian/.nomedia
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/storage/emulated/0/obsidian/Template Obsidian Vault/.obsidian
|
27
.obsidian/app.json
vendored
Normal file
27
.obsidian/app.json
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"defaultViewMode": "preview",
|
||||
"livePreview": false,
|
||||
"autoPairBrackets": false,
|
||||
"autoPairMarkdown": false,
|
||||
"alwaysUpdateLinks": true,
|
||||
"newLinkFormat": "absolute",
|
||||
"useMarkdownLinks": true,
|
||||
"showUnsupportedFiles": true,
|
||||
"attachmentFolderPath": "attachments",
|
||||
"mobileQuickRibbonItem": "command-palette:Open command palette",
|
||||
"trashOption": "local",
|
||||
"autoConvertHtml": false,
|
||||
"showRibbon": true,
|
||||
"mobileToolbarCommands": [
|
||||
"editor:attach-file",
|
||||
"editor:undo",
|
||||
"editor:redo",
|
||||
"editor:cut",
|
||||
"editor:copy",
|
||||
"editor:paste",
|
||||
"editor:configure-toolbar"
|
||||
],
|
||||
"userIgnoreFilters": [
|
||||
".nomedia"
|
||||
]
|
||||
}
|
6
.obsidian/appearance.json
vendored
Normal file
6
.obsidian/appearance.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"theme": "system",
|
||||
"interfaceFontFamily": "Atkinson Hyperlegible",
|
||||
"textFontFamily": "Atkinson Hyperlegible",
|
||||
"monospaceFontFamily": "DejaVu Sans Mono"
|
||||
}
|
5
.obsidian/canvas.json
vendored
Normal file
5
.obsidian/canvas.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"snapToObjects": true,
|
||||
"snapToGrid": true,
|
||||
"defaultWheelBehavior": "zoom"
|
||||
}
|
9
.obsidian/command-palette.json
vendored
Normal file
9
.obsidian/command-palette.json
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"pinned": [
|
||||
"zk-prefixer",
|
||||
"outline:open",
|
||||
"file-explorer:open",
|
||||
"obsidian-trash-explorer:show-trash-explorer",
|
||||
"file-recovery:open"
|
||||
]
|
||||
}
|
5
.obsidian/community-plugins.json
vendored
Normal file
5
.obsidian/community-plugins.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
[
|
||||
"definition-list",
|
||||
"obsidian-trash-explorer",
|
||||
"automatic-table-of-contents"
|
||||
]
|
30
.obsidian/core-plugins-migration.json
vendored
Normal file
30
.obsidian/core-plugins-migration.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"file-explorer": true,
|
||||
"global-search": true,
|
||||
"switcher": true,
|
||||
"graph": true,
|
||||
"backlink": true,
|
||||
"canvas": true,
|
||||
"outgoing-link": true,
|
||||
"tag-pane": true,
|
||||
"properties": false,
|
||||
"page-preview": true,
|
||||
"daily-notes": false,
|
||||
"templates": false,
|
||||
"note-composer": false,
|
||||
"command-palette": true,
|
||||
"slash-command": false,
|
||||
"editor-status": true,
|
||||
"bookmarks": true,
|
||||
"markdown-importer": false,
|
||||
"zk-prefixer": false,
|
||||
"random-note": false,
|
||||
"outline": true,
|
||||
"word-count": false,
|
||||
"slides": false,
|
||||
"audio-recorder": false,
|
||||
"workspaces": false,
|
||||
"file-recovery": true,
|
||||
"publish": false,
|
||||
"sync": false
|
||||
}
|
30
.obsidian/core-plugins.json
vendored
Normal file
30
.obsidian/core-plugins.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"file-explorer": true,
|
||||
"global-search": false,
|
||||
"switcher": false,
|
||||
"graph": false,
|
||||
"backlink": false,
|
||||
"canvas": false,
|
||||
"outgoing-link": false,
|
||||
"tag-pane": false,
|
||||
"properties": false,
|
||||
"page-preview": false,
|
||||
"daily-notes": false,
|
||||
"templates": true,
|
||||
"note-composer": false,
|
||||
"command-palette": true,
|
||||
"slash-command": false,
|
||||
"editor-status": true,
|
||||
"bookmarks": false,
|
||||
"markdown-importer": false,
|
||||
"zk-prefixer": true,
|
||||
"random-note": false,
|
||||
"outline": true,
|
||||
"word-count": false,
|
||||
"slides": false,
|
||||
"audio-recorder": false,
|
||||
"workspaces": false,
|
||||
"file-recovery": true,
|
||||
"publish": false,
|
||||
"sync": false
|
||||
}
|
291
.obsidian/plugins/automatic-table-of-contents/main.js
vendored
Normal file
291
.obsidian/plugins/automatic-table-of-contents/main.js
vendored
Normal file
|
@ -0,0 +1,291 @@
|
|||
let Plugin = class {}
|
||||
let MarkdownRenderer = {}
|
||||
let MarkdownRenderChild = class {}
|
||||
let htmlToMarkdown = (html) => html
|
||||
|
||||
if (isObsidian()) {
|
||||
const obsidian = require('obsidian')
|
||||
Plugin = obsidian.Plugin
|
||||
MarkdownRenderer = obsidian.MarkdownRenderer
|
||||
MarkdownRenderChild = obsidian.MarkdownRenderChild
|
||||
htmlToMarkdown = obsidian.htmlToMarkdown
|
||||
}
|
||||
|
||||
const codeblockId = 'table-of-contents'
|
||||
const codeblockIdShort = 'toc'
|
||||
const availableOptions = {
|
||||
title: {
|
||||
type: 'string',
|
||||
default: '',
|
||||
comment: '',
|
||||
},
|
||||
style: {
|
||||
type: 'value',
|
||||
default: 'nestedList',
|
||||
values: ['nestedList', 'nestedOrderedList', 'inlineFirstLevel'],
|
||||
comment: 'TOC style (nestedList|nestedOrderedList|inlineFirstLevel)',
|
||||
},
|
||||
minLevel: {
|
||||
type: 'number',
|
||||
default: 0,
|
||||
comment: 'Include headings from the specified level',
|
||||
},
|
||||
maxLevel: {
|
||||
type: 'number',
|
||||
default: 0,
|
||||
comment: 'Include headings up to the specified level',
|
||||
},
|
||||
includeLinks: {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
comment: 'Make headings clickable',
|
||||
},
|
||||
debugInConsole: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
comment: 'Print debug info in Obsidian console',
|
||||
},
|
||||
}
|
||||
|
||||
class ObsidianAutomaticTableOfContents extends Plugin {
|
||||
async onload() {
|
||||
const handler = (sourceText, element, context) => {
|
||||
context.addChild(new Renderer(this.app, element, context.sourcePath, sourceText))
|
||||
}
|
||||
this.registerMarkdownCodeBlockProcessor(codeblockId, handler)
|
||||
this.registerMarkdownCodeBlockProcessor(codeblockIdShort, handler)
|
||||
this.addCommand({
|
||||
id: 'insert-automatic-table-of-contents',
|
||||
name: 'Insert table of contents',
|
||||
editorCallback: onInsertToc,
|
||||
})
|
||||
this.addCommand({
|
||||
id: 'insert-automatic-table-of-contents-docs',
|
||||
name: 'Insert table of contents (documented)',
|
||||
editorCallback: onInsertTocWithDocs,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function onInsertToc(editor) {
|
||||
const markdown = '```' + codeblockId + '\n```'
|
||||
editor.replaceRange(markdown, editor.getCursor())
|
||||
}
|
||||
|
||||
function onInsertTocWithDocs(editor) {
|
||||
let markdown = ['```' + codeblockId]
|
||||
Object.keys(availableOptions).forEach((optionName) => {
|
||||
const option = availableOptions[optionName]
|
||||
const comment = option.comment.length > 0 ? ` # ${option.comment}` : ''
|
||||
markdown.push(`${optionName}: ${option.default}${comment}`)
|
||||
})
|
||||
markdown.push('```')
|
||||
editor.replaceRange(markdown.join('\n'), editor.getCursor())
|
||||
}
|
||||
|
||||
class Renderer extends MarkdownRenderChild {
|
||||
constructor(app, element, sourcePath, sourceText) {
|
||||
super(element)
|
||||
this.app = app
|
||||
this.element = element
|
||||
this.sourcePath = sourcePath
|
||||
this.sourceText = sourceText
|
||||
}
|
||||
|
||||
// Render on load
|
||||
onload() {
|
||||
this.render()
|
||||
this.registerEvent(this.app.metadataCache.on('changed', this.onMetadataChange.bind(this)))
|
||||
}
|
||||
|
||||
// Render on file change
|
||||
onMetadataChange() {
|
||||
this.render()
|
||||
}
|
||||
|
||||
render() {
|
||||
try {
|
||||
const options = parseOptionsFromSourceText(this.sourceText)
|
||||
if (options.debugInConsole) debug('Options', options)
|
||||
|
||||
const metadata = this.app.metadataCache.getCache(this.sourcePath)
|
||||
const headings = metadata && metadata.headings ? metadata.headings : []
|
||||
if (options.debugInConsole) debug('Headings', headings)
|
||||
|
||||
const markdown = getMarkdownFromHeadings(headings, options)
|
||||
if (options.debugInConsole) debug('Markdown', markdown)
|
||||
|
||||
this.element.empty()
|
||||
MarkdownRenderer.renderMarkdown(markdown, this.element, this.sourcePath, this)
|
||||
} catch(error) {
|
||||
const readableError = `_💥 Could not render table of contents (${error.message})_`
|
||||
MarkdownRenderer.renderMarkdown(readableError, this.element, this.sourcePath, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getMarkdownFromHeadings(headings, options) {
|
||||
const markdownHandlersByStyle = {
|
||||
nestedList: getMarkdownNestedListFromHeadings,
|
||||
nestedOrderedList: getMarkdownNestedOrderedListFromHeadings,
|
||||
inlineFirstLevel: getMarkdownInlineFirstLevelFromHeadings,
|
||||
}
|
||||
let markdown = ''
|
||||
if (options.title && options.title.length > 0) {
|
||||
markdown += options.title + '\n'
|
||||
}
|
||||
const noHeadingMessage = '_Table of contents: no headings found_'
|
||||
markdown += markdownHandlersByStyle[options.style](headings, options) || noHeadingMessage
|
||||
return markdown
|
||||
}
|
||||
|
||||
function getMarkdownNestedListFromHeadings(headings, options) {
|
||||
return getMarkdownListFromHeadings(headings, false, options)
|
||||
}
|
||||
|
||||
function getMarkdownNestedOrderedListFromHeadings(headings, options) {
|
||||
return getMarkdownListFromHeadings(headings, true, options)
|
||||
}
|
||||
|
||||
function getMarkdownListFromHeadings(headings, isOrdered, options) {
|
||||
const prefix = isOrdered ? '1.' : '-'
|
||||
const lines = []
|
||||
const minLevel = options.minLevel > 0
|
||||
? options.minLevel
|
||||
: Math.min(...headings.map((heading) => heading.level))
|
||||
headings.forEach((heading) => {
|
||||
if (heading.level < minLevel) return
|
||||
if (options.maxLevel > 0 && heading.level > options.maxLevel) return
|
||||
lines.push(`${'\t'.repeat(heading.level - minLevel)}${prefix} ${getMarkdownHeading(heading, options)}`)
|
||||
})
|
||||
return lines.length > 0 ? lines.join('\n') : null
|
||||
}
|
||||
|
||||
function getMarkdownInlineFirstLevelFromHeadings(headings, options) {
|
||||
const minLevel = options.minLevel > 0
|
||||
? options.minLevel
|
||||
: Math.min(...headings.map((heading) => heading.level))
|
||||
const items = headings
|
||||
.filter((heading) => heading.level === minLevel)
|
||||
.map((heading) => {
|
||||
return getMarkdownHeading(heading, options)
|
||||
})
|
||||
return items.length > 0 ? items.join(' | ') : null
|
||||
}
|
||||
|
||||
function getMarkdownHeading(heading, options) {
|
||||
const stripMarkdown = (text) => {
|
||||
text = text.replaceAll('*', '').replaceAll('_', '').replaceAll('`', '')
|
||||
text = text.replaceAll('==', '').replaceAll('~~', '')
|
||||
text = text.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // Strip markdown links
|
||||
return text
|
||||
}
|
||||
const stripHtml = (text) => stripMarkdown(htmlToMarkdown(text))
|
||||
const stripWikilinks = (text, isForLink) => {
|
||||
// Strip [[link|text]] format
|
||||
// For the text part of the final link we only keep "text"
|
||||
// For the link part we need the text + link
|
||||
// Example: "# Some [[file.md|heading]]" must be translated to "[[#Some file.md heading|Some heading]]"
|
||||
text = text.replace(/\[\[([^\]]+)\|([^\]]+)\]\]/g, isForLink ? '$1 $2' : '$2')
|
||||
text = text.replace(/\[\[([^\]]+)\]\]/g, '$1') // Strip [[link]] format
|
||||
// Replace malformed links & reserved wikilinks chars
|
||||
text = text.replaceAll('[[', '').replaceAll('| ', isForLink ? '' : '- ').replaceAll('|', isForLink ? ' ' : '-')
|
||||
return text
|
||||
}
|
||||
const stripTags = (text) => text.replaceAll('#', '')
|
||||
if (options.includeLinks) {
|
||||
// Remove markdown, HTML & wikilinks from text for readability, as they are not rendered in a wikilink
|
||||
let text = heading.heading
|
||||
text = stripMarkdown(text)
|
||||
text = stripHtml(text)
|
||||
text = stripWikilinks(text, false)
|
||||
// Remove wikilinks & tags from link or it won't be clickable (on the other hand HTML & markdown must stay)
|
||||
let link = heading.heading
|
||||
link = stripWikilinks(link, true)
|
||||
link = stripTags(link)
|
||||
|
||||
// Return wiklink style link
|
||||
return `[[#${link}|${text}]]`
|
||||
// Why not markdown links? Because even if it looks like the text part would have a better compatibility
|
||||
// with complex headings (as it would support HTML, markdown, etc) the link part is messy,
|
||||
// because it requires some encoding that looks buggy and undocumented; official docs state the link must be URL encoded
|
||||
// (https://help.obsidian.md/Linking+notes+and+files/Internal+links#Supported+formats+for+internal+links)
|
||||
// but it doesn't work properly, example: "## Some <em>heading</em> with simple HTML" must be encoded as:
|
||||
// [Some <em>heading</em> with simple HTML](#Some%20<em>heading</em>%20with%20simpler%20HTML)
|
||||
// and not
|
||||
// [Some <em>heading</em> with simple HTML](#Some%20%3Cem%3Eheading%3C%2Fem%3E%20with%20simpler%20HTML)
|
||||
// Also it won't be clickable at all if the heading contains #tags or more complex HTML
|
||||
// (example: ## Some <em style="background: red">heading</em> #with-a-tag)
|
||||
// (unless there is a way to encode these use cases that I didn't find)
|
||||
}
|
||||
return heading.heading
|
||||
}
|
||||
|
||||
function parseOptionsFromSourceText(sourceText = '') {
|
||||
const options = {}
|
||||
Object.keys(availableOptions).forEach((option) => {
|
||||
options[option] = availableOptions[option].default
|
||||
})
|
||||
sourceText.split('\n').forEach((line) => {
|
||||
const option = parseOptionFromSourceLine(line)
|
||||
if (option !== null) {
|
||||
options[option.name] = option.value
|
||||
}
|
||||
})
|
||||
return options
|
||||
}
|
||||
|
||||
function parseOptionFromSourceLine(line) {
|
||||
const matches = line.match(/([a-zA-Z0-9._ ]+):(.*)/)
|
||||
if (line.startsWith('#') || !matches) return null
|
||||
const possibleName = matches[1].trim()
|
||||
const optionParams = availableOptions[possibleName]
|
||||
let possibleValue = matches[2].trim()
|
||||
if (!optionParams || optionParams.type !== 'string') {
|
||||
// Strip comments from values except for strings (as a string may contain markdown)
|
||||
possibleValue = possibleValue.replace(/#[^#]*$/, '').trim()
|
||||
}
|
||||
const valueError = new Error(`Invalid value for \`${possibleName}\``)
|
||||
if (optionParams && optionParams.type === 'number') {
|
||||
const value = parseInt(possibleValue)
|
||||
if (value < 0) throw valueError
|
||||
return { name: possibleName, value }
|
||||
}
|
||||
if (optionParams && optionParams.type === 'boolean') {
|
||||
if (!['true', 'false'].includes(possibleValue)) throw valueError
|
||||
return { name: possibleName, value: possibleValue === 'true' }
|
||||
}
|
||||
if (optionParams && optionParams.type === 'value') {
|
||||
if (!optionParams.values.includes(possibleValue)) throw valueError
|
||||
return { name: possibleName, value: possibleValue }
|
||||
}
|
||||
if (optionParams && optionParams.type === 'string') {
|
||||
return { name: possibleName, value: possibleValue }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function debug(type, data) {
|
||||
console.log(...[
|
||||
`%cAutomatic Table Of Contents %c${type}:\n`,
|
||||
'color: orange; font-weight: bold',
|
||||
'font-weight: bold',
|
||||
data,
|
||||
])
|
||||
}
|
||||
|
||||
function isObsidian() {
|
||||
if (typeof process !== 'object') {
|
||||
return true // Obsidian mobile doesn't have a global process object
|
||||
}
|
||||
return !process.env || !process.env.JEST_WORKER_ID // Jest runtime is not Obsidian
|
||||
}
|
||||
|
||||
if (isObsidian()) {
|
||||
module.exports = ObsidianAutomaticTableOfContents
|
||||
} else {
|
||||
module.exports = {
|
||||
parseOptionsFromSourceText,
|
||||
getMarkdownFromHeadings,
|
||||
}
|
||||
}
|
10
.obsidian/plugins/automatic-table-of-contents/manifest.json
vendored
Normal file
10
.obsidian/plugins/automatic-table-of-contents/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "automatic-table-of-contents",
|
||||
"name": "Automatic Table Of Contents",
|
||||
"version": "1.4.0",
|
||||
"minAppVersion": "1.3.0",
|
||||
"description": "Create a table of contents in a note, that updates itself when the note changes",
|
||||
"author": "Johan Satgé",
|
||||
"authorUrl": "https://github.com/johansatge",
|
||||
"isDesktopOnly": false
|
||||
}
|
217
.obsidian/plugins/definition-list/main.js
vendored
Normal file
217
.obsidian/plugins/definition-list/main.js
vendored
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin
|
||||
*/
|
||||
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// main.ts
|
||||
var main_exports = {};
|
||||
__export(main_exports, {
|
||||
default: () => DefinitionListPlugin
|
||||
});
|
||||
module.exports = __toCommonJS(main_exports);
|
||||
var import_obsidian = require("obsidian");
|
||||
var import_view = require("@codemirror/view");
|
||||
var import_state = require("@codemirror/state");
|
||||
var CODE_BLOCK_DELIMITER = "```";
|
||||
var DEFINITION_REGEX = /^(\s*)([:~])\s/;
|
||||
var HEADING_REGEX = /^#+\s/;
|
||||
var LIST_ITEM_REGEX = /^\s*(\*|\+|-|\d+\.)\s/;
|
||||
var HORIZONTAL_RULE_REGEX = /^(-{3,}|\*{3,}|_{3,})/;
|
||||
function isLivePreview(view) {
|
||||
var _a;
|
||||
const editorEl = view.dom.closest(".markdown-source-view");
|
||||
return (_a = editorEl == null ? void 0 : editorEl.classList.contains("is-live-preview")) != null ? _a : false;
|
||||
}
|
||||
var definitionListPlugin = import_view.ViewPlugin.fromClass(class {
|
||||
constructor(view) {
|
||||
this.decorations = this.buildDecorations(view);
|
||||
}
|
||||
update(update) {
|
||||
if (update.docChanged || update.viewportChanged || update.selectionSet) {
|
||||
this.decorations = this.buildDecorations(update.view);
|
||||
}
|
||||
}
|
||||
buildDecorations(view) {
|
||||
if (!isLivePreview(view)) {
|
||||
return import_view.Decoration.none;
|
||||
}
|
||||
const builder = new import_state.RangeSetBuilder();
|
||||
const doc = view.state.doc;
|
||||
const selection = view.state.selection;
|
||||
let inCodeBlock = false;
|
||||
let lastLineWasTerm = false;
|
||||
let lastLineWasDefinition = false;
|
||||
function isNotTerm(content) {
|
||||
return HEADING_REGEX.test(content) || LIST_ITEM_REGEX.test(content) || content.startsWith("![") || HORIZONTAL_RULE_REGEX.test(content) || content.startsWith("[^") || content.startsWith("|") || content.startsWith("$$") || content.startsWith("^");
|
||||
}
|
||||
for (let i = 1; i <= doc.lines; i++) {
|
||||
const line = doc.line(i);
|
||||
const lineText = line.text;
|
||||
const trimmedLineText = lineText.trim();
|
||||
if (trimmedLineText === CODE_BLOCK_DELIMITER) {
|
||||
inCodeBlock = !inCodeBlock;
|
||||
lastLineWasTerm = false;
|
||||
lastLineWasDefinition = false;
|
||||
continue;
|
||||
}
|
||||
if (inCodeBlock) {
|
||||
lastLineWasTerm = false;
|
||||
lastLineWasDefinition = false;
|
||||
continue;
|
||||
}
|
||||
const definitionMatch = DEFINITION_REGEX.exec(lineText);
|
||||
const nextLine = i < doc.lines ? doc.line(i + 1).text : "";
|
||||
const isNextLineDefinition = DEFINITION_REGEX.test(nextLine.trim());
|
||||
if (trimmedLineText === "") {
|
||||
lastLineWasTerm = false;
|
||||
lastLineWasDefinition = false;
|
||||
} else if (definitionMatch && (lastLineWasTerm || lastLineWasDefinition)) {
|
||||
const [, indent, marker] = definitionMatch;
|
||||
const isIndented = indent.length > 0;
|
||||
builder.add(
|
||||
line.from,
|
||||
line.from,
|
||||
import_view.Decoration.line({
|
||||
attributes: { class: isIndented ? "dl-dd-indent" : "dl-dd-reg" }
|
||||
})
|
||||
);
|
||||
const indentStartPos = line.from;
|
||||
const markerEndPos = indentStartPos + indent.length + marker.length + 1;
|
||||
const isCursorTouchingIndentOrMarker = selection.ranges.some(
|
||||
(range) => range.from <= markerEndPos && range.to >= indentStartPos
|
||||
);
|
||||
builder.add(
|
||||
indentStartPos,
|
||||
markerEndPos,
|
||||
import_view.Decoration.mark({
|
||||
attributes: { class: isCursorTouchingIndentOrMarker ? "dl-marker" : "dl-hidden-marker" }
|
||||
})
|
||||
);
|
||||
lastLineWasDefinition = true;
|
||||
lastLineWasTerm = false;
|
||||
} else if (isNextLineDefinition && !isNotTerm(trimmedLineText)) {
|
||||
builder.add(
|
||||
line.from,
|
||||
line.from,
|
||||
import_view.Decoration.line({
|
||||
attributes: { class: "dl-dt" }
|
||||
})
|
||||
);
|
||||
lastLineWasTerm = true;
|
||||
lastLineWasDefinition = false;
|
||||
} else {
|
||||
lastLineWasTerm = false;
|
||||
lastLineWasDefinition = false;
|
||||
}
|
||||
}
|
||||
return builder.finish();
|
||||
}
|
||||
}, {
|
||||
decorations: (v) => v.decorations
|
||||
});
|
||||
var DefinitionListPlugin = class extends import_obsidian.Plugin {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
// Post-processor for handling definition lists in reading mode
|
||||
this.definitionListPostProcessor = (element) => {
|
||||
function isNotTerm(content) {
|
||||
return content.match(/^#+\s/) !== null || // Heading
|
||||
content.match(/^\s*(-|\d+\.)\s/) !== null || // List item
|
||||
content.startsWith(">") || // Blockquote
|
||||
content.startsWith("<img") || // Image
|
||||
content.match(/^(-{3,}|\*{3,}|_{3,})/) !== null || // Horizontal rule
|
||||
content.startsWith("[^") || // Footnote
|
||||
content.includes('class="footnote-backref footnote-link"') || // Footnote backref
|
||||
content.startsWith("|") || // Table
|
||||
content.startsWith("$$") || // Math block
|
||||
content.startsWith("^");
|
||||
}
|
||||
const paragraphs = element.querySelectorAll("p");
|
||||
paragraphs.forEach((paragraph) => {
|
||||
const lines = paragraph.innerHTML.split("<br>");
|
||||
let dl = null;
|
||||
let currentTerm = null;
|
||||
let newContent = [];
|
||||
let invalidateCurrentPair = false;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i].trim();
|
||||
const nextLine = i < lines.length - 1 ? lines[i + 1].trim() : "";
|
||||
const definitionMatch = line.match(/^(\s*)([:~])\s(.+)/);
|
||||
const isNextLineDefinition = nextLine.match(/^(\s*)([:~])\s(.+)/);
|
||||
if (definitionMatch && !invalidateCurrentPair) {
|
||||
if (definitionMatch[3].includes('class="footnote-backref footnote-link"')) {
|
||||
invalidateCurrentPair = true;
|
||||
}
|
||||
if (currentTerm && !invalidateCurrentPair) {
|
||||
if (!dl) {
|
||||
dl = document.createElement("dl");
|
||||
newContent.push(dl);
|
||||
const dt = document.createElement("dt");
|
||||
dt.innerHTML = currentTerm;
|
||||
dl.appendChild(dt);
|
||||
}
|
||||
const dd = document.createElement("dd");
|
||||
dd.innerHTML = definitionMatch[3];
|
||||
dl.appendChild(dd);
|
||||
} else {
|
||||
if (currentTerm) {
|
||||
newContent.push(currentTerm + "<br>");
|
||||
}
|
||||
newContent.push(line + "<br>");
|
||||
currentTerm = null;
|
||||
invalidateCurrentPair = false;
|
||||
}
|
||||
} else if (isNextLineDefinition && !isNotTerm(line) && !invalidateCurrentPair) {
|
||||
if (currentTerm) {
|
||||
newContent.push(currentTerm + "<br>");
|
||||
}
|
||||
currentTerm = line;
|
||||
dl = null;
|
||||
} else {
|
||||
if (currentTerm) {
|
||||
newContent.push(currentTerm + "<br>");
|
||||
currentTerm = null;
|
||||
}
|
||||
newContent.push(line + "<br>");
|
||||
dl = null;
|
||||
invalidateCurrentPair = false;
|
||||
}
|
||||
}
|
||||
paragraph.innerHTML = "";
|
||||
newContent.forEach((content) => {
|
||||
if (typeof content === "string") {
|
||||
paragraph.innerHTML += content;
|
||||
} else {
|
||||
paragraph.appendChild(content);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
async onload() {
|
||||
this.registerMarkdownPostProcessor(this.definitionListPostProcessor);
|
||||
this.registerEditorExtension(definitionListPlugin);
|
||||
}
|
||||
onunload() {
|
||||
}
|
||||
};
|
||||
|
||||
/* nosourcemap */
|
11
.obsidian/plugins/definition-list/manifest.json
vendored
Normal file
11
.obsidian/plugins/definition-list/manifest.json
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"id": "definition-list",
|
||||
"name": "Definition List",
|
||||
"version": "0.2.1",
|
||||
"minAppVersion": "1.6.0",
|
||||
"description": "Adds definition lists to the markdown parser.",
|
||||
"author": "shammond42",
|
||||
"authorUrl": "https://northlandcreativewonders.com",
|
||||
"fundingUrl": "https://buymeacoffee.com/ncwonders",
|
||||
"isDesktopOnly": false
|
||||
}
|
29
.obsidian/plugins/definition-list/styles.css
vendored
Normal file
29
.obsidian/plugins/definition-list/styles.css
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
/* reading mode */
|
||||
dl dt {
|
||||
font-weight: bold;
|
||||
padding-block-start: var(--list-spacing);
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-inline-start: var(--list-indent);
|
||||
padding-block-end: var(--list-spacing);
|
||||
}
|
||||
|
||||
/* live preview */
|
||||
.dl-dt {
|
||||
font-weight: bold;
|
||||
padding-block-start: var(--list-spacing);
|
||||
}
|
||||
|
||||
.markdown-source-view.mod-cm6 .cm-line.dl-dd-reg, .markdown-source-view.mod-cm6 .cm-line.dl-dd-indent {
|
||||
padding-inline-start: var(--list-indent-editing);
|
||||
padding-block-end: var(--list-spacing); /* to add space between definitions, must use padding */
|
||||
}
|
||||
|
||||
.markdown-source-view.mod-cm6 .cm-line.dl-dd-indent {
|
||||
text-indent: 0;
|
||||
}
|
||||
|
||||
.dl-hidden-marker {
|
||||
display: none;
|
||||
}
|
1955
.obsidian/plugins/obsidian-trash-explorer/main.js
vendored
Normal file
1955
.obsidian/plugins/obsidian-trash-explorer/main.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
10
.obsidian/plugins/obsidian-trash-explorer/manifest.json
vendored
Normal file
10
.obsidian/plugins/obsidian-trash-explorer/manifest.json
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "obsidian-trash-explorer",
|
||||
"name": "Trash Explorer",
|
||||
"version": "1.2.3",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Restore and delete files from the Obsidian .trash folder",
|
||||
"author": "Per Mortensen",
|
||||
"authorUrl": "https://permortensen.com",
|
||||
"isDesktopOnly": false
|
||||
}
|
5
.obsidian/switcher.json
vendored
Normal file
5
.obsidian/switcher.json
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"showExistingOnly": false,
|
||||
"showAttachments": true,
|
||||
"showAllFileTypes": true
|
||||
}
|
4
.obsidian/templates.json
vendored
Normal file
4
.obsidian/templates.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"folder": "templates",
|
||||
"timeFormat": "HHmm"
|
||||
}
|
153
.obsidian/workspace-mobile.json
vendored
Normal file
153
.obsidian/workspace-mobile.json
vendored
Normal file
|
@ -0,0 +1,153 @@
|
|||
{
|
||||
"main": {
|
||||
"id": "85182147ab28350a",
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "00ba0ef2c731e4ef",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "d5ef3a88188fa168",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "2024-11-23 1054.md",
|
||||
"mode": "source",
|
||||
"backlinks": false,
|
||||
"source": true
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "2024-11-23 1054"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "vertical"
|
||||
},
|
||||
"left": {
|
||||
"id": "d6ed2530f221082a",
|
||||
"type": "mobile-drawer",
|
||||
"children": [
|
||||
{
|
||||
"id": "c2955ae16fd6d60f",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "file-explorer",
|
||||
"state": {
|
||||
"sortOrder": "alphabetical"
|
||||
},
|
||||
"icon": "lucide-folder-closed",
|
||||
"title": "Files"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "c9bdf2ba11adf6ff",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "search",
|
||||
"state": {
|
||||
"query": "",
|
||||
"matchingCase": false,
|
||||
"explainSearch": false,
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical"
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "Plugin no longer active"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "c20284c67fc84053",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "tag",
|
||||
"state": {
|
||||
"sortOrder": "frequency",
|
||||
"useHierarchy": true
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "Plugin no longer active"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "ec7730e05e2ec4a9",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "bookmarks",
|
||||
"state": {},
|
||||
"icon": "lucide-file",
|
||||
"title": "Plugin no longer active"
|
||||
}
|
||||
}
|
||||
],
|
||||
"currentTab": 0
|
||||
},
|
||||
"right": {
|
||||
"id": "99c2a1c932c8cf84",
|
||||
"type": "mobile-drawer",
|
||||
"children": [
|
||||
{
|
||||
"id": "15cb0d935729a7cd",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "backlink",
|
||||
"state": {
|
||||
"collapseAll": false,
|
||||
"extraContext": false,
|
||||
"sortOrder": "alphabetical",
|
||||
"showSearch": false,
|
||||
"searchQuery": "",
|
||||
"backlinkCollapsed": false,
|
||||
"unlinkedCollapsed": true
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "Plugin no longer active"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "6bef787c5012ed03",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "outgoing-link",
|
||||
"state": {
|
||||
"linksCollapsed": false,
|
||||
"unlinkedCollapsed": true
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "Plugin no longer active"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "d0d12e782fc088dd",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "outline",
|
||||
"state": {
|
||||
"file": "2024-11-23 1054.md"
|
||||
},
|
||||
"icon": "lucide-list",
|
||||
"title": "Outline"
|
||||
}
|
||||
}
|
||||
],
|
||||
"currentTab": 2
|
||||
},
|
||||
"left-ribbon": {
|
||||
"hiddenItems": {
|
||||
"templates:Insert template": false,
|
||||
"zk-prefixer:Create new unique note": false,
|
||||
"obsidian-trash-explorer:Open trash explorer": false,
|
||||
"command-palette:Open command palette": false
|
||||
}
|
||||
},
|
||||
"active": "d5ef3a88188fa168",
|
||||
"lastOpenFiles": [
|
||||
"2024-11-23 094942-0500.md",
|
||||
"2024-11-23 094844-0500.md",
|
||||
"2024-11-22 0836.md"
|
||||
]
|
||||
}
|
129
.obsidian/workspace.json
vendored
Normal file
129
.obsidian/workspace.json
vendored
Normal file
|
@ -0,0 +1,129 @@
|
|||
{
|
||||
"main": {
|
||||
"id": "5b372e93d410ee3a",
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "3f151db712026be4",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "25ae7f7668563155",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "empty",
|
||||
"state": {},
|
||||
"icon": "lucide-file",
|
||||
"title": "New tab"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "vertical"
|
||||
},
|
||||
"left": {
|
||||
"id": "ee98c845c6bccaf5",
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "941e7fff857ace7c",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "26de835c41a7b9e7",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "file-explorer",
|
||||
"state": {
|
||||
"sortOrder": "alphabetical"
|
||||
},
|
||||
"icon": "lucide-folder-closed",
|
||||
"title": "Files"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "d24bddab7f4eb3b5",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "trash-explorer",
|
||||
"state": {},
|
||||
"icon": "trash",
|
||||
"title": "Trash explorer"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "horizontal",
|
||||
"width": 300
|
||||
},
|
||||
"right": {
|
||||
"id": "a4faa311cef524ef",
|
||||
"type": "split",
|
||||
"children": [
|
||||
{
|
||||
"id": "601d4a954f67eb4d",
|
||||
"type": "tabs",
|
||||
"children": [
|
||||
{
|
||||
"id": "ef81523b69933e90",
|
||||
"type": "leaf",
|
||||
"state": {
|
||||
"type": "outline",
|
||||
"state": {
|
||||
"file": "2024-11-23 1151.md"
|
||||
},
|
||||
"icon": "lucide-list",
|
||||
"title": "Outline of 2024-11-23 1151"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"direction": "horizontal",
|
||||
"width": 300
|
||||
},
|
||||
"left-ribbon": {
|
||||
"hiddenItems": {
|
||||
"command-palette:Open command palette": false,
|
||||
"zk-prefixer:Create new unique note": true,
|
||||
"templates:Insert template": true,
|
||||
"obsidian-trash-explorer:Open trash explorer": true
|
||||
}
|
||||
},
|
||||
"active": "26de835c41a7b9e7",
|
||||
"lastOpenFiles": [
|
||||
"2024-11-23 1151.md",
|
||||
"2024-11-23 1054.md",
|
||||
"2024-11-23 1134.md",
|
||||
"templates/Shower Thought.md",
|
||||
"2024-11-23 1052.md",
|
||||
"2024-11-23 1051.md",
|
||||
"Untitled.md",
|
||||
"_attachments/_attachments.md",
|
||||
"Dashboard.md",
|
||||
"2024-11-14 170356-0500.md",
|
||||
"2024-11-14 170309-0500.md",
|
||||
"2024-11-14 170137-0500.md",
|
||||
"Readme.md",
|
||||
"Vaults/Medical/__Using The Vault.md",
|
||||
"Vaults/Medical/_Troubleshooting The Vault.md",
|
||||
"__Dashboard.md",
|
||||
"Vaults/Medical",
|
||||
"Vaults",
|
||||
"2024-09-29-1427.md",
|
||||
"Test.md",
|
||||
".md",
|
||||
"testing.md",
|
||||
"test.md",
|
||||
"Untitled 1",
|
||||
"Enter File Name.md",
|
||||
"Untitled 1.md",
|
||||
"Testing.md",
|
||||
"__attic",
|
||||
"2024-09-29 0932.md",
|
||||
"templates",
|
||||
"attachments"
|
||||
]
|
||||
}
|
4
.obsidian/zk-prefixer.json
vendored
Normal file
4
.obsidian/zk-prefixer.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"format": "YYYY-MM-DD HHmm",
|
||||
"template": "templates/Shower Thought"
|
||||
}
|
1
attachments/.nomedia
Normal file
1
attachments/.nomedia
Normal file
|
@ -0,0 +1 @@
|
|||
/storage/emulated/0/Krita
|
1
templates/.nomedia
Normal file
1
templates/.nomedia
Normal file
|
@ -0,0 +1 @@
|
|||
/storage/emulated/0/Krita
|
16
templates/Shower Thought.md
Normal file
16
templates/Shower Thought.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
tags:
|
||||
- shower-thought
|
||||
created_ts: "{{date}} {{time}}"
|
||||
source:
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
```table-of-contents
|
||||
title: **Table of Contents**
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Shower_Thought
|
Loading…
Reference in a new issue