Install
openclaw skills install @monikazapisekstudio/microtypographyPolish body text before publishing — Polish or English — by fixing hanging single-letter conjunctions/prepositions, adding orphan guards, flagging widow risks, and handling ragged-edge risks without rewriting copy.
openclaw skills install @monikazapisekstudio/microtypographyClean up a block of text at the sentence/paragraph level so it reads well when typeset — no single-letter words stranded at line end, no single-word "orphan" lines left dangling, no unreported widow risk at a column/page break, and no unmanaged ragged-edge risk.
Insert a non-breaking space between a single-letter (or otherwise "small") conjunction/preposition and the word that follows it, so it can never be the last character on a line.
Polish — single-letter words that must never end a line: i, a, o, u, w, z, k (and their capitalized sentence-start forms). Also treat short two-letter forms as strong candidates when local style guides require it: by, że, aż, iż, ze, we, do, na, od, po, ku — apply these only if the project's style guide asks for it; the single-letter rule is non-negotiable, the two-letter rule is a style choice.
English — single-letter words: a, I. English typesetting is generally more lenient than Polish (no hard rule against "a" or "I" ending a line), so treat this as optional polish, not a hard fix, unless the user asks for strict typesetting.
Mechanics per format:
(non-breaking space, renders as visually but blocks the line break). In markdown source this is the literal NBSP character, not an HTML entity, unless the target is HTML. between the word and what follows.<number> x <number>, e.g. 1920x1080, 3 x 4 m), replace the x/X/* with the proper multiplication sign ×. Don't touch a bare x that isn't between two numbers (variable names, "x-axis", "Grade x").100 PLN, 50 m, 16 px, 3 kg. Applies to abbreviated units and currency codes/symbols, not to spelled-out words ("100 dolarów" already reads fine without a hard rule).1920x1080 in a config file are not prose).Dashes — three different characters, three different spacing rules. Don't collapse them into one "make it fancy" transform:
— (parenthetical break, EN default per Bringhurst): no surrounding spaces — word—word. Replace a double hyphen -- used this way with a bare em dash, not a spaced one.– as a sentence-level parenthetical break (PL convention, and the Hunt-recommended EN alternative when a house style prefers a lighter mark than the em dash): surrounded by spaces — word – word — and those spaces should be NBSP if the dash sits near a line-wrap-risky position (short word before/after), otherwise a regular space is fine.– in a numeric/date range (10-15kg, 2020-2023): no spaces at all — 10–15 kg, 2020–2023. This is a different use of the same character from the sentence-dash case above; don't apply spacing rules meant for prose to a range. Add the NBSP-before-unit fix from Rule 1b where a unit follows (10–15 kg).-: never surrounded by spaces, in any context (compound words, prefixes). Don't touch hyphens that aren't standing in for an em/en dash — most hyphens in normal text are correct as-is.Quotation marks: detect the paragraph's language and convert straight quotes "..." to the typographically correct pair: Polish „...”, English “...”. Only convert quotes that wrap actual quoted/spoken text — leave straight quotes inside code, JSON, or attribute values untouched.
Both are opt-in-by-default in code-adjacent contexts (README snippets, inline code) — never touch quotes or dashes inside a code span, fenced block, or URL.
Design-tool context: if the dash/range sits inside a Figma text node (not markdown/HTML prose), the character choice above still applies, but kerning and per-range tracking around the dash are handled by text-typesetting Rule 6, not here — this skill decides which character and spacing, that skill decides how it renders.
Split by whether the text has hard line breaks or reflows.
Case A — hard-wrapped text (terminal output, poetry, plain-text captions, README manually wrapped to N columns): this is fixable directly only when the hard line breaks are part of body prose, not code or tables. Recompute the wrap with a best-fit / minimal-raggedness algorithm (minimize the variance of line-end positions across the paragraph — a lightweight Knuth-Plass-style pass, not naive greedy wrap, since greedy wrap maximizes rag). Apply the fix; note the target column width used in the change log.
Quantified rag threshold (applies to both cases, but especially narrow containers — mobile, UI cards): measure the longest and shortest line in the paragraph. If (longest − shortest) / container_width > 20%, the rag is bad enough to act on, not just cosmetically uneven — this is the trigger point, not a vague "looks ragged" judgment call. Below 20%, leave it; natural word-length variation produces some rag and over-correcting flattens it artificially.
Case B — reflowing text (normal markdown/HTML rendered by a browser/CMS): the source doesn't control where lines actually break, so there's nothing to rewrap. Two things are still legitimate to do here, both non-destructive to wording:
­ in HTML, soft-hyphen char in markdown/plain text) on long, unbreakable words (long Polish compounds, CamelCase, long tokens) so if the renderer needs to break there, it hyphenates cleanly instead of overflowing or forcing an ugly gap. Insert at defensible syllable or morpheme boundaries only. If you cannot identify safe break points, do not guess; flag the word for manual review instead.hyphens: auto; and text-wrap: pretty; on body copy, text-wrap: balance; on headings. This is the correct fix location for rag in reflowing text — flag it as a suggested CSS change alongside the text output.Do not reword sentences to control line length in Case B — that changes content, not typesetting, and violates the "don't alter wording" rule. If reflow genuinely looks bad only after rewording could fix it, offer it as an explicit opt-in suggestion the user must accept separately, never auto-applied.
A punctuation mark sitting at the very start or end of a line of text (an opening quote, dash, bullet, or parenthesis) reads as breaking the column's optical edge, even though it's technically inside the margin — the eye aligns to the letterforms, not the punctuation. Hanging punctuation pushes that mark slightly outside the block so the letters line up cleanly.
hanging-punctuation: first last; on the paragraph/block — this is the correct, native fix and needs no text-level change. Report it as a suggestion alongside other CSS recommendations (Rule 3 Case B), don't silently add it to a stylesheet.text-typesetting's job — it has the paragraph-indent / separate-container tools to pull the mark outside the block. This skill only flags that a heading opens with hanging-punctuation-eligible characters („, ", «, dashes, parentheses); it doesn't compute the indent value itself.hanging-punctuation: first last; for reflowing HTML/CSS output; flag (don't compute) hanging-punctuation-eligible display headings for Figma contexts.i, a, o, u, w, z, k) ends a line — verify by checking each occurrence got an NBSP, not just a regex pass.a/I handled per requested strictness (default: leave as-is unless asked for strict mode).x correctly converted to × only between two numbers, never touching variable/axis names.text-typesetting.microtype package documentation — the term of art microtypography: character/word-level spacing and hyphenation control, as distinct from macrotypography (grid, columns, page layout).hanging-punctuation property (first, last, force-end values) — native browser implementation of the same principle.text-typesetting — computes the actual Figma paragraph-indent/container workaround for hanging punctuation on display headings; this skill only detects and flags the condition.