Skip to content

Conversation

@konbraphat51
Copy link

@konbraphat51 konbraphat51 commented Sep 18, 2025

What?

This add supports reading and writing text markup annotation objects.

This adds:

  • basic infrastructure of reading/editing/adding annotation object
  • actual function PDFPage.addTextMarkupAnnotation() to add text markup annotation object

Reading

  • User can fetch the annotation objects from PDFPage.annotations()
    • This returns PDFAnnotation class instances

Editing

  • Able to change values of annotation objects using set methods of PDFAnnotation class

Adding

  • Able to add annotation object to the specified page by PDFPage.addTextMarkupAnnotation()

Why?

  • There was no interface for controling annotation object in this library
  • I guess many people wanted this feature

How?

  • implement conversion of annotation dictionary objects to PDFAnnotation class instance.
  • add a lot of get/set methods in PDFAnnotation

Testing?

  • Added new test code for this annotation feature.
    • test passed

New Dependencies?

N/A

Screenshots

image

This is created by this code:

//yarn node annotationsample-fixed.js
const fs = require('fs');

async function createAnnotatedPDF() {
  try {
    console.log('Creating PDF with annotation...');

    // Import pdf-lib
    const { PDFDocument, StandardFonts, rgb } = require('./cjs/index');
    const {
      AnnotationTypes,
    } = require('./cjs/core/annotation/AnnotationTypes');

    console.log('PDF-lib loaded successfully');

    // Create a new PDF document
    const pdfDoc = await PDFDocument.create();
    const page = pdfDoc.addPage([600, 400]);
    console.log('Page created');

    // Add some text first
    const helveticaFont = await pdfDoc.embedFont(StandardFonts.Helvetica);
    page.drawText('This text will be highlighted', {
      x: 50,
      y: 300,
      size: 12,
      font: helveticaFont,
      color: rgb(0, 0, 0),
    });
    console.log('Text added');

    // Try to add a highlight annotation
    try {
      page.addTextMarkupAnnotation({
        subtype: AnnotationTypes.Highlight,
        color: [1, 1, 0], // Yellow
        rect: {
          x: 50,
          y: 300,
          width: 150,
          height: 20,
        },
        contents: 'This is a highlight annotation',
        quadPoints: {
          leftbottomX: 50,
          leftbottomY: 300,
          lefttopX: 50,
          lefttopY: 320,
          righttopX: 200,
          righttopY: 320,
          rightbottomX: 200,
          rightbottomY: 300,
        },
      });
      console.log('Annotation added successfully');
    } catch (annotationError) {
      console.log('Could not add annotation:', annotationError.message);
      console.log('Proceeding without annotation...');
    }

    // Save the PDF
    const pdfBytes = await pdfDoc.save();
    fs.writeFileSync('annotationsample.pdf', pdfBytes);
    console.log('PDF created successfully: annotationsample.pdf');
  } catch (error) {
    console.error('Error creating PDF:', error);
  }
}

// Run the function
createAnnotatedPDF();

Suggested Reading?

Anything Else?

N/A

Checklist

  • I read CONTRIBUTING.md.
  • I read MAINTAINERSHIP.md#pull-requests.
  • I added/updated unit tests for my changes.
  • I added/updated integration tests for my changes.
  • I ran the integration tests.
  • I tested my changes in Node, Deno, and the browser.
  • I viewed documents produced with my changes in Adobe Acrobat, Foxit Reader, Firefox, and Chrome.
  • I added/updated doc comments for any new/modified public APIs.
  • My changes work for both new and existing PDF files.
  • I ran the linter on my changes.

because adding `annotationOperation`
@konbraphat51 konbraphat51 changed the title Add support for text markup annotation [WIP] Add support for text markup annotation Sep 18, 2025
@Sharcoux
Copy link
Collaborator

Changing eslint and the yarn.lock doesn't seem related to that PR. Can you split it into 2 PRs please?

@konbraphat51 konbraphat51 marked this pull request as ready for review September 28, 2025 21:45
@konbraphat51
Copy link
Author

Okey, this PR is ready for review!

@konbraphat51 konbraphat51 changed the title [WIP] Add support for text markup annotation Add support for text markup annotation Sep 29, 2025

const quadPointsArray = context.obj(
[
options.quadPoints.leftbottomX,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the PDF Spec, the order should be: leftBottom, rightBottom, rightTop, leftTop, meaning that you probably inverted the top part.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sorry for that. I fixed it

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, I remembered now why I did this.

https://stackoverflow.com/questions/9855814/pdf-spec-vs-acrobat-creation-quadpoints

It seems that Adobe implemented the last two corners horizontally inverted.

I tried the order in the spec and became like this hourglass shape:
image

/QuadPoints [69.9398 58.8418 96.5932 58.8418 96.5932 47.3526 69.9398 47.3526 ] 

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

↑forgot to mention: The image is rendered by Adobe Acrobat

/**
* The quad points that define the region(s) to be marked up.
*/
quadPoints: {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a very annoying data format. Please use Rect instead. Way easier to manipulate!

Copy link
Author

@konbraphat51 konbraphat51 Nov 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean Rect as src\utils\elements\Rectangle.ts?

Actually, qualPoints also covers trapezoids and hourglass shapes, not only rectangles. So I think that is not a good idea

my experiments (sorry it's in Japanese): https://qiita.com/konbraphat51/items/a7ddb30e5277d5e10a5a#%E8%9D%B6%E3%81%A4%E3%81%8C%E3%81%84

image image

@chr33s chr33s mentioned this pull request Nov 27, 2025
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants