Skip to content

LinkedIn Format

LinkedIn posts use a lightweight formatting syntax that supports **bold**, *italic* / _italic_, bullet lists ( or - ), ordered lists, @[Name](urn:li:person:ID) structured mentions, bare @word mentions, and #hashtag tags. Paragraphs are separated by blank lines. RelationalText imports and exports this format using the com.linkedin.facet namespace.

Package: relational-text/linkedinNamespace: com.linkedin.facet

Functions

ts
import { from, to } from 'relational-text/registry'

from('linkedin', input: string): Document

Parse a LinkedIn post string into a Document.

ts
const doc = from('linkedin', 'Excited to share this update!\n\n**Key points:**\n• First insight\n• Second insight\n\n#innovation @[Jane Doe](urn:li:person:abc123)')

Handles:

  • Inline marks: **bold**, *italic*, _italic_
  • Structured mentions: @[Name](urn:li:...) — stored with personName and urn attributes
  • Bare mentions: @word — stored with personName set to the word and empty urn
  • Hashtags: #word — the # character is included in the text content; stored with tag attribute
  • Block types: paragraphs separated by blank lines, / - bullet lists, N. ordered lists

Consecutive non-blank lines that are not list items are accumulated and flushed as a single paragraph block (the lines are joined with \n). An empty input produces a single empty paragraph block.

to('linkedin', doc: Document): string

Render a Document to a LinkedIn post string.

ts
const post = to('linkedin', doc)

Automatically applies any registered lenses targeting com.linkedin.facet via lensGraph.autoTransform(). A Document parsed from another format will have its features mapped to LinkedIn equivalents before rendering.

Block rendering behaviour:

  • paragraph — rendered as a text line; consecutive paragraphs are separated by a blank line (\n)
  • list-item-text — rendered with for bullet lists or N. for ordered lists
  • bullet-list-marker, ordered-list-marker, list-item-marker — structural separator blocks that produce no output

Inline rendering behaviour:

  • bold**text**
  • italic_text_
  • mention@[personName](urn) if urn is present, else @personName
  • hashtag#tag (using the tag attr)

ensureLinkedInLexicon(): void

Register the LinkedIn lexicon and the LinkedIn → RelationalText lens with autoApply: true. Called automatically by from('linkedin', ...) and to('linkedin', ...) on first use. Safe to call multiple times — subsequent calls are no-ops.

Feature Mapping

Inline Marks

LinkedIn syntaxFeature nameType IDExpandRT equivalent
**text**boldcom.linkedin.facet#boldbothbold
*text* or _text_italiccom.linkedin.facet#italicbothitalic

Entities

LinkedIn syntaxFeature nameType IDAttrsRT equivalent
@[Name](urn)mentioncom.linkedin.facet#mentionpersonName, urnmention (personName renamed to handle)
@wordmentioncom.linkedin.facet#mentionpersonName, urn: ""mention
#wordhashtagcom.linkedin.facet#hashtagtaghashtag

Block Elements

Feature nameType IDRT equivalent
paragraphcom.linkedin.facet#paragraphparagraph
bullet-list-markercom.linkedin.facet#bullet-list-markerbullet-list-marker
ordered-list-markercom.linkedin.facet#ordered-list-markerordered-list-marker
list-item-markercom.linkedin.facet#list-item-markerlist-item-marker
list-item-textcom.linkedin.facet#list-item-textlist-item-text

Lens Integration

When ensureLinkedInLexicon() is called it registers a LinkedIn → RelationalText lens (com.linkedin.to.relationaltext.v1) with autoApply: true. The lens is marked invertible: false because mention renames the personName attr to handle.

Notable mappings:

  • mention personName attr is renamed to handle in the RT hub
  • hashtag maps to RT hashtag (identity name mapping)
  • All structural block names map directly
ts
import { from, to } from 'relational-text/registry'

// LinkedIn → Markdown
const doc = from('linkedin', '**Great news** for everyone!')
const md = to('markdown', doc)
// '**Great news** for everyone!\n\n'

// Markdown → LinkedIn
const mdDoc = from('markdown', '**Great news** for everyone!')
const li = to('linkedin', mdDoc)
// '**Great news** for everyone!'

Examples

Parse a post with structured mention and hashtag

ts
import { from } from 'relational-text/registry'

const post = 'Congrats to @[Jane Doe](urn:li:person:abc123) on the launch! #innovation'
const doc = from('linkedin', post)
const json = doc.toJSON()
// text:   "Congrats to Jane Doe on the launch! #innovation"
// facets: [mention over "Jane Doe" with personName="Jane Doe", urn="urn:li:person:abc123",
//          hashtag over "#innovation" with tag="innovation"]

Parse a post with a bare mention

ts
import { from } from 'relational-text/registry'

const doc = from('linkedin', 'Thanks @alice for the feedback!')
// mention feature over "alice" with personName="alice", urn=""

Parse a post with lists

ts
import { from } from 'relational-text/registry'

const post = 'Key takeaways:\n• Insight one\n• Insight two\n1. Step one\n2. Step two'
const doc = from('linkedin', post)
// paragraph block ("Key takeaways:"), two bullet items, two ordered items

Multi-line paragraph

ts
import { from } from 'relational-text/registry'

// Consecutive lines without blank separator are merged into one paragraph
const post = 'Line one\nLine two\n\nNew paragraph'
const doc = from('linkedin', post)
// paragraph("Line one\nLine two"), paragraph("New paragraph")

Export to LinkedIn format

ts
import { from, to } from 'relational-text/registry'

const doc = from('markdown', '**Bold** statement.\n\n- Item A\n- Item B\n')
const li = to('linkedin', doc)
// '**Bold** statement.\n• Item A\n• Item B\n'
// bullet items use • prefix in LinkedIn output

Notes

  • Structured mention format. LinkedIn's API encodes mentions as @[Display Name](urn:li:person:ID). The importer stores both personName and urn as top-level fields on the feature (not nested under attrs). The exporter emits @[personName](urn) when urn is present, or @personName for bare mentions.
  • Hashtag text includes #. The # character is included in the stored text content. The tag attribute holds the word without the #.
  • Paragraphs separated by blank lines. The exporter inserts a blank line (\n) between consecutive paragraph blocks. List items are not separated by blank lines.
  • Bullet list prefix is . The exporter uses the Unicode bullet character () for bullet list items regardless of the original input prefix ( or - are both accepted on import).
  • mention attr rename. The LinkedIn mention feature uses personName for the display name. The RT hub mention uses handle. The lens renames personNamehandle on the way to RT, making the lens non-invertible.
  • No strikethrough or code marks. The LinkedIn lexicon does not define strikethrough or inline code features.
  • Expand semantics. Bold and italic marks expand on both sides. Mention and hashtag are entities (non-expanding).
  • Implicit block type. The LinkedIn lexicon declares implicitBlockType: "paragraph".