Skip to content

API Reference

High-level API

Convert Markdown text to LinkedIn-compatible Unicode plain text.

Parameters:

Name Type Description Default
text str

The Markdown source string.

required
preserve_links bool

When True, link syntax ([text](url)) is left unchanged in the output instead of being reduced to display text.

False
monospace_code bool

When True (the default), inline code spans and fenced code blocks are rendered in Unicode Mathematical Monospace. When False, code is kept as plain text, with the backticks and fences stripped.

True

Returns:

Type Description
str

A plain-text string suitable for pasting into LinkedIn.

Source code in src/md2linkedin/_converter.py
def convert(
    text: str,
    *,
    preserve_links: bool = False,
    monospace_code: bool = True,
) -> str:
    """Convert Markdown text to LinkedIn-compatible Unicode plain text.

    Args:
        text: The Markdown source string.
        preserve_links: When ``True``, link syntax (``[text](url)``) is left
            unchanged in the output instead of being reduced to display text.
        monospace_code: When ``True`` (the default), inline code spans and
            fenced code blocks are rendered in Unicode Mathematical Monospace.
            When ``False``, code is kept as plain text, with the backticks
            and fences stripped.

    Returns:
        A plain-text string suitable for pasting into LinkedIn.

    """
    if not text.strip():
        return ""

    render_options = comrak.RenderOptions()
    render_options.compact_html = True
    # Raw HTML is passed through to the parser below, which reads the text out
    # of it. Nothing is ever rendered as HTML, so nothing can be injected.
    render_options.unsafe_ = True

    extensions = comrak.ExtensionOptions()
    extensions.strikethrough = True
    extensions.table = True
    extensions.autolink = True
    # ``==text==`` becomes ``<mark>``, which the renderer unwraps like any
    # other tag it has no style for, so the markers do not reach the output.
    extensions.highlight = True

    html = comrak.render_markdown(
        text,
        extension_options=extensions,
        render_options=render_options,
    )

    tree = LexborHTMLParser(html)
    renderer = Renderer(
        preserve_links=preserve_links,
        monospace_code=monospace_code,
    )
    out = renderer.render(tree.root)
    # An item that holds nothing but a nested list leaves its marker alone on
    # a line; no line is meant to end in blank space.
    return _TRAILING_SPACE.sub("", out).strip() + "\n"

Convert a Markdown file and write the result to a .txt file.

Parameters:

Name Type Description Default
input_path str | Path

Path to the Markdown source file.

required
output_path str | Path | None

Destination path for the converted output. Defaults to input_path with its last suffix replaced by .linkedin.txt, so notes.v2.md is written to notes.v2.linkedin.txt.

None
preserve_links bool

Passed through to :func:convert.

False
monospace_code bool

Passed through to :func:convert.

True

Returns:

Type Description
Path

The path of the written output file.

Raises:

Type Description
FileNotFoundError

If input_path does not exist.

Source code in src/md2linkedin/_converter.py
def convert_file(
    input_path: str | Path,
    output_path: str | Path | None = None,
    *,
    preserve_links: bool = False,
    monospace_code: bool = True,
) -> Path:
    """Convert a Markdown file and write the result to a ``.txt`` file.

    Args:
        input_path: Path to the Markdown source file.
        output_path: Destination path for the converted output. Defaults to
            *input_path* with its last suffix replaced by ``.linkedin.txt``,
            so ``notes.v2.md`` is written to ``notes.v2.linkedin.txt``.
        preserve_links: Passed through to :func:`convert`.
        monospace_code: Passed through to :func:`convert`.

    Returns:
        The path of the written output file.

    Raises:
        FileNotFoundError: If *input_path* does not exist.

    """
    input_path = Path(input_path)
    if not input_path.exists():
        msg = f"Input file not found: {input_path}"
        raise FileNotFoundError(msg)

    if output_path is None:
        output_path = input_path.with_suffix(".linkedin.txt")
    output_path = Path(output_path)

    md_text = input_path.read_text(encoding=_ENCODING)
    result = convert(
        md_text,
        preserve_links=preserve_links,
        monospace_code=monospace_code,
    )
    output_path.write_text(result, encoding=_ENCODING)
    return output_path

Unicode Mapping

Apply a Unicode sans-serif style to text.

A convenience dispatcher that routes to the appropriate mapping function based on the requested style. Useful when the style is determined dynamically at runtime.

Parameters:

Name Type Description Default
text str

The input string to convert.

required
style Literal['bold', 'italic', 'bold_italic']

One of "bold", "italic", or "bold_italic".

required

Returns:

Type Description
str

A new string with the requested Unicode style applied.

Raises:

Type Description
ValueError

If style is not one of the three accepted values.

Examples:

>>> apply_style("hello", "bold")
'𝗵𝗲𝗹𝗹𝗼'
>>> apply_style("hello", "italic")
'𝘩𝘦𝘭𝘭𝘰'
>>> apply_style("hello", "bold_italic")
'𝙝𝙚𝙡𝙡𝙤'
Source code in src/md2linkedin/_unicode.py
def apply_style(text: str, style: Literal["bold", "italic", "bold_italic"]) -> str:
    """Apply a Unicode sans-serif style to text.

    A convenience dispatcher that routes to the appropriate mapping function
    based on the requested style. Useful when the style is determined
    dynamically at runtime.

    Args:
        text: The input string to convert.
        style: One of ``"bold"``, ``"italic"``, or ``"bold_italic"``.

    Returns:
        A new string with the requested Unicode style applied.

    Raises:
        ValueError: If *style* is not one of the three accepted values.

    Examples:
        >>> apply_style("hello", "bold")
        '𝗵𝗲𝗹𝗹𝗼'

        >>> apply_style("hello", "italic")
        '𝘩𝘦𝘭𝘭𝘰'

        >>> apply_style("hello", "bold_italic")
        '𝙝𝙚𝙡𝙡𝙤'

    """
    if style == "bold":
        return to_sans_bold(text)
    if style == "italic":
        return to_sans_italic(text)
    if style == "bold_italic":
        return to_sans_bold_italic(text)
    msg = f"Unknown style {style!r}. Expected 'bold', 'italic', or 'bold_italic'."
    raise ValueError(msg)

Convert text to Unicode Mathematical Monospace.

ASCII uppercase letters, lowercase letters, and digits are mapped to their monospace counterparts. All other characters (spaces, punctuation, non-ASCII) pass through unchanged.

Parameters:

Name Type Description Default
text str

The input string to convert.

required

Returns:

Type Description
str

A new string with ASCII alphanumerics replaced by monospace

str

Unicode equivalents.

Examples:

>>> to_monospace("Hello, World! 123")
'𝙷𝚎𝚕𝚕𝚘, 𝚆𝚘𝚛𝚕𝚍! 𝟷𝟸𝟹'
>>> to_monospace("café")
'𝚌𝚊𝚏é'
>>> to_monospace("")
''
Source code in src/md2linkedin/_unicode.py
def to_monospace(text: str) -> str:
    """Convert text to Unicode Mathematical Monospace.

    ASCII uppercase letters, lowercase letters, and digits are mapped to
    their monospace counterparts. All other characters (spaces,
    punctuation, non-ASCII) pass through unchanged.

    Args:
        text: The input string to convert.

    Returns:
        A new string with ASCII alphanumerics replaced by monospace
        Unicode equivalents.

    Examples:
        >>> to_monospace("Hello, World! 123")
        '𝙷𝚎𝚕𝚕𝚘, 𝚆𝚘𝚛𝚕𝚍! 𝟷𝟸𝟹'

        >>> to_monospace("café")
        '𝚌𝚊𝚏é'

        >>> to_monospace("")
        ''

    """
    return text.translate(_MONOSPACE_TABLE)

Convert text to Unicode Mathematical Sans-Serif Bold.

ASCII uppercase letters, lowercase letters, and digits are mapped to their bold sans-serif counterparts. All other characters (spaces, punctuation, non-ASCII) pass through unchanged.

Parameters:

Name Type Description Default
text str

The input string to convert.

required

Returns:

Type Description
str

A new string with ASCII alphanumerics replaced by bold sans-serif

str

Unicode equivalents.

Examples:

>>> to_sans_bold("Hello, World! 123")
'𝗛𝗲𝗹𝗹𝗼, 𝗪𝗼𝗿𝗹𝗱! 𝟭𝟮𝟯'
>>> to_sans_bold("café")
'𝗰𝗮𝗳é'
>>> to_sans_bold("")
''
Source code in src/md2linkedin/_unicode.py
def to_sans_bold(text: str) -> str:
    """Convert text to Unicode Mathematical Sans-Serif Bold.

    ASCII uppercase letters, lowercase letters, and digits are mapped to
    their bold sans-serif counterparts. All other characters (spaces,
    punctuation, non-ASCII) pass through unchanged.

    Args:
        text: The input string to convert.

    Returns:
        A new string with ASCII alphanumerics replaced by bold sans-serif
        Unicode equivalents.

    Examples:
        >>> to_sans_bold("Hello, World! 123")
        '𝗛𝗲𝗹𝗹𝗼, 𝗪𝗼𝗿𝗹𝗱! 𝟭𝟮𝟯'

        >>> to_sans_bold("café")
        '𝗰𝗮𝗳é'

        >>> to_sans_bold("")
        ''

    """
    return text.translate(_SANS_BOLD_TABLE)

Convert text to Unicode Mathematical Sans-Serif Italic.

ASCII uppercase and lowercase letters are mapped to their italic sans-serif counterparts. Digits and all other characters pass through unchanged (there are no italic digit codepoints in this Unicode block).

Parameters:

Name Type Description Default
text str

The input string to convert.

required

Returns:

Type Description
str

A new string with ASCII letters replaced by italic sans-serif

str

Unicode equivalents.

Examples:

>>> to_sans_italic("Hello, World!")
'𝘏𝘦𝘭𝘭𝘰, 𝘞𝘰𝘳𝘭𝘥!'
>>> to_sans_italic("price: $42")
'𝘱𝘳𝘪𝘤𝘦: $42'
>>> to_sans_italic("")
''
Source code in src/md2linkedin/_unicode.py
def to_sans_italic(text: str) -> str:
    """Convert text to Unicode Mathematical Sans-Serif Italic.

    ASCII uppercase and lowercase letters are mapped to their italic
    sans-serif counterparts. Digits and all other characters pass through
    unchanged (there are no italic digit codepoints in this Unicode block).

    Args:
        text: The input string to convert.

    Returns:
        A new string with ASCII letters replaced by italic sans-serif
        Unicode equivalents.

    Examples:
        >>> to_sans_italic("Hello, World!")
        '𝘏𝘦𝘭𝘭𝘰, 𝘞𝘰𝘳𝘭𝘥!'

        >>> to_sans_italic("price: $42")
        '𝘱𝘳𝘪𝘤𝘦: $42'

        >>> to_sans_italic("")
        ''

    """
    return text.translate(_SANS_ITALIC_TABLE)

Convert text to Unicode Mathematical Sans-Serif Bold Italic.

ASCII uppercase and lowercase letters are mapped to their bold-italic sans-serif counterparts. Digits and all other characters pass through unchanged.

Parameters:

Name Type Description Default
text str

The input string to convert.

required

Returns:

Type Description
str

A new string with ASCII letters replaced by bold-italic sans-serif

str

Unicode equivalents.

Examples:

>>> to_sans_bold_italic("Hello, World!")
'𝙃𝙚𝙡𝙡𝙤, 𝙒𝙤𝙧𝙡𝙙!'
>>> to_sans_bold_italic("")
''
Source code in src/md2linkedin/_unicode.py
def to_sans_bold_italic(text: str) -> str:
    """Convert text to Unicode Mathematical Sans-Serif Bold Italic.

    ASCII uppercase and lowercase letters are mapped to their bold-italic
    sans-serif counterparts. Digits and all other characters pass through
    unchanged.

    Args:
        text: The input string to convert.

    Returns:
        A new string with ASCII letters replaced by bold-italic sans-serif
        Unicode equivalents.

    Examples:
        >>> to_sans_bold_italic("Hello, World!")
        '𝙃𝙚𝙡𝙡𝙤, 𝙒𝙤𝙧𝙡𝙙!'

        >>> to_sans_bold_italic("")
        ''

    """
    return text.translate(_SANS_BOLD_ITALIC_TABLE)