Skip to content

Commit

Permalink
0.0.20 Bug hunting (headings/alias) and fine tuned settings for recen…
Browse files Browse the repository at this point in the history
…t changes
  • Loading branch information
TfT Hacker committed Oct 2, 2022
1 parent fb3bfbd commit 459159d
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 149 deletions.
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "obsidian42-strange-new-worlds",
"name": "Obsidian42 - Strange New Worlds",
"version": "0.0.19",
"version": "0.0.20",
"minAppVersion": "0.16.3",
"description": "Revealing networked thought and the strange new worlds created by your vault",
"author": "TfTHacker",
Expand Down
11 changes: 6 additions & 5 deletions src/cm-extensions/gutters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {gutter, GutterMarker, } from "@codemirror/view";
import { BlockInfo, EditorView } from "@codemirror/view";
import { editorInfoField } from "obsidian";
import { htmlDecorationForReferencesElement } from "src/cm-extensions/htmlDecorations";
import { getCurrentPage } from "src/indexer";
import { getSNWCacheByFile } from "src/indexer";
import ThePlugin from "src/main";

let thePlugin: ThePlugin;
Expand Down Expand Up @@ -49,17 +49,18 @@ const ReferenceGutterExtension = gutter({

const embedsFromMetaDataCache = mdView.app.metadataCache.getFileCache(mdView.file)?.embeds;

if(embedsFromMetaDataCache?.length>0) {
if(embedsFromMetaDataCache?.length >= thePlugin.settings.minimumRefCountThreshold) {
const lineNumberInFile = editorView.state.doc.lineAt(line.from).number;
for (const embed of embedsFromMetaDataCache) {
if(embed.position.start.line +1 === lineNumberInFile) {
const transformedCache = getCurrentPage(mdView.file);
if(thePlugin.snwAPI.enableDebugging.GutterEmbedCounter)
thePlugin.snwAPI.console("ReferenceGutterExtension transformedCache", transformedCache );
const transformedCache = getSNWCacheByFile(mdView.file);
if(thePlugin.snwAPI.enableDebugging.GutterEmbedCounter) thePlugin.snwAPI.console("ReferenceGutterExtension transformedCache", transformedCache );
for (const ref of transformedCache.embeds) {
if(ref?.references.length>0 && ref?.pos.start.line+1 === lineNumberInFile) {
// @ts-ignore
let refOriginalLink = ref.references[0].reference.original;
if(refOriginalLink.contains("|")) // likely has an alias embedded which needs to be removed for proper matching
refOriginalLink = refOriginalLink.substring(0, refOriginalLink.search(/\|/)) + "]]";
if(refOriginalLink.substring(0,1)!="!")
refOriginalLink = "!" + refOriginalLink;
if( editorView.state.doc.lineAt(line.from).text.trim() === refOriginalLink) {
Expand Down
20 changes: 14 additions & 6 deletions src/cm-extensions/references-cm6.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EditorView, Decoration, MatchDecorator, ViewUpdate, ViewPlugin, DecorationSet, WidgetType} from "@codemirror/view";
import { editorInfoField } from "obsidian";
import { getCurrentPage } from "src/indexer";
import { getSNWCacheByFile } from "src/indexer";
import { TransformedCachedItem } from "../types";
import { htmlDecorationForReferencesElement } from "./htmlDecorations";
import ThePlugin from "src/main";
Expand Down Expand Up @@ -52,7 +52,7 @@ export const InlineReferenceExtension = ViewPlugin.fromClass(class {
const firstCharacterMatch = match[0].charAt(0);
let refType = "";
let key = "";
const transformedCache = getCurrentPage(mdView.file);
const transformedCache = getSNWCacheByFile(mdView.file);
let transformedCachedItem: TransformedCachedItem[] = null;
let wdgt: InlineReferenceWidget = null;

Expand All @@ -74,7 +74,10 @@ export const InlineReferenceExtension = ViewPlugin.fromClass(class {
transformedCachedItem = transformedCache.headings
refType = "heading";
}


if((refType==="embed" || refType==="link") && key.contains("|")) // check for aliased references
key = key.substring(0, key.search(/\|/));

if(key!="") {
wdgt = constructWidgetForInlineReference(refType, key, transformedCachedItem, mdView.file.path);
if(wdgt!=null)
Expand Down Expand Up @@ -110,12 +113,17 @@ export const InlineReferenceExtension = ViewPlugin.fromClass(class {
const constructWidgetForInlineReference = (refType: string, key: string, references: TransformedCachedItem[], filePath: string): InlineReferenceWidget => {
for (let i = 0; i < references.length; i++) {
const ref = references[i];
const matchKey = refType==="heading" ? ref.headerMatch : ref.key;
if(matchKey===key)
if(ref?.references.length>0)
let matchKey = ref.key;
if(refType==="heading") {
matchKey = ref.headerMatch; // headers require special comparison
key = key.replace(/^\s+|\s+$/g,''); // should be not leading spaces
}
if(matchKey===key) {
if(ref?.references.length>=thePlugin.settings.minimumRefCountThreshold)
return new InlineReferenceWidget(ref.references.length, ref.type, ref.key, ref.references[0].resolvedFile.path.replace(".md",""), null, ref.pos.start.line);
else
return null;
}
}
}

Expand Down
18 changes: 10 additions & 8 deletions src/cm-extensions/references-preview.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {MarkdownPostProcessorContext} from "obsidian";
import {htmlDecorationForReferencesElement} from "./htmlDecorations";
import {getCurrentPage} from "../indexer";
import {getSNWCacheByFile} from "../indexer";
import ThePlugin from "../main";


Expand Down Expand Up @@ -35,7 +35,9 @@ export default function markdownPreviewProcessor(el : HTMLElement, ctx : Markdow
// check for incompatibility with other plugins
if(app.metadataCache.getFileCache(currentFile)?.frontmatter?.["kanban-plugin"] ) return; //no support for kanban board

const transformedCache = getCurrentPage(currentFile);
const transformedCache = getSNWCacheByFile(currentFile);

const minRefCountThreshold = thePlugin.settings.minimumRefCountThreshold;

if (transformedCache?.blocks || transformedCache.embeds || transformedCache.headings || transformedCache.links) {
const sectionInfo = ctx.getSectionInfo(el);
Expand All @@ -48,10 +50,10 @@ export default function markdownPreviewProcessor(el : HTMLElement, ctx : Markdow
} catch (error) { /* nothing to do here */ }

for (const value of transformedCache.blocks) {
if ( value.references.length > 0 &&
if ( value.references.length >= minRefCountThreshold &&
(value.pos.start.line >= sectionInfo?.lineStart && value.pos.end.line <= sectionInfo?.lineEnd) &&
!isThisAnEmbed ) {
const referenceElement = htmlDecorationForReferencesElement(value.references.length, "block", value.key, value.references[0].resolvedFile.path.replace(".md",""), "", value.pos.start.line);
const referenceElement = htmlDecorationForReferencesElement(value.references.length, "block", value.key, value.references[0].resolvedFile.path.replace(".md",""), "", value.pos.start.line);
let blockElement: HTMLElement = el.querySelector('p')
if (!blockElement) {
blockElement = el.querySelector("li");
Expand All @@ -71,7 +73,7 @@ export default function markdownPreviewProcessor(el : HTMLElement, ctx : Markdow
el.querySelectorAll(".internal-embed:not(.snw-embed-preview)").forEach(element => {
const embedKey = element.getAttribute('src');
for (const value of transformedCache.embeds) {
if (value.references.length > 0 && embedKey.endsWith(value.key)) {
if (value.references.length >= minRefCountThreshold && embedKey.endsWith(value.key)) {
const referenceElement = htmlDecorationForReferencesElement(value.references.length, "embed", value.key, value.references[0].resolvedFile.path.replace(".md",""), "", value.pos.start.line);
referenceElement.addClass('snw-embed-preview');
element.after(referenceElement);
Expand All @@ -84,9 +86,9 @@ export default function markdownPreviewProcessor(el : HTMLElement, ctx : Markdow
if(thePlugin.settings.enableRenderingHeadersInMarkdown) {
const headerKey = el.querySelector("[data-heading]");
if (transformedCache?.headings && headerKey) {
const textContext = headerKey.textContent
const textContext = headerKey.getAttribute("data-heading")
for (const value of transformedCache.headings) {
if (value.references.length > 0 && value.headerMatch === textContext) {
if (value.references.length >= minRefCountThreshold && value.headerMatch === textContext) {
const referenceElement = htmlDecorationForReferencesElement(value.references.length, "heading", value.key, value.references[0].resolvedFile.path.replace(".md",""), "", value.pos.start.line);
referenceElement.addClass("snw-heading-preview");
el.querySelector("h1,h2,h3,h4,h5,h6").insertAdjacentElement("beforeend", referenceElement);
Expand All @@ -100,7 +102,7 @@ export default function markdownPreviewProcessor(el : HTMLElement, ctx : Markdow
el.querySelectorAll("a.internal-link:not(.snw-link-preview)").forEach(element => {
const link = element.getAttribute('data-href');
for (const value of transformedCache.links) {
if (value.references.length > 0 && (value.key === link || (value?.original!=undefined && value?.original.contains(link)))) {
if (value.references.length >= minRefCountThreshold && (value.key === link || (value?.original!=undefined && value?.original.contains(link)))) {
const referenceElement = htmlDecorationForReferencesElement(value.references.length, "link", value.key, value.references[0].resolvedFile.path.replace(".md",""), "", value.pos.start.line);
referenceElement.addClass('snw-link-preview');
element.after(referenceElement);
Expand Down
115 changes: 37 additions & 78 deletions src/indexer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@



import { CachedMetadata, HeadingCache, stripHeading, TFile, Pos} from "obsidian";
import ThePlugin from "./main";
import {Link, TransformedCache} from "./types";
// import {Link, ListItem, Section, TransformedCache} from "./types";


let references: {[x:string]:Link[]};
let allLinkRsolutions: Link[];
Expand All @@ -21,6 +22,12 @@ export function getSnwAllLinksResolutions(){
return allLinkRsolutions;
}

/**
* Buildings a optimized list of cache references for resolving the block count.
* It is only updated when there are data changes to the vault. This is hooked to an event
* trigger in main.ts
* @export
*/
export function buildLinksAndReferences(): void {
allLinkRsolutions = thePlugin.app.fileManager.getAllLinkResolutions(); //cache this for use in other pages
const refs = allLinkRsolutions.reduce((acc: {[x:string]: Link[]}, link : Link): { [x:string]: Link[] } => {
Expand All @@ -31,30 +38,42 @@ export function buildLinksAndReferences(): void {
keyBasedOnLink = link.reference.link;
keyBasedOnFullPath = link.resolvedFile.path.replace(link.resolvedFile.name,"") + link.reference.link;

if(!acc[keyBasedOnLink]) {
acc[keyBasedOnLink] = [];
if(keyBasedOnLink===keyBasedOnFullPath) {
keyBasedOnFullPath=null;
}
acc[keyBasedOnLink].push(link);

if(!acc[keyBasedOnFullPath]) {
acc[keyBasedOnFullPath] = [];
if(!acc[keyBasedOnLink]) {
acc[keyBasedOnLink] = [];
}
acc[keyBasedOnFullPath].push(link)
acc[keyBasedOnLink].push(link);

if(keyBasedOnFullPath!=null) {
if(!acc[keyBasedOnFullPath]) {
acc[keyBasedOnFullPath] = [];
}
acc[keyBasedOnFullPath].push(link)
}
return acc;
}, {});

references = refs;
// @ts-ignore
window.snwRefs = references;
window.snwAPI.references = references;
lastUpdateToReferences = Date.now();
}


// following MAP works as a cache for the getCurrentPage call. Based on time elapsed since last update, it just returns a cached transformedCache object
const cacheCurrentPages = new Map<string,TransformedCache>();

export function getCurrentPage(file: TFile): TransformedCache {
/**
* Provides an optimized view of the cache for determining the block count for references in a given page
*
* @export
* @param {TFile} file
* @return {*} {TransformedCache}
*/
export function getSNWCacheByFile(file: TFile): TransformedCache {

if(cacheCurrentPages.has(file.path)) {
const cachedPage = cacheCurrentPages.get(file.path);
Expand All @@ -66,13 +85,14 @@ export function getCurrentPage(file: TFile): TransformedCache {

const transformedCache: TransformedCache = {};
const cachedMetaData = thePlugin.app.metadataCache.getFileCache(file);
if (! cachedMetaData) {
if (!cachedMetaData) {
return transformedCache;
}

if (! references) {
if (!references) {
buildLinksAndReferences();
}

const headings: string[] = Object.values(thePlugin.app.metadataCache.metadataCache).reduce((acc : string[], file : CachedMetadata) => {
const headings = file.headings;
if (headings) {
Expand All @@ -94,17 +114,18 @@ export function getCurrentPage(file: TFile): TransformedCache {
references: references[ filePath + "#^" + block.id ] || []
}));
}

if (cachedMetaData?.headings) {
transformedCache.headings = cachedMetaData.headings.map((header: {heading: string; position: Pos; level: number;}) => ({
original: "#".repeat(header.level) + " " + header.heading,
key: `${file.path.replace(".md","")}#${header.heading}`,
key: `${file.path.replace(".md","")}#${stripHeading(header.heading)}`,
headerMatch: header.heading,
headerMatch2: file.basename + "#" + header.heading,
pos: header.position,
page: file.basename,
type: "heading",
references: references[`${file.path.replace(".md","")}#${header.heading}`] ||
references[`${file.basename}$#${(header.heading)}`] || []
references: references[`${file.path.replace(".md","")}#${stripHeading(header.heading)}`] ||
references[`${file.basename}$#${(stripHeading(header.heading))}`] || []
}));
}

Expand All @@ -121,33 +142,17 @@ export function getCurrentPage(file: TFile): TransformedCache {
});
if (transformedCache.links) {
transformedCache.links = transformedCache.links.map((link) => {
// if (link.key.includes("/")) {
// const keyArr = link.key.split("/");
// link.key = keyArr[keyArr.length - 1];
// }
if (link.key.includes("#") && !link.key.includes("#^")) {
const heading = headings.filter((heading : string) => stripHeading(heading) === link.key.split("#")[1])[0];
link.original = heading ? heading : undefined;
}
// if (link.key.startsWith("#^") || link.key.startsWith("#")) {
// link.key = `${link.page}${link.key}`;
// link.references = references[link.key] || [];
// }
return link;
});
// remove duplicate links
// if (transformedCache.links)
// transformedCache.linksWithoutDuplicates = transformedCache.links.filter((link, index, self) => index === self.findIndex((t) => (t.key === link.key)))

});
}
}

if (cachedMetaData?.embeds) {
transformedCache.embeds = cachedMetaData.embeds.map((embed) => {
// if (embed.link.includes("/")) {
// const keyArr = embed.link.split("/");
// embed.link = keyArr[keyArr.length - 1];
// }
return {
key: embed.link,
page: file.basename,
Expand All @@ -170,58 +175,12 @@ export function getCurrentPage(file: TFile): TransformedCache {
}
return embed;
});
// remove duplicate blocks
// if (transformedCache.embeds)
// transformedCache.embedsWithDuplicates = transformedCache.embeds.filter((embed, index, self) => index === self.findIndex((t) => (t.key === embed.key)))

}
}


transformedCache.cacheMetaData = cachedMetaData;
transformedCache.createDate = Date.now();
cacheCurrentPages.set(file.path, transformedCache);

return transformedCache;
}

/**
* If the section is of type list, add the list items from the metadataCache to the section object.
* This makes it easier to iterate a list when building block ref buttons
*
* @param {SectionCache[]} sections
* @param {ListItemCache[]} listItems
*
* @return {Section[]} Array of sections with additional items key
// */

// function createListSections(cache: CachedMetadata): Section[] {
// if (cache.listItems) {
// return cache.sections.map((section) => {
// const items: ListItem[] = [];
// if (section.type === "list") {
// cache.listItems.forEach((item : ListItem) => {
// if (item.position.start.line >= section.position.start.line && item.position.start.line<= section.position.end.line
// ) {
// const id = cache.embeds?.find(
// (embed) => embed.position.start.line === item.position.start.line) ?. link || cache.links ?. find((link) => link.position.start.line === item.position.start.line) ?. link || "";

// items.push({
// key: id,
// pos: item.position,
// ...item
// });
// }}
// );
// const sectionWithItems = {
// items,
// ...section
// };
// return sectionWithItems;
// }
// return section;
// }
// );
// }

// return cache.sections;}
4 changes: 2 additions & 2 deletions src/snwApi.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getCurrentPage } from "./indexer";
import { getSNWCacheByFile } from "./indexer";
import ThePlugin from "./main";
import { Settings } from "./ui/settingsTab";

Expand Down Expand Up @@ -52,7 +52,7 @@ export default class SnwAPI {
return {
TFile: currentFile,
metadataCache: app.metadataCache.getFileCache(currentFile),
SnwTransformedCache: getCurrentPage(currentFile),
SnwTransformedCache: getSNWCacheByFile(currentFile),
}
}
}
Loading

0 comments on commit 459159d

Please sign in to comment.