Andley_BG4e/.obsidian/plugins/obsidian-footnotes/main.js

327 lines
68 KiB
JavaScript
Raw Normal View History

vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
'use strict';
var obsidian = require('obsidian');
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
//Add chevron-up-square icon from lucide for mobile toolbar (temporary until Obsidian updates to Lucide v0.130.0)
obsidian.addIcon("chevron-up-square", `<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="lucide lucide-chevron-up-square"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><polyline points="8,14 12,10 16,14"></polyline></svg>`);
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
class MyPlugin extends obsidian.Plugin {
constructor() {
super(...arguments);
this.AllMarkers = /\[\^([^\[\]]+)\](?!:)/dg;
this.AllNumberedMarkers = /\[\^(\d+)\]/gi;
this.AllDetailsNameOnly = /\[\^([^\[\]]+)\]:/g;
this.DetailInLine = /\[\^([^\[\]]+)\]:/;
this.ExtractNameFromFootnote = /(\[\^)([^\[\]]+)(?=\])/;
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
}
onload() {
return __awaiter(this, void 0, void 0, function* () {
this.addCommand({
id: "insert-autonumbered-footnote",
name: "Insert / Navigate Auto-Numbered Footnote",
icon: "plus-square",
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
checkCallback: (checking) => {
if (checking)
return !!this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
this.insertAutonumFootnote();
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
},
});
this.addCommand({
id: "insert-named-footnote",
name: "Insert / Navigate Named Footnote",
icon: "chevron-up-square",
checkCallback: (checking) => {
if (checking)
return !!this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
this.insertNamedFootnote();
}
});
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
});
}
//UNIVERSAL FUNCTIONS
listExistingFootnoteDetails(doc) {
let FootnoteDetailList = [];
//search each line for footnote details and add to list
for (let i = 0; i < doc.lineCount(); i++) {
let theLine = doc.getLine(i);
let lineMatch = theLine.match(this.AllDetailsNameOnly);
if (lineMatch) {
let temp = lineMatch[0];
temp = temp.replace("[^", "");
temp = temp.replace("]:", "");
FootnoteDetailList.push(temp);
}
}
if (FootnoteDetailList.length > 0) {
return FootnoteDetailList;
}
else {
return null;
}
}
listExistingFootnoteMarkersAndLocations(doc) {
let markerEntry;
let FootnoteMarkerInfo = [];
//search each line for footnote markers
//for each, add their name, line number, and start index to FootnoteMarkerInfo
for (let i = 0; i < doc.lineCount(); i++) {
let theLine = doc.getLine(i);
let lineMatch;
while ((lineMatch = this.AllMarkers.exec(theLine)) != null) {
markerEntry = {
footnote: lineMatch[0],
lineNum: i,
startIndex: lineMatch.index
};
FootnoteMarkerInfo.push(markerEntry);
}
}
return FootnoteMarkerInfo;
}
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
shouldJumpFromDetailToMarker(lineText, cursorPosition, doc) {
// check if we're in a footnote detail line ("[^1]: footnote")
// if so, jump cursor back to the footnote in the text
// https://github.com/akaalias/obsidian-footnotes#improved-quick-navigation
let match = lineText.match(this.DetailInLine);
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
if (match) {
let s = match[0];
let index = s.replace("[^", "");
index = index.replace("]:", "");
let footnote = s.replace(":", "");
let returnLineIndex = cursorPosition.line;
// find the FIRST OCCURENCE where this footnote exists in the text
for (let i = 0; i < doc.lineCount(); i++) {
let scanLine = doc.getLine(i);
if (scanLine.contains(footnote)) {
let cursorLocationIndex = scanLine.indexOf(footnote);
returnLineIndex = i;
doc.setCursor({
line: returnLineIndex,
ch: cursorLocationIndex + footnote.length,
});
return true;
}
}
}
return false;
}
shouldJumpFromMarkerToDetail(lineText, cursorPosition, doc) {
// Jump cursor TO detail marker
// does this line have a footnote marker?
// does the cursor overlap with one of them?
// if so, which one?
// find this footnote marker's detail line
// place cursor there
let markerTarget = null;
let FootnoteMarkerInfo = this.listExistingFootnoteMarkersAndLocations(doc);
let currentLine = cursorPosition.line;
let footnotesOnLine = FootnoteMarkerInfo.filter(markerEntry => markerEntry.lineNum === currentLine);
if (footnotesOnLine != null) {
for (let i = 0; i <= footnotesOnLine.length - 1; i++) {
if (footnotesOnLine[i].footnote !== null) {
let marker = footnotesOnLine[i].footnote;
let indexOfMarkerInLine = footnotesOnLine[i].startIndex;
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
if (cursorPosition.ch >= indexOfMarkerInLine &&
cursorPosition.ch <= indexOfMarkerInLine + marker.length) {
markerTarget = marker;
break;
}
}
}
}
if (markerTarget !== null) {
// extract name
let match = markerTarget.match(this.ExtractNameFromFootnote);
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
if (match) {
let footnoteName = match[2];
// find the first line with this detail marker name in it.
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
for (let i = 0; i < doc.lineCount(); i++) {
let theLine = doc.getLine(i);
let lineMatch = theLine.match(this.DetailInLine);
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
if (lineMatch) {
// compare to the index
let nameMatch = lineMatch[1];
if (nameMatch == footnoteName) {
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
doc.setCursor({ line: i, ch: lineMatch[0].length + 1 });
return true;
}
}
}
}
}
return false;
}
//FUNCTIONS FOR AUTONUMBERED FOOTNOTES
insertAutonumFootnote() {
const mdView = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (!mdView)
return false;
if (mdView.editor == undefined)
return false;
const doc = mdView.editor;
const cursorPosition = doc.getCursor();
const lineText = doc.getLine(cursorPosition.line);
const markdownText = mdView.data;
if (this.shouldJumpFromDetailToMarker(lineText, cursorPosition, doc))
return;
if (this.shouldJumpFromMarkerToDetail(lineText, cursorPosition, doc))
return;
return this.shouldCreateAutonumFootnote(lineText, cursorPosition, doc, markdownText);
}
shouldCreateAutonumFootnote(lineText, cursorPosition, doc, markdownText) {
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
// create new footnote with the next numerical index
let matches = markdownText.match(this.AllNumberedMarkers);
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
let currentMax = 1;
if (matches != null) {
for (let i = 0; i <= matches.length - 1; i++) {
let match = matches[i];
match = match.replace("[^", "");
match = match.replace("]", "");
let matchNumber = Number(match);
if (matchNumber + 1 > currentMax) {
currentMax = matchNumber + 1;
}
}
}
let footNoteId = currentMax;
let footnoteMarker = `[^${footNoteId}]`;
let linePart1 = lineText.substr(0, cursorPosition.ch);
let linePart2 = lineText.substr(cursorPosition.ch);
let newLine = linePart1 + footnoteMarker + linePart2;
doc.replaceRange(newLine, { line: cursorPosition.line, ch: 0 }, { line: cursorPosition.line, ch: lineText.length });
let lastLineIndex = doc.lastLine();
let lastLine = doc.getLine(lastLineIndex);
while (lastLineIndex > 0) {
lastLine = doc.getLine(lastLineIndex);
if (lastLine.length > 0) {
doc.replaceRange("", { line: lastLineIndex, ch: 0 }, { line: doc.lastLine(), ch: 0 });
break;
}
lastLineIndex--;
}
let footnoteDetail = `\n[^${footNoteId}]: `;
let list = this.listExistingFootnoteDetails(doc);
if (list === null && currentMax == 1) {
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
footnoteDetail = "\n" + footnoteDetail;
doc.setLine(doc.lastLine(), lastLine + footnoteDetail);
doc.setCursor(doc.lastLine() - 1, footnoteDetail.length - 1);
}
else {
doc.setLine(doc.lastLine(), lastLine + footnoteDetail);
doc.setCursor(doc.lastLine(), footnoteDetail.length - 1);
}
}
//FUNCTIONS FOR NAMED FOOTNOTES
insertNamedFootnote() {
const mdView = this.app.workspace.getActiveViewOfType(obsidian.MarkdownView);
if (!mdView)
return false;
if (mdView.editor == undefined)
return false;
const doc = mdView.editor;
const cursorPosition = doc.getCursor();
const lineText = doc.getLine(cursorPosition.line);
const markdownText = mdView.data;
if (this.shouldJumpFromDetailToMarker(lineText, cursorPosition, doc))
return;
if (this.shouldJumpFromMarkerToDetail(lineText, cursorPosition, doc))
return;
if (this.shouldCreateMatchingFootnoteDetail(lineText, cursorPosition, doc))
return;
return this.shouldCreateFootnoteMarker(lineText, cursorPosition, doc, markdownText);
}
shouldCreateMatchingFootnoteDetail(lineText, cursorPosition, doc) {
// Create matching footnote detail for footnote marker
// does this line have a footnote marker?
// does the cursor overlap with one of them?
// if so, which one?
// does this footnote marker have a detail line?
// if not, create it and place cursor there
let reOnlyMarkersMatches = lineText.match(this.AllMarkers);
let markerTarget = null;
if (reOnlyMarkersMatches) {
for (let i = 0; i <= reOnlyMarkersMatches.length; i++) {
let marker = reOnlyMarkersMatches[i];
if (marker != undefined) {
let indexOfMarkerInLine = lineText.indexOf(marker);
if (cursorPosition.ch >= indexOfMarkerInLine &&
cursorPosition.ch <= indexOfMarkerInLine + marker.length) {
markerTarget = marker;
break;
}
}
}
}
if (markerTarget != null) {
//extract footnote
let match = markerTarget.match(this.ExtractNameFromFootnote);
//find if this footnote exists by listing existing footnote details
if (match) {
let footnoteId = match[2];
let list = this.listExistingFootnoteDetails(doc);
// Check if the list is empty OR if the list doesn't include current footnote
// if so, add detail for the current footnote
if (list === null || !list.includes(footnoteId)) {
let lastLineIndex = doc.lastLine();
let lastLine = doc.getLine(lastLineIndex);
while (lastLineIndex > 0) {
lastLine = doc.getLine(lastLineIndex);
if (lastLine.length > 0) {
doc.replaceRange("", { line: lastLineIndex, ch: 0 }, { line: doc.lastLine(), ch: 0 });
break;
}
lastLineIndex--;
}
let footnoteDetail = `\n[^${footnoteId}]: `;
if (list === null || list.length < 1) {
footnoteDetail = "\n" + footnoteDetail;
doc.setLine(doc.lastLine(), lastLine + footnoteDetail);
doc.setCursor(doc.lastLine() - 1, footnoteDetail.length - 1);
}
else {
doc.setLine(doc.lastLine(), lastLine + footnoteDetail);
doc.setCursor(doc.lastLine(), footnoteDetail.length - 1);
}
return true;
}
return;
}
}
}
shouldCreateFootnoteMarker(lineText, cursorPosition, doc, markdownText) {
//create empty footnote marker for name input
let emptyMarker = `[^]`;
doc.replaceRange(emptyMarker, doc.getCursor());
//move cursor in between [^ and ]
doc.setCursor(cursorPosition.line, cursorPosition.ch + 2);
//open footnotePicker popup
}
vault backup: 2022-12-20 10:02:37 Affected files: .gitignore .obsidian/app.json .obsidian/appearance.json .obsidian/community-plugins.json .obsidian/config .obsidian/core-plugins.json .obsidian/global-search.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/control-characters/data.json .obsidian/plugins/control-characters/main.js .obsidian/plugins/control-characters/manifest.json .obsidian/plugins/control-characters/styles.css .obsidian/plugins/obsidian-footnotes/main.js .obsidian/plugins/obsidian-footnotes/manifest.json .obsidian/plugins/obsidian-footnotes/styles.css .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/data[衝突].json .obsidian/plugins/obsidian-git/main.js .obsidian/plugins/obsidian-git/manifest.json .obsidian/plugins/obsidian-git/styles.css .obsidian/plugins/obsidian-hider/data.json .obsidian/plugins/obsidian-hider/main.js .obsidian/plugins/obsidian-hider/manifest.json .obsidian/plugins/obsidian-hider/styles.css .obsidian/plugins/obsidian-regex-replace/data.json .obsidian/plugins/obsidian-regex-replace/main.js .obsidian/plugins/obsidian-regex-replace/manifest.json .obsidian/plugins/obsidian-regex-replace/styles.css .obsidian/plugins/obsidian-tidy-footnotes/main.js .obsidian/plugins/obsidian-tidy-footnotes/manifest.json .obsidian/plugins/wikilinks-to-mdlinks-obsidian/main.js .obsidian/plugins/wikilinks-to-mdlinks-obsidian/manifest.json .obsidian/rtl.json .obsidian/snippets/bg4e.css .obsidian/snippets/margin-narrow.css .obsidian/snippets/margin-wide.css .obsidian/starred.json .obsidian/templates.json .obsidian/workspace .obsidian/workspace.json .obsidian/workspaces.json
2022-12-20 02:02:37 +00:00
}
module.exports = MyPlugin;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZXMiOlsibm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5qcyIsIm1haW4udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcclxuICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcclxuICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXh0ZW5kcyhkLCBiKSB7XHJcbiAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxyXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICBpZiAoZS5pbmRleE9mKHBbaV0pIDwgMCAmJiBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwocywgcFtpXSkpXHJcbiAgICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgICAgICB9XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpIHtcclxuICAgIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XHJcbiAgICBpZiAodHlwZW9mIFJlZmxlY3QgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIFJlZmxlY3QuZGVjb3JhdGUgPT09IFwiZnVuY3Rpb25cIikgciA9IFJlZmxlY3QuZGVjb3JhdGUoZGVjb3JhdG9ycywgdGFyZ2V0LCBrZXksIGRlc2MpO1xyXG4gICAgZWxzZSBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgaWYgKGQgPSBkZWNvcmF0b3JzW2ldKSByID0gKGMgPCAzID8gZChyKSA