Add Markdown to Post Format command and fix non-breaking space before period
- New markdownToLinkedIn() function converts Markdown to LinkedIn/Facebook-ready text: ## headings → Unicode bold, **bold** → Unicode bold, _italic_ → Unicode italic, - list items → em-dash bullets; blank lines and heading spacing handled correctly - New "Convert Markdown to Post Format" command registered in commands.ts - Fix space-before-period cleanup to also strip U+00A0 (non-breaking space), which Obsidian inserts after bold/formatted text (/ \./g → /[ \u00A0]\./g) - Update README to document the new command and updated function list Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ An [Obsidian](https://obsidian.md) plugin that transforms selected text into Uni
|
|||||||
- **Convert List Bullets to Em Dash** — prefixes every selected line with `— `, stripping any leading `* ` marker first
|
- **Convert List Bullets to Em Dash** — prefixes every selected line with `— `, stripping any leading `* ` marker first
|
||||||
- **Convert List to Numbered (Slash)** — numbers every selected line as `1/ item`, `2/ item`, ..., stripping any leading `* ` marker first
|
- **Convert List to Numbered (Slash)** — numbers every selected line as `1/ item`, `2/ item`, ..., stripping any leading `* ` marker first
|
||||||
- **Convert List to Numbered (Parentheses)** — numbers every selected line as `(1) item`, `(2) item`, ..., stripping any leading `* ` marker first
|
- **Convert List to Numbered (Parentheses)** — numbers every selected line as `(1) item`, `(2) item`, ..., stripping any leading `* ` marker first
|
||||||
|
- **Convert Markdown to Post Format** — converts a Markdown selection to LinkedIn/Facebook-ready text: `##` headings → bold, `**bold**` → Unicode bold, `_italic_` → Unicode italic, `- ` list items → `— ` em-dash bullets
|
||||||
- Non-mapped characters (punctuation, spaces, emoji, etc.) are passed through unchanged
|
- Non-mapped characters (punctuation, spaces, emoji, etc.) are passed through unchanged
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -27,6 +28,7 @@ An [Obsidian](https://obsidian.md) plugin that transforms selected text into Uni
|
|||||||
- **Convert List Bullets to Em Dash** — prefixes every line with `— ` (strips `* ` if present)
|
- **Convert List Bullets to Em Dash** — prefixes every line with `— ` (strips `* ` if present)
|
||||||
- **Convert List to Numbered (Slash)** — numbers every line as `1/ item`, `2/ item`, ... (strips `* ` if present)
|
- **Convert List to Numbered (Slash)** — numbers every line as `1/ item`, `2/ item`, ... (strips `* ` if present)
|
||||||
- **Convert List to Numbered (Parentheses)** — numbers every line as `(1) item`, `(2) item`, ... (strips `* ` if present)
|
- **Convert List to Numbered (Parentheses)** — numbers every line as `(1) item`, `(2) item`, ... (strips `* ` if present)
|
||||||
|
- **Convert Markdown to Post Format** — converts Markdown to LinkedIn/Facebook-ready text (headings, bold, italic, lists)
|
||||||
|
|
||||||
The selected text is replaced in place.
|
The selected text is replaced in place.
|
||||||
|
|
||||||
@@ -57,8 +59,8 @@ npm run lint # ESLint check
|
|||||||
| File | Purpose |
|
| File | Purpose |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `src/unicode-maps.ts` | Builds character lookup maps from Unicode code point ranges |
|
| `src/unicode-maps.ts` | Builds character lookup maps from Unicode code point ranges |
|
||||||
| `src/formatter.ts` | `transformText(text, style)`, `cleanText(text)`, and `bulletToEmdash(text)` — text transformation functions |
|
| `src/formatter.ts` | `transformText`, `cleanText`, `bulletToEmdash`, `bulletToArrow`, `numberedListSlash`, `numberedListParens`, `markdownToLinkedIn` — text transformation functions |
|
||||||
| `src/commands.ts` | Registers the eight editor commands with the Obsidian plugin API |
|
| `src/commands.ts` | Registers the nine editor commands with the Obsidian plugin API |
|
||||||
| `src/main.ts` | Plugin entry point — calls `registerCommands` on load |
|
| `src/main.ts` | Plugin entry point — calls `registerCommands` on load |
|
||||||
|
|
||||||
### Unicode blocks used
|
### Unicode blocks used
|
||||||
|
|||||||
+11
-1
@@ -1,5 +1,5 @@
|
|||||||
import { Plugin } from "obsidian";
|
import { Plugin } from "obsidian";
|
||||||
import { transformText, cleanText, bulletToEmdash, bulletToArrow, numberedListSlash, numberedListParens, FormatStyle } from "./formatter";
|
import { transformText, cleanText, bulletToEmdash, bulletToArrow, numberedListSlash, numberedListParens, markdownToLinkedIn, FormatStyle } from "./formatter";
|
||||||
|
|
||||||
function addFormatCommand(plugin: Plugin, style: FormatStyle, name: string) {
|
function addFormatCommand(plugin: Plugin, style: FormatStyle, name: string) {
|
||||||
plugin.addCommand({
|
plugin.addCommand({
|
||||||
@@ -68,4 +68,14 @@ export function registerCommands(plugin: Plugin): void {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
plugin.addCommand({
|
||||||
|
id: "unicode-formatter:markdown-to-linkedin",
|
||||||
|
name: "Convert Markdown to Post Format",
|
||||||
|
editorCallback: (editor) => {
|
||||||
|
const selection = editor.getSelection();
|
||||||
|
if (selection) {
|
||||||
|
editor.replaceSelection(markdownToLinkedIn(selection));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,3 +46,54 @@ export function numberedListParens(text: string): string {
|
|||||||
return `(${n}) ${content}`;
|
return `(${n}) ${content}`;
|
||||||
}).join("\n");
|
}).join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function applyInlineMarkdown(text: string): string {
|
||||||
|
return text.replace(/\*\*(.+?)\*\*|_(.+?)_/g, (_match, bold, italic) => {
|
||||||
|
if (bold !== undefined) return transformText(bold, "bold");
|
||||||
|
return transformText(italic, "italic");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function markdownToLinkedIn(text: string): string {
|
||||||
|
const lines = text.split("\n");
|
||||||
|
const output: string[] = [];
|
||||||
|
let pendingBlanks = 0;
|
||||||
|
let skipNextBlanks = false;
|
||||||
|
let inListContext = false;
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
if (line.trim() === "") {
|
||||||
|
if (!skipNextBlanks) pendingBlanks++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
skipNextBlanks = false;
|
||||||
|
|
||||||
|
if (line.startsWith("## ")) {
|
||||||
|
for (let i = 0; i < pendingBlanks; i++) output.push("");
|
||||||
|
pendingBlanks = 0;
|
||||||
|
inListContext = false;
|
||||||
|
const headingText = line.slice(3);
|
||||||
|
output.push(transformText(applyInlineMarkdown(headingText), "bold") + " ");
|
||||||
|
skipNextBlanks = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.startsWith("- ")) {
|
||||||
|
if (!inListContext) {
|
||||||
|
for (let i = 0; i < pendingBlanks; i++) output.push("");
|
||||||
|
}
|
||||||
|
pendingBlanks = 0;
|
||||||
|
output.push("— " + applyInlineMarkdown(line.slice(2)) + " ");
|
||||||
|
inListContext = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < pendingBlanks; i++) output.push("");
|
||||||
|
pendingBlanks = 0;
|
||||||
|
inListContext = false;
|
||||||
|
output.push(applyInlineMarkdown(line));
|
||||||
|
}
|
||||||
|
|
||||||
|
return output.join("\n").replace(/[ \u00A0]\./g, ".").trimEnd();
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user