obsidian#htmlToMarkdown TypeScript Examples
The following examples show how to use
obsidian#htmlToMarkdown.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Action.ts From obsidian-rss with GNU General Public License v3.0 | 5 votes |
static COPY = new Action(t("copy_to_clipboard"), "documents", ((_, item) : Promise<void> => {
return copy(htmlToMarkdown(item.content));
}));
Example #2
Source File: functions.ts From obsidian-rss with GNU General Public License v3.0 | 5 votes |
export function rssToMd(plugin: RssReaderPlugin, content: string): string {
let markdown = htmlToMarkdown(content);
//If dataview is installed
if ((plugin.app as any).plugins.plugins["dataview"]) {
//wrap dataview inline code
const {
inlineQueryPrefix,
inlineJsQueryPrefix
} = (plugin.app as any).plugins.plugins.dataview.api.settings as { [key: string]: string };
markdown = markdown.replace(RegExp(`\`${escapeRegExp(inlineQueryPrefix)}.*\``, 'g'), "<pre>$&</pre>");
markdown = markdown.replace(RegExp(`\`${escapeRegExp(inlineJsQueryPrefix)}.*\``, 'g'), "<pre>$&</pre>");
}
//If templater is installed
if ((plugin.app as any).plugins.plugins["templater-obsidian"]) {
//wrap templater commands
markdown = markdown.replace(/<%([\s\S]*?)%>/g, "```javascript\n$&\n```");
}
//wrap wallabag.xml codeblocks where there is a processor registered.
//as codeblockProcessors is not exposed publicly(and seems to be only existent after v.13) do a check first
//@ts-ignore
if(MarkdownPreviewRenderer.codeBlockPostProcessors) {
//@ts-ignore
const codeblockProcessors: string[] = Object.keys(MarkdownPreviewRenderer.codeBlockPostProcessors);
for (const codeblockProcessor of codeblockProcessors) {
const regex = RegExp("^```" + codeblockProcessor +"\[\\s\\S\]*?```$", "gm");
markdown = markdown.replace(regex, "<pre>$&</pre>");
}
}else {
//just remove wallabag.xml codeblocks instead
markdown = markdown.replace(/^```.*\n([\s\S]*?)```$/gm, "<pre>$&</pre>");
}
if(!plugin.settings.displayMedia) {
//remove any embeds, but keep alias
markdown = markdown.replace(/!?\[(.*)\]\(.+\)/gm, "$1");
}
return markdown;
}
Example #3
Source File: functions.ts From obsidian-rss with GNU General Public License v3.0 | 4 votes |
function applyTemplate(plugin: RssReaderPlugin, item: RssFeedItem, template: string, filename?: string): string {
let result = template.replace(/{{title}}/g, item.title);
result = result.replace(/{{link}}/g, item.link);
result = result.replace(/{{author}}/g, item.creator);
result = result.replace(/{{published}}/g, moment(item.pubDate).format(plugin.settings.dateFormat));
result = result.replace(/{{created}}/g, moment().format(plugin.settings.dateFormat));
result = result.replace(/{{date}}/g, moment().format(plugin.settings.dateFormat));
result = result.replace(/{{feed}}/g, item.feed);
result = result.replace(/{{folder}}/g, item.folder);
result = result.replace(/{{description}}/g, item.description);
result = result.replace(/{{media}}/g, item.enclosure);
result = result.replace(/({{published:).*(}})/g, function (k) {
const value = k.split(":")[1];
const format = value.substring(0, value.indexOf("}"));
return moment(item.pubDate).format(format);
});
result = result.replace(/({{created:).*(}})/g, function (k) {
const value = k.split(":")[1];
const format = value.substring(0, value.indexOf("}"));
return moment().format(format);
});
result = result.replace(/({{tags:).*(}})/g, function (k) {
const value = k.split(":")[1];
const separator = value.substring(0, value.indexOf("}"));
return item.tags.join(separator);
});
result = result.replace(/({{#tags:).*(}})/g, function (k) {
const value = k.split(":")[1];
const separator = value.substring(0, value.indexOf("}"));
return item.tags.map(i => '#' + i).join(separator);
});
result = result.replace(/{{tags}}/g, item.tags.join(", "));
result = result.replace(/{{#tags}}/g, item.tags.map(i => '#' + i).join(", "));
result = result.replace(/{{highlights}}/g, item.highlights.map(value => {
//remove wallabag.xml - from the start of a highlight
return "- " + rssToMd(plugin, removeFormatting(value).replace(/^(-+)/, ""))
}).join("\n"));
result = result.replace(/({{highlights:)[\s\S][^}]*(}})/g, function (k) {
const value = k.split(/(:[\s\S]?)/);
const tmp = value.slice(1).join("");
const template = tmp.substring(1, tmp.indexOf("}"));
return item.highlights.map(i => {
return template.replace(/%%highlight%%/g, rssToMd(plugin, removeFormatting(i)).replace(/^(-+)/, ""));
}).join("");
});
if (filename) {
result = result.replace(/{{filename}}/g, filename);
}
let content = rssToMd(plugin, item.content);
item.highlights.forEach(highlight => {
const mdHighlight = htmlToMarkdown(highlight);
content = content.replace(mdHighlight, "==" + mdHighlight + "==");
});
/*
fixes #48
replacing $ with $$$, because that is a special regex character:
https://developer.mozilla.org/en-US/docs/web/javascript/reference/global_objects/string/replace#specifying_a_string_as_a_parameter
solution taken from: https://stackoverflow.com/a/22612228/5589264
*/
content = content.replace(/\$/g, "$$$");
result = result.replace(/{{content}}/g, content);
return result;
}
Example #4
Source File: ItemModal.ts From obsidian-rss with GNU General Public License v3.0 | 4 votes |
async display(): Promise<void> {
this.modalEl.addClass("rss-modal");
const {contentEl} = this;
contentEl.empty();
//don't add any scrolling to modal content
contentEl.style.height = "100%";
contentEl.style.overflowY = "hidden";
const topButtons = contentEl.createDiv('topButtons');
let actions = Array.of(Action.CREATE_NOTE, Action.PASTE, Action.COPY, Action.OPEN);
if (this.save) {
this.readButton = new ButtonComponent(topButtons)
.setIcon(this.item.read ? 'eye-off' : 'eye')
.setTooltip(this.item.read ? t("mark_as_unread") : t("mark_as_read"))
.onClick(async () => {
await this.markAsRead();
});
this.readButton.buttonEl.setAttribute("tabindex", "-1");
this.readButton.buttonEl.addClass("rss-button");
this.favoriteButton = new ButtonComponent(topButtons)
.setIcon(this.item.favorite ? 'star-glyph' : 'star')
.setTooltip(this.item.favorite ? t("remove_from_favorites") : t("mark_as_favorite"))
.onClick(async () => {
await this.markAsFavorite();
});
this.favoriteButton.buttonEl.setAttribute("tabindex", "-1");
this.favoriteButton.buttonEl.addClass("rss-button");
actions = Array.of(Action.TAGS, ...actions);
}
actions.forEach((action) => {
const button = new ButtonComponent(topButtons)
.setIcon(action.icon)
.setTooltip(action.name)
.onClick(async () => {
await action.processor(this.plugin, this.item);
});
button.buttonEl.setAttribute("tabindex", "-1");
button.buttonEl.addClass("rss-button");
});
//@ts-ignore
if (this.app.plugins.plugins["obsidian-tts"]) {
const ttsButton = new ButtonComponent(topButtons)
.setIcon("headphones")
.setTooltip(t("read_article_tts"))
.onClick(async () => {
const content = htmlToMarkdown(this.item.content);
//@ts-ignore
await this.app.plugins.plugins["obsidian-tts"].ttsService.say(this.item.title, content, this.item.language);
});
ttsButton.buttonEl.addClass("rss-button");
}
const prevButton = new ButtonComponent(topButtons)
.setIcon("left-arrow-with-tail")
.setTooltip(t("previous"))
.onClick(() => {
this.previous();
});
prevButton.buttonEl.addClass("rss-button");
const nextButton = new ButtonComponent(topButtons)
.setIcon("right-arrow-with-tail")
.setTooltip(t("next"))
.onClick(() => {
this.next();
});
nextButton.buttonEl.addClass("rss-button");
const title = contentEl.createEl('h1', 'rss-title');
title.addClass("rss-selectable");
title.setText(this.item.title);
const subtitle = contentEl.createEl("h3", "rss-subtitle");
subtitle.addClass("rss-selectable");
if (this.item.creator) {
subtitle.appendText(this.item.creator);
}
if (this.item.pubDate) {
subtitle.appendText(" - " + window.moment(this.item.pubDate).format(this.plugin.settings.dateFormat));
}
const tagEl = contentEl.createSpan("tags");
this.item.tags.forEach((tag) => {
const tagA = tagEl.createEl("a");
tagA.setText(tag);
tagA.addClass("tag", "rss-tag");
});
const content = contentEl.createDiv('rss-content');
content.addClass("rss-scrollable-content", "rss-selectable");
if (this.item.enclosure && this.plugin.settings.displayMedia) {
if (this.item.enclosureType.toLowerCase().contains("audio")) {
const audio = content.createEl("audio", {attr: {controls: "controls"}});
audio.createEl("source", {attr: {src: this.item.enclosure, type: this.item.enclosureType}});
}
if (this.item.enclosureType.toLowerCase().contains("video")) {
const video = content.createEl("video", {attr: {controls: "controls", width: "100%", height: "100%"}});
video.createEl("source", {attr: {src: this.item.enclosure, type: this.item.enclosureType}});
}
//embedded yt player
if (this.item.enclosure && this.item.id.startsWith("yt:")) {
content.createEl("iframe", {
attr: {
type: "text/html",
src: "https://www.youtube.com/embed/" + this.item.enclosure,
width: "100%",
height: "100%",
allowFullscreen: "true"
}
});
}
}
if (this.item.content) {
//prepend empty yaml to fix rendering errors
const markdown = "---\n---" + rssToMd(this.plugin, this.item.content);
await MarkdownRenderer.renderMarkdown(markdown, content, "", this.plugin);
this.item.highlights.forEach(highlight => {
if (content.innerHTML.includes(highlight)) {
const newNode = contentEl.createEl("mark");
newNode.innerHTML = highlight;
content.innerHTML = content.innerHTML.replace(highlight, newNode.outerHTML);
newNode.remove();
} else {
console.log("Highlight not included");
console.log(highlight);
}
});
content.addEventListener('contextmenu', (event) => {
event.preventDefault();
const selection = document.getSelection();
const range = selection.getRangeAt(0);
const div = contentEl.createDiv();
const htmlContent = range.cloneContents();
const html = htmlContent.cloneNode(true);
div.appendChild(html);
const selected = div.innerHTML;
div.remove();
const menu = new Menu(this.app);
let previousHighlight: HTMLElement;
if (this.item.highlights.includes(range.startContainer.parentElement.innerHTML)) {
previousHighlight = range.startContainer.parentElement;
}
if (this.item.highlights.includes(range.startContainer.parentElement.parentElement.innerHTML)) {
previousHighlight = range.startContainer.parentElement.parentElement;
}
if(previousHighlight) {
menu.addItem(item => {
item
.setIcon("highlight-glyph")
.setTitle(t("highlight_remove"))
.onClick(async () => {
const replacement = contentEl.createSpan();
replacement.innerHTML = previousHighlight.innerHTML;
previousHighlight.replaceWith(replacement);
this.item.highlights.remove(previousHighlight.innerHTML);
const feedContents = this.plugin.settings.items;
await this.plugin.writeFeedContent(() => {
return feedContents;
});
});
});
}else if(!this.item.highlights.includes(selected) && selected.length > 0) {
menu.addItem(item => {
item
.setIcon("highlight-glyph")
.setTitle(t("highlight"))
.onClick(async () => {
const newNode = contentEl.createEl("mark");
newNode.innerHTML = selected;
range.deleteContents();
range.insertNode(newNode);
this.item.highlights.push(selected);
const feedContents = this.plugin.settings.items;
await this.plugin.writeFeedContent(() => {
return feedContents;
});
//cleaning up twice to remove nested elements
this.removeDanglingElements(contentEl);
this.removeDanglingElements(contentEl);
});
});
}
if(selected.length > 0) {
menu
.addItem(item => {
item
.setIcon("documents")
.setTitle(t("copy_to_clipboard"))
.onClick(async () => {
await copy(selection.toString());
});
});
//@ts-ignore
if (this.app.plugins.plugins["obsidian-tts"]) {
menu.addItem(item => {
item
.setIcon("headphones")
.setTitle(t("read_article_tts"))
.onClick(() => {
//@ts-ignore
const tts = this.app.plugins.plugins["obsidian-tts"].ttsService;
tts.say("", selection.toString());
});
});
}
}
menu.showAtMouseEvent(event);
});
}
}
Example #5
Source File: ItemModal.ts From obsidian-rss with GNU General Public License v3.0 | 4 votes |
constructor(plugin: RssReaderPlugin, item: RssFeedItem, items: RssFeedItem[], save = true) {
super(plugin.app);
this.plugin = plugin;
this.items = items;
this.item = item;
this.save = save;
if (this.save) {
this.item.read = true;
const feedContents = this.plugin.settings.items;
this.plugin.writeFeedContent(() => {
return feedContents;
});
if (!this.plugin.settings) {
return;
}
if (this.plugin.settings.hotkeys.read) {
this.scope.register([], this.plugin.settings.hotkeys.read, () => {
this.markAsRead();
});
}
if (this.plugin.settings.hotkeys.favorite) {
this.scope.register([], this.plugin.settings.hotkeys.favorite, () => {
this.markAsFavorite();
});
}
if (this.plugin.settings.hotkeys.tags) {
this.scope.register([], this.plugin.settings.hotkeys.tags, () => {
Action.TAGS.processor(this.plugin, this.item);
});
}
}
if (this.plugin.settings.hotkeys.create) {
this.scope.register([], this.plugin.settings.hotkeys.create, () => {
Action.CREATE_NOTE.processor(this.plugin, this.item);
});
}
if (this.plugin.settings.hotkeys.paste) {
this.scope.register([], this.plugin.settings.hotkeys.paste, () => {
Action.PASTE.processor(this.plugin, this.item);
});
}
if (this.plugin.settings.hotkeys.copy) {
this.scope.register([], this.plugin.settings.hotkeys.copy, () => {
Action.COPY.processor(this.plugin, this.item);
});
}
if (this.plugin.settings.hotkeys.open) {
this.scope.register([], this.plugin.settings.hotkeys.open, () => {
Action.OPEN.processor(this.plugin, this.item);
});
}
if (this.plugin.settings.hotkeys.next) {
this.scope.register([], this.plugin.settings.hotkeys.next, () => {
this.next();
});
}
if (this.plugin.settings.hotkeys.previous) {
this.scope.register([], this.plugin.settings.hotkeys.previous, () => {
this.previous();
});
}
//@ts-ignore
if (this.app.plugins.plugins["obsidian-tts"] && this.plugin.settings.hotkeys.tts) {
this.scope.register([], this.plugin.settings.hotkeys.tts, () => {
//@ts-ignore
const tts = this.app.plugins.plugins["obsidian-tts"].ttsService;
if (tts.isSpeaking()) {
if (tts.isPaused()) {
tts.resume();
} else {
tts.pause();
}
return;
}
const content = htmlToMarkdown(this.item.content);
tts.say(this.item.title, content, this.item.language);
});
}
}