{"id":18067125,"url":"https://github.com/philterpaper/text-knuthplass","last_synced_at":"2025-06-13T05:04:25.062Z","repository":{"id":59756782,"uuid":"319773562","full_name":"PhilterPaper/Text-KnuthPlass","owner":"PhilterPaper","description":"Text::KnuthPlass paragraph shaping package for Perl","archived":false,"fork":false,"pushed_at":"2023-05-15T22:12:31.000Z","size":638,"stargazers_count":1,"open_issues_count":7,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-05T15:14:07.798Z","etag":null,"topics":["line-split","paragraph","paragraph-generation","perl","perl5","shaping"],"latest_commit_sha":null,"homepage":"https://www.catskilltech.com/FreeSW/product/Text%2DKnuthPlass/title/Text%3A%3AKnuthPlass/freeSW_full","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PhilterPaper.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-08T22:11:16.000Z","updated_at":"2023-07-30T21:16:56.000Z","dependencies_parsed_at":"2023-01-31T09:30:48.440Z","dependency_job_id":null,"html_url":"https://github.com/PhilterPaper/Text-KnuthPlass","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/PhilterPaper/Text-KnuthPlass","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilterPaper%2FText-KnuthPlass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilterPaper%2FText-KnuthPlass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilterPaper%2FText-KnuthPlass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilterPaper%2FText-KnuthPlass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PhilterPaper","download_url":"https://codeload.github.com/PhilterPaper/Text-KnuthPlass/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhilterPaper%2FText-KnuthPlass/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259584749,"owners_count":22880194,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["line-split","paragraph","paragraph-generation","perl","perl5","shaping"],"created_at":"2024-10-31T07:07:39.786Z","updated_at":"2025-06-13T05:04:25.022Z","avatar_url":"https://github.com/PhilterPaper.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Text-KnuthPlass\n\nA line-splitting (paragraph shaping) library for Perl.\n\n## What is it?\n\nText::KnuthPlass uses the famed Knuth-Plass line-splitting algorithm (used in \n**TeX** and **LaTeX**) to break up a text string into a properly \"shaped\" \nparagraph. Certain rules are followed to not only efficiently pack the \nparagraph into a minimal number of lines, but also to minimize hyphenation, \nkeep line density fairly constant, and take other measures to ensure that the \noutput is typographically \"nice looking\". It works with both fixed-width fonts \nand with proportional (variable-width) fonts, where you supply the font library \nthat calculates word lengths (e.g., PDF::Builder's _advancewidth()_ method). \nText::KnuthPlass permits varying line lengths, to allow text to flow around \nother objects, such as illustrations. It also makes use of (by default) \nText::Hyphen, a library to indicate where words can be split (for hyphenation \npurposes).\n\nSee also this blog on [Paragraph Shaping](https://www.catskilltech.com/utils/show.php?link=paragraph-shaping) for a deeper dive into the subject.\n\n[Home Page](https://www.catskilltech.com/FreeSW/product/Text%2DKnuthPlass/title/Text%3A%3AKnuthPlass/freeSW_full), including Documentation and Examples.\n\n[![Open Issues](https://img.shields.io/github/issues/PhilterPaper/Text-KnuthPlass)](https://github.com/PhilterPaper/Text-KnuthPlass/issues)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://makeapullrequest.com)\n[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/PhilterPaper/Text-KnuthPlass/graphs/commit-activity)\n\n`Text::KnuthPlass` is a Perl and XS (C) implementation of the well-known \nKnuth-Plass TeX paragraph-shaping (a.k.a. line-breaking) algorithm, as created\nby Donald E. Knuth and Michael F. Plass in 1981.\n\nGiven a long string containing the text of a paragraph, this module decides\nwhere to split a line (possibly hyphenating a word in the process), while\nattempting to:\n\n* maintain text \"tightness\" within a reasonable, comfortably readable, range (neither jammed together nor excessively loose).\n* maintain fairly consistent text \"tightness\" (limited change from line to line).\n* minimize the amount of hyphenation overall (words split at a line end).\n\nWhat is a stated objective of Knuth-Plass but I **don't** think this implementation directly does:\n\n* minimize the number of lines resulting.\n* not have two or more hyphenated lines in a row.\n* not have entire words \"floating\" over the next line (particularly when not fully justified, e.g., \"ragged right\").\n* not hyphenate the paragraph's penultimate line.\n\nWhat it definitely **doesn't** do:\n\n* attempt to avoid widows and orphans. This is the job of the calling routine, as `Text::KnuthPlass` doesn't know how much of the paragraph fits on this page (or column) and how much has to be spilled to the next page or column. It simply splits up the entire paragraph, and leaves it to your code to render.\n* attempt to avoid hyphenating the last word of the last line of a _split_ paragraph on a page or column (as before, it doesn't know where you're going to be splitting the paragraph between columns or pages).\n* attempt to optimize over an entire _page_ (it handles one paragraph at a time).\n* avoid having the same word (or fragment) starting or ending two lines in a row (a \"stack\"). This is undesirable because it makes it easier to mistrack while reading, and accidentally skip up or down a line.\n* avoid near-vertical \"rivers\" of whitespace.\n* avoid a very short or single word last line (a \"cub\").\n\nIn spite of these limitations, the Knuth-Plass (\"TeX line splitting\") algorithm\nis still pretty much the gold standard for paragraph shaping.\n\nThe Knuth-Plass algorithm does this by defining \"boxes\", \"glue\", and\n\"penalties\" for the paragraph text, and fiddling with line break points to\nminimize the overall sum of demerits (a penalty value for various \"bad\ntypesetting\" gaffes). This can result in the \"breaking\" of one\nor more of the listed rules, if it results in an overall better scoring \n(\"better looking\") layout.\n\n`Text::KnuthPlass` handles word widths by either character count, or a\nuser-supplied width function (such as based on the current font and font\nsize). It can also handle varying-length lines, if your column is not a\nperfect rectangle (see examples).\n\n## Installation\n\n    perl Build.PL\n    ./Build\n    ./Build test\n    ./Build install\n\nNote that if the XS (C) code fails to build and install for some reason, or\nyou enjoy watching paint dry, you\ncan still run \"pure Perl\" code -- it's much slower, but will always run. In\nlib/Text/KnuthPlass.pm, look for the flag setting\n`use constant purePerl =\u003e 0;` and change it to a value of `1`.\n\n## Documentation\n\nAfter installation, documentation can be found via\n\n    perldoc Text::KnuthPlass\n\nor\n\n    pod2html lib/Text/KnuthPlass.pm \u003e KnuthPlass.html\n\n## Support\n\nBug tracking is via\n\n    \"https://github.com/PhilterPaper/Text-KnuthPlass/issues?q=is%3Aissue+sort%3Aupdated-desc+is%3Aopen\"\n\n(you will need a GitHub account to create a ticket, or contribute to a\ndiscussion, but anyone can read tickets.) The old RT ticket system is closed.\n\nDo NOT under ANY circumstances open a PR (Pull Request) to **report a _bug_**. \nIt is a waste of both _your_ and _our_ time and effort. A PR is an offering of \ncode that you think belongs **permanently** in the product. Instead, simply \nopen a regular ticket (_issue_) in GitHub, and attach a Perl (.pl) program \nillustrating the problem, if possible. \nIf you believe that you have a good program patch, and offer to share\nit as a PR, we may give the go-ahead. Unsolicited PRs may be closed without\nfurther action.\n\n## License\n\nThis product is licensed under the Perl license. You may redistribute under\nthe GPL license, if desired, but you will have to add a copy of that license\nto your distribution, per its terms.\n\n(c)copyright 2020-2023 by Phil M Perry;\nearlier copyrights held by Simon Cozens\n\n## History\n\nAround 2009, Bram Stein wrote a Javascript implementation of the Knuth-Plass\nparagraph fitting algorithm named `typeset` (not to be confused with the\nlanguage `typescript`, nor the publishing system `Typeset`). It may be found\non GitHub in `bramstein/typeset`, and does not appear to be maintained (last\nupdate 2017). In 2011, Simon Cozens ported `typeset` to Perl, and called it\n`Text::KnuthPlass`, maintaining it for only a short time. In 2020, Phil Perry\ntook over maintenance of this package.\n\n**Note**:  gitpan/Text-KnuthPlass (on GitHub) appears to be a Read-Only\narchive of Text::KnuthPlass from _before_ Perry took over maintenance. It is\nold, and thus not very useful. See PhilterPaper/Text-KnuthPlass for the latest\ncode.\n\nThere are many copies of the Knuth-Plass paper/thesis, as well as discussions\nand explanations of the algorithm, floating around on the Web, so I will leave\nit to you to find some examples. Just the keywords _Knuth_ and _Plass_ should\nget you there. Rather than my listing everything here, pay a \n[visit](https://www.catskilltech.com/utils/show.php?link=paragraph-shaping#resources) \nto my discussion on the subject.\nThere is also a list of \n[criteria](https://www.catskilltech.com/utils/show.php?link=paragraph-shaping#criteria) \nof what makes good paragraph shaping.\n\nThere is also a refactored (still Javascript) version of\n`typeset`, intended for use as a library, in `frobnitzem/typeset`.\nFinally, there are a\nnumber of Knuth-Plass implementations in other languages, such as Python\n(`akuchling/texlib`) and typescript (`avery-laird/breaker`) that could be\nstudied. And of course, there is the original Knuth-Plass paper and the\nannotated listing in _TeX: The Program_. It's just a matter of finding the\ntime to go through all these sources and extend `Text::KnuthPlass` in\nvarious ways.\n\n## An Example\n\nFind an example of using Text::KnuthPlass in `examples/PDF/Flatland.pl`,\nderived from the example in _typeset_. It\nassumes that Text::Hyphen and PDF::Builder are installed. You can easily\nsubstitute PDF::API2 and change the PDF::Builder references in the code. You\ncan change many settings, such as the font, font size, indentation amount,\nleading, line length (in Points), and whether output is flush right or ragged\nright. The output file is `Flatland.pdf`.\n\nThere are more examples, including `KP.pl` and `Triangle.pl`, both giving some\nusage examples to get various effects, for a variety of input texts. Both PDF\nand text file outputs are produced.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphilterpaper%2Ftext-knuthplass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphilterpaper%2Ftext-knuthplass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphilterpaper%2Ftext-knuthplass/lists"}