Skip to content

Repository files navigation

So long, and thanks for a fish

pbtext • paste formatted posts in social networks

PBText keeps supported formatting when you paste a prepared post into LinkedIn, Facebook, YouTube, or X.

Write in your favorite text editor. Copy. Paste in LinkedIn, YouTube, Facebook, or X (Twitter). Keep the formatting. PBText handles the conversion automatically.

PBText works with bold, italic, underline, strikethrough, headings, paragraphs, lists, links, code, and common Markdown formatting. It also keeps supported line breaks and intentional blank lines.

PBText outputs plain text using Unicode characters, combining marks, and simple text frames so the visible formatting can be used in supported publishing fields.

Documentation

  • DEVELOPMENT.md — local development setup and unpacked-extension workflow.
  • INSTALL.md — installation instructions for users and developers.
  • PRIVACY.md — PBText privacy policy and clipboard-data handling.
  • PUBLISH.md — technical preparation sequence for building a publication-ready update.
  • RELEASE.md — release ZIP contents, packaging rules, and archive inspection.
  • SOLUTION.md — high-level architecture, runtime flow, module boundaries, and Mermaid diagrams.
  • TEST.md — development test cycle, automated checks, browser harnesses, Test Show, and live-platform verification.

Officially Supported Sites

PBText officially supports:

  • LinkedIn: linkedin.com, www.linkedin.com
  • X/Twitter: x.com, www.x.com, twitter.com, www.twitter.com
  • Facebook: facebook.com, www.facebook.com
  • YouTube: youtube.com, www.youtube.com

All behavior documented as supported in this README and TEST.md is part of the contract on each of these sites. If it fails in a supported site's editor, that is a PBText bug rather than an accepted site-specific limitation.

Test Show and the browser harnesses load the shared scripts directly. The production content script runs only on the supported publishing platforms listed above.

Current Behavior

PBText reads clipboard data and produces plain text for insertion.

  • Rich HTML containing a hyperlink takes priority so PBText can preserve and expose its URL.
  • Otherwise, detected Markdown in text/plain is treated as the source of truth and rich styling is discarded.
  • If no Markdown is detected, PBText parses clipboard HTML when available and falls back to plain text.
  • Output is inserted as text and line breaks, not as styled HTML.
  • Plain text that PBText cannot visibly transform is left to the site's normal paste handling.
  • When PBText makes at least one visible supported transformation, it appends the punchline once, after one empty line:
I made the post pretty with PBText. You can do the same.

The punchline is not added merely because PBText handled the paste or detected Markdown. Plain text that stays visually unchanged receives no punchline. For example, Hello stays Hello, while Hello **world** becomes Hello 𝐰𝐨𝐫𝐥𝐝 and receives the punchline. Supported list, heading, code, link, and inline-style transformations also count as visible changes.

Formatting

Supported inline formatting:

  • Bold: **text** or rich <strong>/<b>
  • Italic: *text* / _text_ or rich <em>/<i>
  • Underline: __text__ or rich underline
  • Strikethrough: ~~text~~ or rich strike/delete
  • Inline code: `npm run build`
  • Combinations of bold, italic, underline, and strikethrough

Supported block formatting:

  • Paragraphs and intentional blank lines
  • Single line breaks inside a paragraph
  • Rich HTML lists: unordered items use •; ordered items use 1., 2., 3. and always restart from 1.
  • HTML headings and Markdown ATX headings (# through ######), rendered in bold
  • Markdown checkboxes, bracket markers, and unordered-list lines
  • Rich HTML hyperlinks are expanded as link text (original URL); the URL is kept literal and is not Unicode-formatted
  • Fenced Markdown code blocks with or without a language label
  • Standalone --- lines rendered as twelve em dashes: ————————————

Example code block output:

⎡ 𝚓𝚜
⎢ 𝚌𝚘𝚗𝚜𝚝 𝚡 = 𝟷;
⎢ 𝚌𝚘𝚗𝚜𝚘𝚕𝚎.𝚕𝚘𝚐(𝚡);
⎣

Tabs inside code blocks are expanded to four spaces.

Bracket Markers And Markdown Lists

Default bracket-marker replacements:

Input Output
[ ] ▢ (U+25A2)
[x] ☑︎ (U+2611 U+FE0E)
[*], [star] 🌟
[f], [fire] 🔥
  • Markers are case-sensitive and work anywhere in ordinary text, but are not replaced inside inline code or fenced code blocks.
  • At the start of a list item, a configured marker replaces the complete - [marker] prefix and acts as the bullet: - [fire] Hot becomes 🔥 Hot.
  • Other lines beginning with - become — list items. Leading spaces and tabs are accepted and discarded, so nesting is flattened.
  • Unknown markers fall through to the ordinary-list rule: - [X] Task becomes — [X] Task.
  • Add one- or multi-character mappings in src/bracketMarkerConfig.js, then reload the extension and page.

Unicode Strategy

PBText uses Unicode characters rather than real CSS styles:

  • Latin letters and digits can be converted to mathematical bold, italic, bold italic, or monospace forms.
  • Decomposable Latin letters with diacritics are handled by styling the base letter and preserving combining marks.
  • Underline and strikethrough are rendered with combining marks.
  • Non-decomposable letters such as ß, ẞ, æ, œ, ø, ł, đ, ð, þ, ħ, and ı are preserved as-is.
  • Cyrillic text has a separate Unicode-rendering strategy. Bold Cyrillic runs are separated and surrounded with spaced bullets around each letter.
  • Italic Cyrillic runs use spaced hyphenation points between each letter.
  • For a fully styled Cyrillic word inside a line, an adjacent interword space is reinforced with two non-breaking spaces while retaining the original regular space. Each side is evaluated independently: line boundaries and attached punctuation receive nothing, while an existing space on the other side is still reinforced. Styled fragments inside a word do not receive extra boundary spacing.
  • Other unsupported Cyrillic styles preserve the original letters rather than substituting visually similar Latin characters.

Project Structure

  • src/lineBreaks.js: newline normalization and visible text layout helpers.
  • src/bracketMarkerConfig.js: one- or multi-character bracket-marker replacements.
  • src/lineTransforms.js: headings, line rules, lists, and bracket-marker transformations.
  • src/cyrillicStyleConfig.js: declarative separators and spacing for Cyrillic styles.
  • src/markdownParser.js: Markdown inline and fenced-code parsing.
  • src/htmlParser.js: clipboard HTML parsing, hyperlinks, effective styles, and indentation hints.
  • src/clipboardParser.js: clipboard source selection and plain-text parsing.
  • src/rules.js: Unicode formatting rules.
  • src/renderer.js: rendering internal blocks into final plain text.
  • src/pastePipeline.js: high-level formatting flow and punchline append.
  • src/textInsertion.js: shared insertion into editable targets through explicit generic, model-native, and model-literal modes.
  • src/content.js: runtime paste interception on supported domains.
  • tests/smoke.js: dependency-free pipeline smoke tests.
  • tests/project-structure.js: script-order contract checks for the production manifest and Test Show pages.

The parsers and renderer exchange a small internal model:

  • A segment contains text, boolean formatting marks, and an optional hyperlink address.
  • A block contains type, segments, and newlinesAfter.
  • List and code blocks add only the data they need, such as list or language.

The files are loaded as plain scripts, so their order in manifest.json and the Test Show pages is part of the runtime contract.

Local Checks

node tests/smoke.js
node tests/project-structure.js
for f in src/*.js tests/*.js; do node --check "$f" || exit 1; done
node -e "JSON.parse(require('fs').readFileSync('manifest.json','utf8')); console.log('manifest ok')"

Known Limits

  • Formatting is plain-text Unicode, not real rich text.
  • Punctuation generally has no separate mathematical monospace/bold/italic variant and is preserved.
  • Code block frames are text characters; their visual alignment depends on the target editor font.
  • The extension does not try to syntax-highlight code.
  • Hyperlink expansion requires rich HTML with an actual link; Markdown [text](URL) syntax is not parsed.
  • The current domain list is hardcoded in manifest.json.
  • Clipboard payloads larger than 1,000,000 characters are left to the site's normal paste handling.

About

Paste Formatted Text into LinkedIn, Facebook, Youtube, and X

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages