Merge pull request #41 from eSlider/fix/put-txt-fixed-width
fix(docs): fixed-width txt as monospace code block
This commit is contained in:
@@ -101,11 +101,14 @@ func (t Tools) TXTToDOCX(txtPath, docxPath string) error {
|
||||
return t.MDToDOCX(tmpMD, docxPath)
|
||||
}
|
||||
|
||||
// TxtToMarkdown converts plain text to Markdown that preserves line breaks in DOCX output.
|
||||
// Single newlines become hard breaks; blank lines stay paragraph separators.
|
||||
// TxtToMarkdown converts plain text to Markdown for DOCX output.
|
||||
// Prose text: each line is a hard break. Fixed-width extracts (INE, pdftotext -layout):
|
||||
// wrapped in a fenced code block (monospace, columns preserved).
|
||||
func TxtToMarkdown(content string) string {
|
||||
content = strings.ReplaceAll(content, "\r\n", "\n")
|
||||
content = strings.ReplaceAll(content, "\r", "\n")
|
||||
content = normalizeTxtNewlines(content)
|
||||
if isFixedWidthTxt(content) {
|
||||
return "```\n" + content + "\n```\n"
|
||||
}
|
||||
var b strings.Builder
|
||||
for _, line := range strings.Split(content, "\n") {
|
||||
if strings.TrimSpace(line) == "" {
|
||||
@@ -118,6 +121,33 @@ func TxtToMarkdown(content string) string {
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func normalizeTxtNewlines(content string) string {
|
||||
content = strings.ReplaceAll(content, "\r\n", "\n")
|
||||
return strings.ReplaceAll(content, "\r", "\n")
|
||||
}
|
||||
|
||||
// isFixedWidthTxt detects pdftotext -layout style extracts (many indented/spaced columns).
|
||||
func isFixedWidthTxt(content string) bool {
|
||||
lines := strings.Split(content, "\n")
|
||||
if len(lines) < 8 {
|
||||
return false
|
||||
}
|
||||
indented, long := 0, 0
|
||||
for _, line := range lines {
|
||||
if strings.TrimSpace(line) == "" {
|
||||
continue
|
||||
}
|
||||
if len(line) >= 72 {
|
||||
long++
|
||||
}
|
||||
if len(line) > 0 && (line[0] == ' ' || line[0] == '\t') {
|
||||
indented++
|
||||
}
|
||||
}
|
||||
n := len(lines)
|
||||
return indented*100/n >= 20 || (long >= 5 && indented*100/n >= 10)
|
||||
}
|
||||
|
||||
// MDToDOCX writes a DOCX next to or at outPath from a Markdown file.
|
||||
func (t Tools) MDToDOCX(mdPath, docxPath string) error {
|
||||
if Ext(mdPath) != ".md" && Ext(mdPath) != ".markdown" {
|
||||
|
||||
@@ -34,6 +34,25 @@ func TestNeedsOCR_Image(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTxtToMarkdown_FixedWidthUsesCodeBlock(t *testing.T) {
|
||||
var lines []string
|
||||
for i := 0; i < 12; i++ {
|
||||
lines = append(lines, " column layout line "+strings.Repeat("x", 40))
|
||||
}
|
||||
in := strings.Join(lines, "\n")
|
||||
md := TxtToMarkdown(in)
|
||||
if !strings.HasPrefix(md, "```\n") || !strings.Contains(md, "```") {
|
||||
t.Fatalf("expected code block: %q", md[:min(80, len(md))])
|
||||
}
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestTxtToMarkdownPreservesLines(t *testing.T) {
|
||||
in := "line1\nline2\n\nline4"
|
||||
md := TxtToMarkdown(in)
|
||||
|
||||
Reference in New Issue
Block a user