Documentation Index Fetch the complete documentation index at: https://mintlify.com/ragaeeb/kokokor/llms.txt
Use this file to discover all available pages before exploring further.
Your First Paragraph Reconstruction
This guide will walk you through using Kokokor to reconstruct paragraphs from OCR output.
Install Kokokor
If you haven’t already, install Kokokor using your preferred package manager: See the installation guide for other package managers.
Prepare Your OCR Data
Kokokor expects OCR observations with bounding box coordinates and text content. Here’s a typical structure: const ocrResult = {
dpi: { x: 300 , y: 300 },
page: { width: 2480 , height: 3508 },
observations: [
{
text: 'This is the first' ,
bbox: { x: 100 , y: 100 , width: 200 , height: 20 }
},
{
text: 'line of text.' ,
bbox: { x: 310 , y: 100 , width: 150 , height: 20 }
},
{
text: 'This is a new paragraph.' ,
bbox: { x: 100 , y: 150 , width: 300 , height: 20 }
},
],
};
The bbox object contains x, y (top-left corner), width, and height in pixels.
Import and Use reconstructParagraphs
Import the main function and process your OCR data: import { reconstructParagraphs } from 'kokokor' ;
const result = reconstructParagraphs ({
observations: ocrResult . observations ,
page: {
dpiX: ocrResult . dpi . x ,
dpiY: ocrResult . dpi . y ,
height: ocrResult . page . height ,
width: ocrResult . page . width ,
},
});
console . log ( result . text );
View the Results
The reconstructParagraphs function returns an object with:
text: The reconstructed text with proper paragraph breaks
textBlocks: Array of text blocks with metadata (centering, poetry, headings, etc.)
Expected output: This is the first line of text.
This is a new paragraph.
Each text block also includes metadata: result . textBlocks . forEach ( block => {
console . log ( block . text );
console . log ( 'Centered:' , block . isCentered );
console . log ( 'Poetry:' , block . isPoetic );
console . log ( 'Heading:' , block . isHeading );
console . log ( 'Footnote:' , block . isFootnote );
});
Complete Example
Here’s a complete working example you can copy and run:
import { reconstructParagraphs } from 'kokokor' ;
// Example OCR result from a document scanner
const ocrResult = {
dpi: { x: 300 , y: 300 },
page: { width: 2480 , height: 3508 },
observations: [
{ text: 'This is the first' , bbox: { x: 100 , y: 100 , width: 200 , height: 20 } },
{ text: 'line of text.' , bbox: { x: 310 , y: 100 , width: 150 , height: 20 } },
{ text: 'This is a new paragraph.' , bbox: { x: 100 , y: 150 , width: 300 , height: 20 } },
],
};
// Reconstruct paragraphs
const result = reconstructParagraphs ({
observations: ocrResult . observations ,
page: {
dpiX: ocrResult . dpi . x ,
dpiY: ocrResult . dpi . y ,
height: ocrResult . page . height ,
width: ocrResult . page . width ,
},
});
console . log ( result . text );
// Output:
// This is the first line of text.
// This is a new paragraph.
Understanding the Output
Text Property
The text property contains the fully reconstructed text with:
Lines merged within paragraphs
Double newlines between paragraphs
Poetry lines preserved individually
Footnotes separated from body text
Text Blocks Property
The textBlocks array provides structured access to each paragraph with metadata:
type TextBlock = {
text : string ;
bbox : BoundingBox ;
isCentered ?: boolean ; // Text is centered on the page
isPoetic ?: boolean ; // Detected as poetry (not merged into paragraphs)
isHeading ?: boolean ; // Detected as a heading
isFootnote ?: boolean ; // Detected as a footnote
};
Next Steps
Advanced Configuration Customize paragraph detection parameters for your specific use case
API Reference Explore the complete API documentation
Poetry Detection Learn how Kokokor identifies and preserves poetic content
RTL Text Support Working with Arabic, Hebrew, and other right-to-left languages
Common Use Cases
Working with Surya OCR
If you’re using the Surya OCR library, convert the output format:
import { reconstructParagraphs , mapMatrixToBoundingBox } from 'kokokor' ;
// Surya returns bounding boxes as [x1, y1, x2, y2]
const suryaResult = {
text_lines: [
{ bbox: [ 100 , 100 , 400 , 120 ], text: 'Text from Surya OCR' },
],
};
// Convert to Kokokor format
const observations = suryaResult . text_lines . map ( line => ({
text: line . text ,
bbox: mapMatrixToBoundingBox ( line . bbox as [ number , number , number , number ]),
}));
const result = reconstructParagraphs ({
observations ,
page: { dpiX: 300 , dpiY: 300 , width: 2480 , height: 3508 }
});
Processing RTL Text
For right-to-left languages like Arabic:
import { flipAndAlignObservations , reconstructParagraphs } from 'kokokor' ;
// Flip coordinates for RTL text
const flipped = flipAndAlignObservations (
observations ,
imageWidth ,
dpiX
);
const result = reconstructParagraphs ({
observations: flipped ,
page: { dpiX , dpiY , width: imageWidth , height: imageHeight }
});
Custom Paragraph Detection
Adjust the paragraph detection sensitivity:
const result = reconstructParagraphs (
{
observations ,
page: pageContext
},
{
verticalJumpFactor: 2 , // Higher = more sensitive to vertical gaps
widthTolerance: 0.85 // Lower = more sensitive to short lines
}
);
The default parameters work well for most documents. Only customize if you’re seeing incorrect paragraph breaks.