Skip to content

Commit

Permalink
feat: convert comments in reading mode to widgets (fixes #7)
Browse files Browse the repository at this point in the history
refactor: rewrite postprocessor to also output htmlelements
  • Loading branch information
Fevol committed Mar 4, 2024
1 parent 01b3d32 commit 7bc5cb9
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 61 deletions.
9 changes: 2 additions & 7 deletions src/editor/base/ranges/base_range.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import {ChangeSet} from '@codemirror/state';
import {CM_All_Brackets, type STRING_SUGGESTION_TYPE, type SuggestionType} from './definitions';
import type {EditorChange} from '../edit-handler';
import {type CommentRange} from './types';
import {RANGE_CURSOR_MOVEMENT_OPTION} from "../../../types";
import {PreviewMode, RANGE_CURSOR_MOVEMENT_OPTION} from "../../../types";


const shortHandMapping = {
Expand Down Expand Up @@ -266,18 +265,14 @@ export abstract class CriticMarkupRange {
this.touches_right_bracket(cursor, outside_loose, inside_loose);
}

postprocess(unwrap: boolean = true, livepreview_mode: number = 0, tag: string = 'div', left: boolean | null = null, text?: string) {
postprocess(unwrap: boolean = true, previewMode: PreviewMode = PreviewMode.ALL, tag: keyof HTMLElementTagNameMap = 'div', left: boolean | null = null, text?: string): string | HTMLElement {
let str = text ?? this.text;
if (!text && unwrap) {
// Range is larger than what is actually given (no end bracket found within text)
if (this.to >= str.length && !str.endsWith(CM_All_Brackets[this.type].at(-1)!))
str = this.unwrap_bracket(true);
/*else if (this.from === 0 && !str.startsWith(CM_All_Brackets[this.type][0]))
str = this.unwrap_bracket(str, false);*/
else
str = this.unwrap();
}

return `<${tag} class='criticmarkup-${this.repr.toLowerCase()}'>${str}</${tag}>`;
}

Expand Down
21 changes: 10 additions & 11 deletions src/editor/base/ranges/types/addition_range.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CM_All_Brackets, SuggestionType } from '../definitions';
import { CriticMarkupRange } from '../base_range';
import {PreviewMode} from "../../../../types";

export class AdditionRange extends CriticMarkupRange {
constructor(from: number, to: number, text: string, metadata?: number) {
Expand All @@ -14,23 +15,21 @@ export class AdditionRange extends CriticMarkupRange {
return '';
}

postprocess(unwrap: boolean = true, livepreview_mode: number = 0, tag: string = "div", left: boolean | null = null, text?: string) {
postprocess(unwrap: boolean = true, previewMode: PreviewMode = PreviewMode.ALL, tag: keyof HTMLElementTagNameMap = "div", left: boolean | null = null, text?: string) {
let str = text ?? this.text;
if (!text && unwrap) {
// Range is larger than what is actually given (no end bracket found within text)
if (this.to >= str.length && !str.endsWith(CM_All_Brackets[this.type].at(-1)!))
str = this.unwrap_bracket(true);
/*else if (this.from === 0 && !str.startsWith(CM_All_Brackets[this.type][0]))
str = this.unwrap_bracket(str, false);*/
else
str = this.unwrap();
}
if (!livepreview_mode)
str = `<${tag} class='criticmarkup-preview criticmarkup-addition'>${str}</${tag}>`;
else if (livepreview_mode === 1)
str = `<${tag} class='criticmarkup-preview'>${str}</${tag}>`;
else
str = `<${tag} class='criticmarkup-preview'/>`;
return str;

let cls = "criticmarkup-preview";
if (previewMode === PreviewMode.ALL)
cls += " criticmarkup-addition";
else if (previewMode === PreviewMode.REJECT)
str = "";

return `<${tag} class='${cls}'>${str}</${tag}>`;
}
}
45 changes: 44 additions & 1 deletion src/editor/base/ranges/types/comment_range.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { SuggestionType } from '../definitions';
import {CM_All_Brackets, SuggestionType} from '../definitions';
import { CriticMarkupRange } from '../base_range';
import {Component, MarkdownRenderer, setIcon} from "obsidian";
import {PreviewMode} from "../../../../types";

export class CommentRange extends CriticMarkupRange {
reply_depth = 0;
Expand Down Expand Up @@ -28,6 +30,47 @@ export class CommentRange extends CriticMarkupRange {
this.attached_comment = range;
}

postprocess(unwrap: boolean = true, previewMode: PreviewMode = PreviewMode.ALL, tag: keyof HTMLElementTagNameMap = 'div', left: boolean | null = null, text?: string) {
let str = text ?? this.text;
if (!text && unwrap) {
if (this.to >= str.length && !str.endsWith(CM_All_Brackets[this.type].at(-1)!))
str = this.unwrap_bracket(true);
else
str = this.unwrap();
}

const icon = document.createElement('span');
icon.classList.add('criticmarkup-comment-icon');
setIcon(icon, 'message-square');
let tooltip: HTMLElement | null = null;
let component = new Component();
icon.onmouseenter = () => {
if (tooltip) return;

tooltip = document.createElement('div');
tooltip.classList.add('criticmarkup-comment-tooltip');
MarkdownRenderer.render(app, str, tooltip, '', component);
component.load();
icon!.appendChild(tooltip);

// Set tooltip position
const icon_rect = icon!.getBoundingClientRect();
const tooltip_rect = tooltip.getBoundingClientRect();
tooltip.style.left = icon_rect.x - tooltip_rect.x + 12 + "px";
}

icon.onmouseleave = () => {
if (tooltip) {
component.unload();
icon!.removeChild(tooltip!);
tooltip = null;
}
}


return icon;
}

constructor(from: number, to: number, text: string, metadata?: number) {
super(from, to, SuggestionType.COMMENT, 'Comment', text, metadata);
}
Expand Down
25 changes: 12 additions & 13 deletions src/editor/base/ranges/types/deletion_range.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CM_All_Brackets, SuggestionType } from '../definitions';
import { CriticMarkupRange } from '../base_range';
import {CM_All_Brackets, SuggestionType} from '../definitions';
import {CriticMarkupRange} from '../base_range';
import {PreviewMode} from "../../../../types";

export class DeletionRange extends CriticMarkupRange {
constructor(from: number, to: number, text: string, metadata?: number) {
Expand All @@ -14,23 +15,21 @@ export class DeletionRange extends CriticMarkupRange {
return this.unwrap();
}

postprocess(unwrap: boolean = true, livepreview_mode: number = 0, tag: string = "div", left: boolean | null = null, text?: string) {
postprocess(unwrap: boolean = true, previewMode: PreviewMode = PreviewMode.ALL, tag: keyof HTMLElementTagNameMap = "div", left: boolean | null = null, text?: string) {
let str = text ?? this.text;
if (!text && unwrap) {
// Range is larger than what is actually given (no end bracket found within text)
if (this.to >= str.length && !str.endsWith(CM_All_Brackets[this.type].at(-1)!))
str = this.unwrap_bracket(true);
/*else if (this.from === 0 && !str.startsWith(CM_All_Brackets[this.type][0]))
str = this.unwrap_bracket(str, false);*/
else
str = this.unwrap();
}
if (!livepreview_mode)
str = `<${tag} class='criticmarkup-preview criticmarkup-deletion'>${str}</${tag}>`;
else if (livepreview_mode === 1)
str = `<${tag} class='criticmarkup-preview'/>`;
else
str = `<${tag} class='criticmarkup-preview'>${str}</${tag}>`;
return str;

let cls = "criticmarkup-preview";
if (previewMode === PreviewMode.ALL)
cls += " criticmarkup-deletion";
else if (previewMode === PreviewMode.ACCEPT)
str = "";

return `<${tag} class='${cls}'>${str}</${tag}>`;
}
}
41 changes: 24 additions & 17 deletions src/editor/base/ranges/types/substitution_range.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {CM_All_Brackets, SuggestionType} from '../definitions';
import { CriticMarkupRange } from '../base_range';
import {PreviewMode} from "../../../../types";

export class SubstitutionRange extends CriticMarkupRange {
constructor(from: number, public middle: number, to: number, text: string, metadata?: number) {
Expand Down Expand Up @@ -133,7 +134,7 @@ export class SubstitutionRange extends CriticMarkupRange {
return left ? this.from + 3 === this.middle : this.middle + 2 === this.to - 3;
}

postprocess(unwrap: boolean = true, livepreview_mode: number = 0, tag: string = "div", left: boolean | null = null, text?: string) {
postprocess(unwrap: boolean = true, previewMode: PreviewMode = PreviewMode.ALL, tag: keyof HTMLElementTagNameMap = "div", left: boolean | null = null, text?: string) {
let str = text ?? this.text;
let parts: string[] = [str];
if (!text && unwrap) {
Expand All @@ -146,25 +147,31 @@ export class SubstitutionRange extends CriticMarkupRange {
parts = this.unwrap_parts();
}


const cls = "criticmarkup-preview";
if (parts.length === 1) {
if (!livepreview_mode)
str = `<${tag} class='criticmarkup-preview criticmarkup-${left ? "deletion" : "addition"}'>${parts[0]}</${tag}>`;
else if (livepreview_mode === 1)
str = left ? "" : `<${tag} class='criticmarkup-preview'>${parts[0]}</${tag}>`;
else
str = left ? `<${tag} class='criticmarkup-preview'>${parts[0]}</${tag}>` : "";
parts[+(left as boolean)] = parts[0];
parts[+!left] = "";
}

str = "";
if (previewMode === PreviewMode.ALL) {
if (parts[0].length) {
str += `<${tag} class='${cls} criticmarkup-deletion'>${parts[0]}</${tag}>`;
}
if (parts[1].length) {
str += `<${tag} class='${cls} criticmarkup-addition'>${parts[1]}</${tag}>`;
}
} else {
if (!livepreview_mode) {
str = "";
if (parts[0].length)
str += `<${tag} class='criticmarkup-preview criticmarkup-deletion'>${parts[0]}</${tag}>`;
if (parts[1].length)
str += `<${tag} class='criticmarkup-preview criticmarkup-addition'>${parts[1]}</${tag}>`;
if (previewMode === PreviewMode.ACCEPT) {
if (parts[1].length) {
str += `<${tag} class='${cls}'>${parts[1]}</${tag}>`;
}
} else {
if (parts[0].length) {
str += `<${tag} class='${cls}'>${parts[0]}</${tag}>`;
}
}
else if (livepreview_mode === 1)
str = `<${tag} class='criticmarkup-preview'>${parts[1]}</${tag}>`;
else
str = `<${tag} class='criticmarkup-preview'>${parts[0]}</${tag}>`;
}
return str;
}
Expand Down
42 changes: 31 additions & 11 deletions src/editor/renderers/post-process/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,13 @@ export async function postProcess(el: HTMLElement, ctx: MarkdownPostProcessorCon


// FIXME: Unwrap is still the issue: find when to remove brackets correctly
el.innerHTML = range.postprocess(false, settings.default_preview_mode, 'div', left, element_contents);
const new_el = range.postprocess(false, settings.default_preview_mode, 'div', left, element_contents);
if (new_el instanceof HTMLElement) {
el.innerHTML = "";
el.appendChild(new_el);
} else {
el.innerHTML = new_el;
}

return;
}
Expand Down Expand Up @@ -106,7 +112,7 @@ export async function postProcess(el: HTMLElement, ctx: MarkdownPostProcessorCon
// No range syntax found in element, and no context was provided to determine whether the element is even part of a noe
if (!element_ranges.length && !ranges_in_range?.length) return;

let previous_start = 0, new_element = '';
let previous_start = 0, new_element: (HTMLElement | string)[] = []

// Case where range was opened in earlier block, and closed in current block
// Parser on element contents will not register the end bracket as a valid range, so we need to manually construct the range
Expand All @@ -124,8 +130,7 @@ export async function postProcess(el: HTMLElement, ctx: MarkdownPostProcessorCon
if (missing_range && left_outside && right_outside && missing_range.type === SuggestionType.SUBSTITUTION) {
const missing_range_middle = element_contents.indexOf(CM_All_Brackets[SuggestionType.SUBSTITUTION][1]);
const TempRange = new SubstitutionRange(-Infinity, missing_range_middle, Infinity, element_contents);
new_element += TempRange.postprocess(true, settings.default_preview_mode, 'span');
el.innerHTML = new_element;
el.innerHTML = TempRange.postprocess(true, settings.default_preview_mode, 'span');
return;
}

Expand All @@ -139,14 +144,14 @@ export async function postProcess(el: HTMLElement, ctx: MarkdownPostProcessorCon
TempRange = new SubstitutionRange(-Infinity, missing_range_middle === -1 ? -Infinity : missing_range_middle, missing_range_end, element_contents);
} else
TempRange = new RANGE_PROTOTYPE_MAPPER[missing_range.type](-Infinity, missing_range_end, element_contents);
new_element += TempRange.postprocess(true, settings.default_preview_mode, 'span');
new_element.push(TempRange.postprocess(true, settings.default_preview_mode, 'span'));
previous_start = TempRange.to;
}

// DEFAULT: Ranges get processed as normal (ranges which exists completely within the block)
for (const range of element_ranges) {
new_element += element_contents.slice(previous_start, range.from) +
range.postprocess(true, settings.default_preview_mode, 'span');
new_element.push(element_contents.slice(previous_start, range.from));
new_element.push(range.postprocess(true, settings.default_preview_mode, 'span'));
previous_start = range.to;
}

Expand All @@ -159,10 +164,25 @@ export async function postProcess(el: HTMLElement, ctx: MarkdownPostProcessorCon
TempRange = new SubstitutionRange(0, Infinity, Infinity, element_contents.slice(missing_range_start, -4));
else
TempRange = new RANGE_PROTOTYPE_MAPPER[missing_range.type](0, Infinity, element_contents.slice(missing_range_start, -4));
new_element += element_contents.slice(previous_start, missing_range_start) + TempRange.postprocess(true, settings.default_preview_mode, 'span');
new_element.push(element_contents.slice(previous_start, missing_range_start));
new_element.push(TempRange.postprocess(true, settings.default_preview_mode, 'span'));
previous_start = Infinity;
}
new_element += element_contents.slice(previous_start);

el.innerHTML = new_element;
new_element.push(element_contents.slice(previous_start));

el.innerHTML = "";
const to_reinsert: HTMLElement[] = [];
let str = "";
for (const child of new_element) {
if (typeof child === 'string')
str += child;
else {
str += `<placeholder></placeholder>`;
to_reinsert.push(child);
}
}
el.innerHTML = str;
el.querySelectorAll('placeholder').forEach((placeholder, i) => {
placeholder.replaceWith(to_reinsert[i]);
});
}

0 comments on commit 7bc5cb9

Please sign in to comment.