Obtenga más información en pdf-lib.js.org
pdf-lib
se creó para abordar la falta de soporte sólido del ecosistema JavaScript para la manipulación de PDF (especialmente para la modificación de PDF).
Dos de las características distintivas de pdf-lib
son:
Hay otras buenas bibliotecas de PDF de JavaScript de código abierto disponibles. Sin embargo, la mayoría de ellos sólo pueden crear documentos, no pueden modificar los existentes. Y muchos de ellos sólo funcionan en entornos particulares.
Este ejemplo produce este PDF.
Pruebe la demostración de JSFiddle
import { PDFDocument , StandardFonts , rgb } from 'pdf-lib'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Embed the Times Roman font
const timesRomanFont = await pdfDoc . embedFont ( StandardFonts . TimesRoman )
// Add a blank page to the document
const page = pdfDoc . addPage ( )
// Get the width and height of the page
const { width , height } = page . getSize ( )
// Draw a string of text toward the top of the page
const fontSize = 30
page . drawText ( 'Creating PDFs in JavaScript is awesome!' , {
x : 50 ,
y : height - 4 * fontSize ,
size : fontSize ,
font : timesRomanFont ,
color : rgb ( 0 , 0.53 , 0.71 ) ,
} )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
Este ejemplo produce este PDF (cuando este PDF se utiliza para la variable existingPdfBytes
).
Pruebe la demostración de JSFiddle
import { degrees , PDFDocument , rgb , StandardFonts } from 'pdf-lib' ;
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const existingPdfBytes = ...
// Load a PDFDocument from the existing PDF bytes
const pdfDoc = await PDFDocument . load ( existingPdfBytes )
// Embed the Helvetica font
const helveticaFont = await pdfDoc . embedFont ( StandardFonts . Helvetica )
// Get the first page of the document
const pages = pdfDoc . getPages ( )
const firstPage = pages [ 0 ]
// Get the width and height of the first page
const { width , height } = firstPage . getSize ( )
// Draw a string of text diagonally across the first page
firstPage . drawText ( 'This text was added with JavaScript!' , {
x : 5 ,
y : height / 2 + 300 ,
size : 50 ,
font : helveticaFont ,
color : rgb ( 0.95 , 0.1 , 0.1 ) ,
rotate : degrees ( - 45 ) ,
} )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
Este ejemplo produce este PDF.
Pruebe la demostración de JSFiddle
Consulte también Crear y completar formularios.
import { PDFDocument } from 'pdf-lib'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Add a blank page to the document
const page = pdfDoc . addPage ( [ 550 , 750 ] )
// Get the form so we can add fields to it
const form = pdfDoc . getForm ( )
// Add the superhero text field and description
page . drawText ( 'Enter your favorite superhero:' , { x : 50 , y : 700 , size : 20 } )
const superheroField = form . createTextField ( 'favorite.superhero' )
superheroField . setText ( 'One Punch Man' )
superheroField . addToPage ( page , { x : 55 , y : 640 } )
// Add the rocket radio group, labels, and description
page . drawText ( 'Select your favorite rocket:' , { x : 50 , y : 600 , size : 20 } )
page . drawText ( 'Falcon Heavy' , { x : 120 , y : 560 , size : 18 } )
page . drawText ( 'Saturn IV' , { x : 120 , y : 500 , size : 18 } )
page . drawText ( 'Delta IV Heavy' , { x : 340 , y : 560 , size : 18 } )
page . drawText ( 'Space Launch System' , { x : 340 , y : 500 , size : 18 } )
const rocketField = form . createRadioGroup ( 'favorite.rocket' )
rocketField . addOptionToPage ( 'Falcon Heavy' , page , { x : 55 , y : 540 } )
rocketField . addOptionToPage ( 'Saturn IV' , page , { x : 55 , y : 480 } )
rocketField . addOptionToPage ( 'Delta IV Heavy' , page , { x : 275 , y : 540 } )
rocketField . addOptionToPage ( 'Space Launch System' , page , { x : 275 , y : 480 } )
rocketField . select ( 'Saturn IV' )
// Add the gundam check boxes, labels, and description
page . drawText ( 'Select your favorite gundams:' , { x : 50 , y : 440 , size : 20 } )
page . drawText ( 'Exia' , { x : 120 , y : 400 , size : 18 } )
page . drawText ( 'Kyrios' , { x : 120 , y : 340 , size : 18 } )
page . drawText ( 'Virtue' , { x : 340 , y : 400 , size : 18 } )
page . drawText ( 'Dynames' , { x : 340 , y : 340 , size : 18 } )
const exiaField = form . createCheckBox ( 'gundam.exia' )
const kyriosField = form . createCheckBox ( 'gundam.kyrios' )
const virtueField = form . createCheckBox ( 'gundam.virtue' )
const dynamesField = form . createCheckBox ( 'gundam.dynames' )
exiaField . addToPage ( page , { x : 55 , y : 380 } )
kyriosField . addToPage ( page , { x : 55 , y : 320 } )
virtueField . addToPage ( page , { x : 275 , y : 380 } )
dynamesField . addToPage ( page , { x : 275 , y : 320 } )
exiaField . check ( )
dynamesField . check ( )
// Add the planet dropdown and description
page . drawText ( 'Select your favorite planet*:' , { x : 50 , y : 280 , size : 20 } )
const planetsField = form . createDropdown ( 'favorite.planet' )
planetsField . addOptions ( [ 'Venus' , 'Earth' , 'Mars' , 'Pluto' ] )
planetsField . select ( 'Pluto' )
planetsField . addToPage ( page , { x : 55 , y : 220 } )
// Add the person option list and description
page . drawText ( 'Select your favorite person:' , { x : 50 , y : 180 , size : 18 } )
const personField = form . createOptionList ( 'favorite.person' )
personField . addOptions ( [
'Julius Caesar' ,
'Ada Lovelace' ,
'Cleopatra' ,
'Aaron Burr' ,
'Mark Antony' ,
] )
personField . select ( 'Ada Lovelace' )
personField . addToPage ( page , { x : 55 , y : 70 } )
// Just saying...
page . drawText ( `* Pluto should be a planet too!` , { x : 15 , y : 15 , size : 15 } )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
Este ejemplo produce este PDF (cuando este PDF se usa para la variable formPdfBytes
, esta imagen se usa para la variable marioImageBytes
y esta imagen se usa para la variable emblemImageBytes
).
Pruebe la demostración de JSFiddle
Consulte también Crear y completar formularios.
import { PDFDocument } from 'pdf-lib'
// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const formPdfBytes = ...
const marioImageBytes = ...
const emblemImageBytes = ...
// Load a PDF with form fields
const pdfDoc = await PDFDocument . load ( formPdfBytes )
// Embed the Mario and emblem images
const marioImage = await pdfDoc . embedPng ( marioImageBytes )
const emblemImage = await pdfDoc . embedPng ( emblemImageBytes )
// Get the form containing all the fields
const form = pdfDoc . getForm ( )
// Get all fields in the PDF by their names
const nameField = form . getTextField ( 'CharacterName 2' )
const ageField = form . getTextField ( 'Age' )
const heightField = form . getTextField ( 'Height' )
const weightField = form . getTextField ( 'Weight' )
const eyesField = form . getTextField ( 'Eyes' )
const skinField = form . getTextField ( 'Skin' )
const hairField = form . getTextField ( 'Hair' )
const alliesField = form . getTextField ( 'Allies' )
const factionField = form . getTextField ( 'FactionName' )
const backstoryField = form . getTextField ( 'Backstory' )
const traitsField = form . getTextField ( 'Feat+Traits' )
const treasureField = form . getTextField ( 'Treasure' )
const characterImageField = form . getButton ( 'CHARACTER IMAGE' )
const factionImageField = form . getTextField ( 'Faction Symbol Image' )
// Fill in the basic info fields
nameField . setText ( 'Mario' )
ageField . setText ( '24 years' )
heightField . setText ( `5' 1"` )
weightField . setText ( '196 lbs' )
eyesField . setText ( 'blue' )
skinField . setText ( 'white' )
hairField . setText ( 'brown' )
// Fill the character image field with our Mario image
characterImageField . setImage ( marioImage )
// Fill in the allies field
alliesField . setText (
[
`Allies:` ,
` • Princess Daisy` ,
` • Princess Peach` ,
` • Rosalina` ,
` • Geno` ,
` • Luigi` ,
` • Donkey Kong` ,
` • Yoshi` ,
` • Diddy Kong` ,
`` ,
`Organizations:` ,
` • Italian Plumbers Association` ,
] . join ( 'n' ) ,
)
// Fill in the faction name field
factionField . setText ( `Mario's Emblem` )
// Fill the faction image field with our emblem image
factionImageField . setImage ( emblemImage )
// Fill in the backstory field
backstoryField . setText (
`Mario is a fictional character in the Mario video game franchise, owned by Nintendo and created by Japanese video game designer Shigeru Miyamoto. Serving as the company's mascot and the eponymous protagonist of the series, Mario has appeared in over 200 video games since his creation. Depicted as a short, pudgy, Italian plumber who resides in the Mushroom Kingdom, his adventures generally center upon rescuing Princess Peach from the Koopa villain Bowser. His younger brother and sidekick is Luigi.` ,
)
// Fill in the traits field
traitsField . setText (
[
`Mario can use three basic three power-ups:` ,
` • the Super Mushroom, which causes Mario to grow larger` ,
` • the Fire Flower, which allows Mario to throw fireballs` ,
` • the Starman, which gives Mario temporary invincibility` ,
] . join ( 'n' ) ,
)
// Fill in the treasure field
treasureField . setText ( [ '• Gold coins' , '• Treasure chests' ] . join ( 'n' ) )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
Este ejemplo produce este PDF (cuando este PDF se utiliza para la variable formPdfBytes
).
Pruebe la demostración de JSFiddle
import { PDFDocument } from 'pdf-lib'
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const formPdfBytes = ...
// Load a PDF with form fields
const pdfDoc = await PDFDocument . load ( formPdfBytes )
// Get the form containing all the fields
const form = pdfDoc . getForm ( )
// Fill the form's fields
form . getTextField ( 'Text1' ) . setText ( 'Some Text' ) ;
form . getRadioGroup ( 'Group2' ) . select ( 'Choice1' ) ;
form . getRadioGroup ( 'Group3' ) . select ( 'Choice3' ) ;
form . getRadioGroup ( 'Group4' ) . select ( 'Choice1' ) ;
form . getCheckBox ( 'Check Box3' ) . check ( ) ;
form . getCheckBox ( 'Check Box4' ) . uncheck ( ) ;
form . getDropdown ( 'Dropdown7' ) . select ( 'Infinity' ) ;
form . getOptionList ( 'List Box6' ) . select ( 'Honda' ) ;
// Flatten the form's fields
form . flatten ( ) ;
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
Este ejemplo produce este PDF (cuando este PDF se usa para la variable firstDonorPdfBytes
y este PDF se usa para la variable secondDonorPdfBytes
).
Pruebe la demostración de JSFiddle
import { PDFDocument } from 'pdf-lib'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const firstDonorPdfBytes = ...
const secondDonorPdfBytes = ...
// Load a PDFDocument from each of the existing PDFs
const firstDonorPdfDoc = await PDFDocument . load ( firstDonorPdfBytes )
const secondDonorPdfDoc = await PDFDocument . load ( secondDonorPdfBytes )
// Copy the 1st page from the first donor document, and
// the 743rd page from the second donor document
const [ firstDonorPage ] = await pdfDoc . copyPages ( firstDonorPdfDoc , [ 0 ] )
const [ secondDonorPage ] = await pdfDoc . copyPages ( secondDonorPdfDoc , [ 742 ] )
// Add the first copied page
pdfDoc . addPage ( firstDonorPage )
// Insert the second copied page to index 0, so it will be the
// first page in `pdfDoc`
pdfDoc . insertPage ( 0 , secondDonorPage )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
Este ejemplo produce este PDF (cuando esta imagen se usa para la variable jpgImageBytes
y esta imagen se usa para la variable pngImageBytes
).
Pruebe la demostración de JSFiddle
import { PDFDocument } from 'pdf-lib'
// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const jpgImageBytes = ...
const pngImageBytes = ...
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Embed the JPG image bytes and PNG image bytes
const jpgImage = await pdfDoc . embedJpg ( jpgImageBytes )
const pngImage = await pdfDoc . embedPng ( pngImageBytes )
// Get the width/height of the JPG image scaled down to 25% of its original size
const jpgDims = jpgImage . scale ( 0.25 )
// Get the width/height of the PNG image scaled down to 50% of its original size
const pngDims = pngImage . scale ( 0.5 )
// Add a blank page to the document
const page = pdfDoc . addPage ( )
// Draw the JPG image in the center of the page
page . drawImage ( jpgImage , {
x : page . getWidth ( ) / 2 - jpgDims . width / 2 ,
y : page . getHeight ( ) / 2 - jpgDims . height / 2 ,
width : jpgDims . width ,
height : jpgDims . height ,
} )
// Draw the PNG image near the lower right corner of the JPG image
page . drawImage ( pngImage , {
x : page . getWidth ( ) / 2 - pngDims . width / 2 + 75 ,
y : page . getHeight ( ) / 2 - pngDims . height ,
width : pngDims . width ,
height : pngDims . height ,
} )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
Este ejemplo produce este PDF (cuando este PDF se usa para la variable americanFlagPdfBytes
y este PDF se usa para la variable usConstitutionPdfBytes
).
Pruebe la demostración de JSFiddle
import { PDFDocument } from 'pdf-lib'
// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const americanFlagPdfBytes = ...
const usConstitutionPdfBytes = ...
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Embed the American flag PDF bytes
const [ americanFlag ] = await pdfDoc . embedPdf ( americanFlagPdfBytes )
// Load the U.S. constitution PDF bytes
const usConstitutionPdf = await PDFDocument . load ( usConstitutionPdfBytes )
// Embed the second page of the constitution and clip the preamble
const preamble = await pdfDoc . embedPage ( usConstitutionPdf . getPages ( ) [ 1 ] , {
left : 55 ,
bottom : 485 ,
right : 300 ,
top : 575 ,
} )
// Get the width/height of the American flag PDF scaled down to 30% of
// its original size
const americanFlagDims = americanFlag . scale ( 0.3 )
// Get the width/height of the preamble clipping scaled up to 225% of
// its original size
const preambleDims = preamble . scale ( 2.25 )
// Add a blank page to the document
const page = pdfDoc . addPage ( )
// Draw the American flag image in the center top of the page
page . drawPage ( americanFlag , {
... americanFlagDims ,
x : page . getWidth ( ) / 2 - americanFlagDims . width / 2 ,
y : page . getHeight ( ) - americanFlagDims . height - 150 ,
} )
// Draw the preamble clipping in the center bottom of the page
page . drawPage ( preamble , {
... preambleDims ,
x : page . getWidth ( ) / 2 - preambleDims . width / 2 ,
y : page . getHeight ( ) / 2 - preambleDims . height / 2 - 50 ,
} )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
pdf-lib
se basa en un módulo hermano para admitir la incorporación de fuentes personalizadas: @pdf-lib/fontkit
. Debe agregar el módulo @pdf-lib/fontkit
a su proyecto y registrarlo usando pdfDoc.registerFontkit(...)
antes de incrustar fuentes personalizadas.
Consulte a continuación las instrucciones de instalación detalladas sobre cómo instalar
@pdf-lib/fontkit
como módulo UMD o NPM.
Este ejemplo produce este PDF (cuando esta fuente se usa para la variable fontBytes
).
Pruebe la demostración de JSFiddle
import { PDFDocument , rgb } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If you're running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const fontBytes = ...
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Register the `fontkit` instance
pdfDoc . registerFontkit ( fontkit )
// Embed our custom font in the document
const customFont = await pdfDoc . embedFont ( fontBytes )
// Add a blank page to the document
const page = pdfDoc . addPage ( )
// Create a string of text and measure its width and height in our custom font
const text = 'This is text in an embedded font!'
const textSize = 35
const textWidth = customFont . widthOfTextAtSize ( text , textSize )
const textHeight = customFont . heightAtSize ( textSize )
// Draw the string of text on the page
page . drawText ( text , {
x : 40 ,
y : 450 ,
size : textSize ,
font : customFont ,
color : rgb ( 0 , 0.53 , 0.71 ) ,
} )
// Draw a box around the string of text
page . drawRectangle ( {
x : 40 ,
y : 450 ,
width : textWidth ,
height : textHeight ,
borderColor : rgb ( 1 , 0 , 0 ) ,
borderWidth : 1.5 ,
} )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
Este ejemplo produce este PDF (cuando esta imagen se usa para la variable jpgAttachmentBytes
y este PDF se usa para la variable pdfAttachmentBytes
).
Pruebe la demostración de JSFiddle
import { PDFDocument } from 'pdf-lib'
// These should be Uint8Arrays or ArrayBuffers
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const jpgAttachmentBytes = ...
const pdfAttachmentBytes = ...
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Add the JPG attachment
await pdfDoc . attach ( jpgAttachmentBytes , 'cat_riding_unicorn.jpg' , {
mimeType : 'image/jpeg' ,
description : 'Cool cat riding a unicorn! ???️' ,
creationDate : new Date ( '2019/12/01' ) ,
modificationDate : new Date ( '2020/04/19' ) ,
} )
// Add the PDF attachment
await pdfDoc . attach ( pdfAttachmentBytes , 'us_constitution.pdf' , {
mimeType : 'application/pdf' ,
description : 'Constitution of the United States ???' ,
creationDate : new Date ( '1787/09/17' ) ,
modificationDate : new Date ( '1992/05/07' ) ,
} )
// Add a page with some text
const page = pdfDoc . addPage ( ) ;
page . drawText ( 'This PDF has two attachments' , { x : 135 , y : 415 } )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
Este ejemplo produce este PDF .
Pruebe la demostración de JSFiddle
import { PDFDocument , StandardFonts } from 'pdf-lib'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Embed the Times Roman font
const timesRomanFont = await pdfDoc . embedFont ( StandardFonts . TimesRoman )
// Add a page and draw some text on it
const page = pdfDoc . addPage ( [ 500 , 600 ] )
page . setFont ( timesRomanFont )
page . drawText ( 'The Life of an Egg' , { x : 60 , y : 500 , size : 50 } )
page . drawText ( 'An Epic Tale of Woe' , { x : 125 , y : 460 , size : 25 } )
// Set all available metadata fields on the PDFDocument. Note that these fields
// are visible in the "Document Properties" section of most PDF readers.
pdfDoc . setTitle ( '? The Life of an Egg ?' )
pdfDoc . setAuthor ( 'Humpty Dumpty' )
pdfDoc . setSubject ( ' An Epic Tale of Woe ' )
pdfDoc . setKeywords ( [ 'eggs' , 'wall' , 'fall' , 'king' , 'horses' , 'men' ] )
pdfDoc . setProducer ( 'PDF App 9000 ?' )
pdfDoc . setCreator ( 'pdf-lib (https://github.com/Hopding/pdf-lib)' )
pdfDoc . setCreationDate ( new Date ( '2018-06-24T01:58:37.228Z' ) )
pdfDoc . setModificationDate ( new Date ( '2019-12-21T07:00:11.000Z' ) )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
Pruebe la demostración de JSFiddle
import { PDFDocument } from 'pdf-lib'
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const existingPdfBytes = ...
// Load a PDFDocument without updating its existing metadata
const pdfDoc = await PDFDocument . load ( existingPdfBytes , {
updateMetadata : false
} )
// Print all available metadata fields
console . log ( 'Title:' , pdfDoc . getTitle ( ) )
console . log ( 'Author:' , pdfDoc . getAuthor ( ) )
console . log ( 'Subject:' , pdfDoc . getSubject ( ) )
console . log ( 'Creator:' , pdfDoc . getCreator ( ) )
console . log ( 'Keywords:' , pdfDoc . getKeywords ( ) )
console . log ( 'Producer:' , pdfDoc . getProducer ( ) )
console . log ( 'Creation Date:' , pdfDoc . getCreationDate ( ) )
console . log ( 'Modification Date:' , pdfDoc . getModificationDate ( ) )
Este script genera lo siguiente ( cuando este PDF se utiliza para la variable existingPdfBytes
):
Title: Microsoft Word - Basic Curriculum Vitae example.doc
Author: Administrator
Subject: undefined
Creator: PScript5.dll Version 5.2
Keywords: undefined
Producer: Acrobat Distiller 8.1.0 (Windows)
Creation Date: 2010-07-29T14:26:00.000Z
Modification Date: 2010-07-29T14:26:00.000Z
import {
PDFDocument ,
StandardFonts ,
NonFullScreenPageMode ,
ReadingDirection ,
PrintScaling ,
Duplex ,
PDFName ,
} from 'pdf-lib'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Embed the Times Roman font
const timesRomanFont = await pdfDoc . embedFont ( StandardFonts . TimesRoman )
// Add a page and draw some text on it
const page = pdfDoc . addPage ( [ 500 , 600 ] )
page . setFont ( timesRomanFont )
page . drawText ( 'The Life of an Egg' , { x : 60 , y : 500 , size : 50 } )
page . drawText ( 'An Epic Tale of Woe' , { x : 125 , y : 460 , size : 25 } )
// Set all available viewer preferences on the PDFDocument:
const viewerPrefs = pdfDoc . catalog . getOrCreateViewerPreferences ( )
viewerPrefs . setHideToolbar ( true )
viewerPrefs . setHideMenubar ( true )
viewerPrefs . setHideWindowUI ( true )
viewerPrefs . setFitWindow ( true )
viewerPrefs . setCenterWindow ( true )
viewerPrefs . setDisplayDocTitle ( true )
// Set the PageMode (otherwise setting NonFullScreenPageMode has no meaning)
pdfDoc . catalog . set ( PDFName . of ( 'PageMode' ) , PDFName . of ( 'FullScreen' ) )
// Set what happens when fullScreen is closed
viewerPrefs . setNonFullScreenPageMode ( NonFullScreenPageMode . UseOutlines )
viewerPrefs . setReadingDirection ( ReadingDirection . L2R )
viewerPrefs . setPrintScaling ( PrintScaling . None )
viewerPrefs . setDuplex ( Duplex . DuplexFlipLongEdge )
viewerPrefs . setPickTrayByPDFSize ( true )
// We can set the default print range to only the first page
viewerPrefs . setPrintPageRange ( { start : 0 , end : 0 } )
// Or we can supply noncontiguous ranges (e.g. pages 1, 3, and 5-7)
viewerPrefs . setPrintPageRange ( [
{ start : 0 , end : 0 } ,
{ start : 2 , end : 2 } ,
{ start : 4 , end : 6 } ,
] )
viewerPrefs . setNumCopies ( 2 )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
import { PDFDocument } from 'pdf-lib'
// This should be a Uint8Array or ArrayBuffer
// This data can be obtained in a number of different ways
// If your running in a Node environment, you could use fs.readFile()
// In the browser, you could make a fetch() call and use res.arrayBuffer()
const existingPdfBytes = ...
// Load a PDFDocument without updating its existing metadata
const pdfDoc = await PDFDocument . load ( existingPdfBytes )
const viewerPrefs = pdfDoc . catalog . getOrCreateViewerPreferences ( )
// Print all available viewer preference fields
console . log ( 'HideToolbar:' , viewerPrefs . getHideToolbar ( ) )
console . log ( 'HideMenubar:' , viewerPrefs . getHideMenubar ( ) )
console . log ( 'HideWindowUI:' , viewerPrefs . getHideWindowUI ( ) )
console . log ( 'FitWindow:' , viewerPrefs . getFitWindow ( ) )
console . log ( 'CenterWindow:' , viewerPrefs . getCenterWindow ( ) )
console . log ( 'DisplayDocTitle:' , viewerPrefs . getDisplayDocTitle ( ) )
console . log ( 'NonFullScreenPageMode:' , viewerPrefs . getNonFullScreenPageMode ( ) )
console . log ( 'ReadingDirection:' , viewerPrefs . getReadingDirection ( ) )
console . log ( 'PrintScaling:' , viewerPrefs . getPrintScaling ( ) )
console . log ( 'Duplex:' , viewerPrefs . getDuplex ( ) )
console . log ( 'PickTrayByPDFSize:' , viewerPrefs . getPickTrayByPDFSize ( ) )
console . log ( 'PrintPageRange:' , viewerPrefs . getPrintPageRange ( ) )
console . log ( 'NumCopies:' , viewerPrefs . getNumCopies ( ) )
Este script genera lo siguiente ( cuando este PDF se utiliza para la variable existingPdfBytes
):
HideToolbar: true
HideMenubar: true
HideWindowUI: false
FitWindow: true
CenterWindow: true
DisplayDocTitle: true
NonFullScreenPageMode: UseNone
ReadingDirection: R2L
PrintScaling: None
Duplex: DuplexFlipLongEdge
PickTrayByPDFSize: true
PrintPageRange: [ { start: 1, end: 1 }, { start: 3, end: 4 } ]
NumCopies: 2
Este ejemplo produce este PDF .
Pruebe la demostración de JSFiddle
import { PDFDocument , rgb } from 'pdf-lib'
// SVG path for a wavy line
const svgPath =
'M 0,20 L 100,160 Q 130,200 150,120 C 190,-40 200,200 300,150 L 400,90'
// Create a new PDFDocument
const pdfDoc = await PDFDocument . create ( )
// Add a blank page to the document
const page = pdfDoc . addPage ( )
page . moveTo ( 100 , page . getHeight ( ) - 5 )
// Draw the SVG path as a black line
page . moveDown ( 25 )
page . drawSvgPath ( svgPath )
// Draw the SVG path as a thick green line
page . moveDown ( 200 )
page . drawSvgPath ( svgPath , { borderColor : rgb ( 0 , 1 , 0 ) , borderWidth : 5 } )
// Draw the SVG path and fill it with red
page . moveDown ( 200 )
page . drawSvgPath ( svgPath , { color : rgb ( 1 , 0 , 0 ) } )
// Draw the SVG path at 50% of its original size
page . moveDown ( 200 )
page . drawSvgPath ( svgPath , { scale : 0.5 } )
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc . save ( )
// For example, `pdfBytes` can be:
// • Written to a file in Node
// • Downloaded from the browser
// • Rendered in an <iframe>
pdf-lib
es totalmente compatible con el nuevo y emocionante tiempo de ejecución de Deno! Todos los ejemplos de uso funcionan en Deno. Lo único que debe hacer es cambiar las importaciones de pdf-lib
y @pdf-lib/fontkit
para usar Skypack CDN, porque Deno requiere que se haga referencia a todos los módulos a través de URL.
Consulte también Cómo crear y modificar archivos PDF en Deno con pdf-lib
A continuación se muestra el ejemplo de creación de documento modificado para Deno:
import {
PDFDocument ,
StandardFonts ,
rgb ,
} from 'https://cdn.skypack.dev/pdf-lib@^1.11.1?dts' ;
const pdfDoc = await PDFDocument . create ( ) ;
const timesRomanFont = await pdfDoc . embedFont ( StandardFonts . TimesRoman ) ;
const page = pdfDoc . addPage ( ) ;
const { width , height } = page . getSize ( ) ;
const fontSize = 30 ;
page . drawText ( 'Creating PDFs in JavaScript is awesome!' , {
x : 50 ,
y : height - 4 * fontSize ,
size : fontSize ,
font : timesRomanFont ,
color : rgb ( 0 , 0.53 , 0.71 ) ,
} ) ;
const pdfBytes = await pdfDoc . save ( ) ;
await Deno . writeFile ( 'out.pdf' , pdfBytes ) ;
Si guarda este script como create-document.ts
, puede ejecutarlo usando Deno con el siguiente comando:
deno run --allow-write create-document.ts
El archivo out.pdf
resultante se verá como este PDF.
Aquí hay un ejemplo un poco más complicado que demuestra cómo incrustar una fuente y medir texto en Deno:
import {
degrees ,
PDFDocument ,
rgb ,
StandardFonts ,
} from 'https://cdn.skypack.dev/pdf-lib@^1.11.1?dts' ;
import fontkit from 'https://cdn.skypack.dev/@pdf-lib/fontkit@^1.0.0?dts' ;
const url = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf' ;
const fontBytes = await fetch ( url ) . then ( ( res ) => res . arrayBuffer ( ) ) ;
const pdfDoc = await PDFDocument . create ( ) ;
pdfDoc . registerFontkit ( fontkit ) ;
const customFont = await pdfDoc . embedFont ( fontBytes ) ;
const page = pdfDoc . addPage ( ) ;
const text = 'This is text in an embedded font!' ;
const textSize = 35 ;
const textWidth = customFont . widthOfTextAtSize ( text , textSize ) ;
const textHeight = customFont . heightAtSize ( textSize ) ;
page . drawText ( text , {
x : 40 ,
y : 450 ,
size : textSize ,
font : customFont ,
color : rgb ( 0 , 0.53 , 0.71 ) ,
} ) ;
page . drawRectangle ( {
x : 40 ,
y : 450 ,
width : textWidth ,
height : textHeight ,
borderColor : rgb ( 1 , 0 , 0 ) ,
borderWidth : 1.5 ,
} ) ;
const pdfBytes = await pdfDoc . save ( ) ;
await Deno . writeFile ( 'out.pdf' , pdfBytes ) ;
Si guarda este script como custom-font.ts
, puede ejecutarlo con el siguiente comando:
deno run --allow-write --allow-net custom-font.ts
El archivo out.pdf
resultante se verá como este PDF.
Los ejemplos de uso proporcionan un código breve y directo que demuestra las diferentes características de pdf-lib
. Puede encontrar ejemplos de trabajo completos en el directorio apps/
. Estas aplicaciones se utilizan para realizar pruebas manuales de pdf-lib
antes de cada lanzamiento (además de las pruebas automatizadas).
Actualmente hay cuatro aplicaciones:
node
: contiene pruebas para pdf-lib
en entornos Node. Estas pruebas son una referencia útil al intentar guardar/cargar archivos PDF, fuentes o imágenes con pdf-lib
desde el sistema de archivos. También le permiten abrir rápidamente sus archivos PDF en diferentes visores (Acrobat, Preview, Foxit, Chrome, Firefox, etc...) para garantizar la compatibilidad.web
: contiene pruebas para pdf-lib
en entornos de navegador. Estas pruebas son una referencia útil al intentar guardar/cargar archivos PDF, fuentes o imágenes con pdf-lib
en un entorno de navegador.rn
: contiene pruebas para pdf-lib
en entornos React Native. Estas pruebas son una referencia útil al intentar guardar/cargar archivos PDF, fuentes o imágenes con pdf-lib
en un entorno React Native.deno
: contiene pruebas para pdf-lib
en entornos Deno. Estas pruebas son una referencia útil al intentar guardar/cargar archivos PDF, fuentes o imágenes con pdf-lib
desde el sistema de archivos. Para instalar la última versión estable:
# With npm
npm install --save pdf-lib
# With yarn
yarn add pdf-lib
Esto supone que estás usando npm o Yarn como administrador de paquetes.
También puede descargar pdf-lib
como módulo UMD desde unpkg o jsDelivr. Las compilaciones de UMD se han compilado en ES5, por lo que deberían funcionar en cualquier navegador moderno. Las compilaciones UMD son útiles si no estás utilizando un administrador de paquetes o un paquete de módulos. Por ejemplo, puedes usarlos directamente en la etiqueta <script>
de una página HTML.
Las siguientes compilaciones están disponibles:
NOTA: si está utilizando los scripts CDN en producción, debe incluir un número de versión específico en la URL, por ejemplo:
- https://unpkg.com/[email protected]/dist/pdf-lib.min.js
- https://cdn.jsdelivr.net/npm/[email protected]/dist/pdf-lib.min.js
Cuando utilice una compilación UMD, tendrá acceso a una variable global window.PDFLib
. Esta variable contiene todas las clases y funciones exportadas por pdf-lib
. Por ejemplo:
// NPM module
import { PDFDocument , rgb } from 'pdf-lib' ;
// UMD module
var PDFDocument = PDFLib . PDFDocument ;
var rgb = PDFLib . rgb ;
pdf-lib
se basa en un módulo hermano para admitir la incorporación de fuentes personalizadas: @pdf-lib/fontkit
. Debe agregar el módulo @pdf-lib/fontkit
a su proyecto y registrarlo usando pdfDoc.registerFontkit(...)
antes de incrustar fuentes personalizadas (consulte el ejemplo de incrustación de fuentes). Este módulo no se incluye de forma predeterminada porque no todos los usuarios lo necesitan y aumenta el tamaño del paquete.
Instalar este módulo es fácil. Al igual que el propio pdf-lib
, @pdf-lib/fontkit
se puede instalar con npm
/ yarn
o como un módulo UMD.
# With npm
npm install --save @pdf-lib/fontkit
# With yarn
yarn add @pdf-lib/fontkit
Para registrar la instancia fontkit
:
import { PDFDocument } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'
const pdfDoc = await PDFDocument . create ( )
pdfDoc . registerFontkit ( fontkit )
Las siguientes compilaciones están disponibles:
NOTA: si está utilizando los scripts CDN en producción, debe incluir un número de versión específico en la URL, por ejemplo:
- https://unpkg.com/@pdf-lib/[email protected]/dist/fontkit.umd.min.js
- https://cdn.jsdelivr.net/npm/@pdf-lib/[email protected]/dist/fontkit.umd.min.js
Cuando utilice una compilación UMD, tendrá acceso a una variable global window.fontkit
. Para registrar la instancia fontkit
:
var pdfDoc = await PDFLib . PDFDocument . create ( )
pdfDoc . registerFontkit ( fontkit )
La documentación de la API está disponible en el sitio del proyecto en https://pdf-lib.js.org/docs/api/.
El repositorio del sitio del proyecto (y los archivos de documentación generados) se encuentra aquí: https://github.com/Hopding/pdf-lib-docs.
Cuando trabaje con archivos PDF, frecuentemente encontrará los términos "codificación de caracteres" y "fuente". Si tiene experiencia en desarrollo web, quizás se pregunte por qué son tan frecuentes. ¿No son simplemente detalles molestos de los que no deberías preocuparte? ¿No deberían las bibliotecas y lectores de PDF poder manejar todo esto como lo hacen los navegadores web? Lamentablemente, este no es el caso. La naturaleza del formato de archivo PDF hace que sea muy difícil evitar pensar en codificaciones de caracteres y fuentes cuando se trabaja con archivos PDF.
pdf-lib
hace todo lo posible para simplificarle las cosas. Pero no puede realizar magia. Esto significa que debes tener en cuenta lo siguiente:
import { PDFDocument , StandardFonts } from 'pdf-lib'
const pdfDoc = await PDFDocument . create ( )
const courierFont = await pdfDoc . embedFont ( StandardFonts . Courier )
const page = pdfDoc . addPage ( )
page . drawText ( 'Some boring latin text in the Courier font' , {
font : courierFont ,
} )
embedFont
. Cuando incrusta su propia fuente, puede utilizar cualquier carácter Unicode que admita. Esta capacidad le libera de las limitaciones impuestas por las fuentes estándar. La mayoría de los archivos PDF utilizan fuentes incrustadas. Puede incrustar y utilizar una fuente personalizada como esta (ver también): import { PDFDocument } from 'pdf-lib'
import fontkit from '@pdf-lib/fontkit'
const url = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf'
const fontBytes = await fetch ( url ) . then ( ( res ) => res . arrayBuffer ( ) )
const pdfDoc = await PDFDocument . create ( )
pdfDoc . registerFontkit ( fontkit )
const ubuntuFont = await pdfDoc . embedFont ( fontBytes )
const page = pdfDoc . addPage ( )
page . drawText ( 'Some fancy Unicode text in the ŪЬȕǹƚü font' , {
font : ubuntuFont ,
} )
Tenga en cuenta que se producirán errores de codificación si intenta utilizar un carácter con una fuente que no lo admita. Por ejemplo, Ω
no está en el juego de caracteres WinAnsi. Entonces, intentar dibujarlo en una página con la fuente Helvetica estándar arrojará el siguiente error:
Error: WinAnsi cannot encode "Ω" (0x03a9)
at Encoding.encodeUnicodeCodePoint
Incrustar una fuente en un documento PDF normalmente aumentará el tamaño del archivo. Puede reducir la cantidad de aumento del tamaño de un archivo subconjuntos de la fuente para que solo se incrusten los caracteres necesarios. Puede crear subconjuntos de una fuente configurando la opción subset
en true
. Por ejemplo:
const font = await pdfDoc . embedFont ( fontBytes , { subset : true } ) ;
Tenga en cuenta que el subconjunto no funciona para todas las fuentes. Consulte el n.° 207 (comentario) para obtener detalles adicionales.
pdf-lib
puede crear, completar y leer campos de formulario PDF. Se admiten los siguientes tipos de campos:
Consulte los ejemplos de uso de creación y llenado de formularios para obtener ejemplos de código. Las pruebas 1, 14, 15, 16 y 17 en los ejemplos completos contienen código de ejemplo funcional para la creación de formularios y el llenado de una variedad de entornos JS diferentes.
IMPORTANTE: La fuente predeterminada utilizada para mostrar texto en botones, menús desplegables, listas de opciones y campos de texto es la fuente Helvetica estándar. Esta fuente solo admite caracteres del alfabeto latino (consulte Fuentes y Unicode para obtener más detalles). Esto significa que si alguno de estos tipos de campos se crea o modifica para contener texto fuera del alfabeto latino (como suele ser el caso), deberá incrustar y utilizar una fuente personalizada para actualizar la apariencia del campo. De lo contrario, se generará un error (probablemente al guardar el PDFDocument
).
Puede utilizar una fuente incrustada al completar los campos del formulario de la siguiente manera:
import { PDFDocument } from 'pdf-lib' ;
import fontkit from '@pdf-lib/fontkit' ;
// Fetch the PDF with form fields
const formUrl = 'https://pdf-lib.js.org/assets/dod_character.pdf' ;
const formBytes = await fetch ( formUrl ) . then ( ( res ) => res . arrayBuffer ( ) ) ;
// Fetch the Ubuntu font
const fontUrl = 'https://pdf-lib.js.org/assets/ubuntu/Ubuntu-R.ttf' ;
const fontBytes = await fetch ( fontUrl ) . then ( ( res ) => res . arrayBuffer ( ) ) ;
// Load the PDF with form fields
const pdfDoc = await PDFDocument . load ( formBytes ) ;
// Embed the Ubuntu font
pdfDoc . registerFontkit ( fontkit ) ;
const ubuntuFont = await pdfDoc . embedFont ( fontBytes ) ;
// Get two text fields from the form
const form = pdfDoc . getForm ( ) ;
const nameField = form . getTextField ( 'CharacterName 2' ) ;
const ageField = form . getTextField ( 'Age' ) ;
// Fill the text fields with some fancy Unicode characters (outside
// the WinAnsi latin character set)
nameField . setText ( 'Ӎӑȑїõ' ) ;
ageField . setText ( '24 ŷȇȁŗš' ) ;
// **Key Step:** Update the field appearances with the Ubuntu font
form . updateFieldAppearances ( ubuntuFont ) ;
// Save the PDF with filled form fields
const pdfBytes = await pdfDoc . save ( ) ;
Se puede acceder a los campos de formulario existentes con los siguientes métodos de PDFForm
:
PDFForm.getButton
PDFForm.getCheckBox
PDFForm.getDropdown
PDFForm.getOptionList
PDFForm.getRadioGroup
PDFForm.getTextField
Se pueden crear nuevos campos de formulario con los siguientes métodos de PDFForm
:
PDFForm.createButton
PDFForm.createCheckBox
PDFForm.createDropdown
PDFForm.createOptionList
PDFForm.createRadioGroup
PDFForm.createTextField
A continuación se muestran algunos de los métodos más utilizados para leer y completar las subclases de PDFField
antes mencionadas:
PDFCheckBox.check
PDFCheckBox.uncheck
PDFCheckBox.isChecked
PDFDropdown.select
PDFDropdown.clear
PDFDropdown.getSelected
PDFDropdown.getOptions
PDFDropdown.addOptions
PDFOptionList.select
PDFOptionList.clear
PDFOptionList.getSelected
PDFOptionList.getOptions
PDFOptionList.addOptions
PDFRadioGroup.select
PDFRadioGroup.clear
PDFRadioGroup.getSelected
PDFRadioGroup.getOptions
PDFRadioGroup.addOptionToPage
PDFTextField.setText
PDFTextField.getText
PDFTextField.setMaxLength
PDFTextField.getMaxLength
PDFTextField.removeMaxLength
pdf-lib
puede extraer el contenido de los campos de texto (consulte PDFTextField.getText
), pero no puede extraer texto sin formato en una página fuera de un campo de formulario. Esta es una característica difícil de implementar, pero está dentro del alcance de esta biblioteca y puede agregarse a pdf-lib
en el futuro. Consulte los puntos 93, 137, 177, 329 y 380.pdf-lib
puede eliminar y editar el contenido de los campos de texto (consulte PDFTextField.setText
), pero no proporciona API para eliminar o editar texto en una página fuera de un campo de formulario. Esta también es una característica difícil de implementar, pero está dentro del alcance de pdf-lib
y puede agregarse en el futuro. Consulte los puntos 93, 137, 177, 329 y 380.pdf-lib
no admite el uso de HTML o CSS al agregar contenido a un PDF. De manera similar, pdf-lib
no puede incrustar contenido HTML/CSS en archivos PDF. Por más conveniente que sea una característica de este tipo, sería extremadamente difícil de implementar y está mucho más allá del alcance de esta biblioteca. Si esta capacidad es algo que necesita, considere usar Puppeteer. ¡Discusiones es el mejor lugar para chatear con nosotros, hacer preguntas y aprender más sobre pdf-lib!
Consulte también MAINTAINERSHIP.md#communication y MAINTAINERSHIP.md#discord.
Actualmente, pdf-lib
no admite documentos cifrados. No debes utilizar pdf-lib
con documentos cifrados. Sin embargo, esta es una característica que podría agregarse a pdf-lib
. ¡Cree un problema si esta función le resulta útil!
Cuando se pasa un documento cifrado a PDFDocument.load(...)
, se generará un error:
import { PDFDocument , EncryptedPDFError } from 'pdf-lib'
const encryptedPdfBytes = ...
// Assignment fails. Throws an `EncryptedPDFError`.
const pdfDoc = PDFDocument . load ( encryptedPdfBytes )
Este comportamiento predeterminado suele ser el que desea. Le permite detectar fácilmente si un documento determinado está cifrado y le impide intentar modificarlo. Sin embargo, si realmente desea cargar el documento, puede utilizar la opción { ignoreEncryption: true }
:
import { PDFDocument } from 'pdf-lib'
const encryptedPdfBytes = ...
// Assignment succeeds. Does not throw an error.
const pdfDoc = PDFDocument . load ( encryptedPdfBytes , { ignoreEncryption : true } )
Tenga en cuenta que utilizar esta opción no descifra el documento . Esto significa que cualquier modificación que intente realizar en el PDFDocument
devuelto puede fallar o tener resultados inesperados.
No deberías utilizar esta opción. Sólo existe por razones de compatibilidad con versiones anteriores.
¡Agradecemos las contribuciones de la comunidad de código abierto! Si está interesado en contribuir a pdf-lib
, eche un vistazo al archivo CONTRIBUTING.md. Contiene información que le ayudará a configurar y ejecutar pdf-lib
en su máquina. (¡Intentamos que esto sea lo más simple y rápido posible!)
Consulte MAINTAINERSHIP.md para obtener detalles sobre cómo se mantiene este repositorio y cómo utilizamos los problemas, las relaciones públicas y las discusiones.
pdfkit
es una biblioteca de generación de PDF para Node y el navegador. Esta biblioteca fue inmensamente útil como referencia y prueba de existencia al crear pdf-lib
. El código de pdfkit
para la incrustación de fuentes, la incrustación de PNG y la incrustación de JPG fue especialmente útil.pdf.js
es una biblioteca de renderizado de PDF para el navegador. Esta biblioteca fue útil como referencia al escribir el analizador de pdf-lib
. Parte del código para la decodificación de secuencias se transfirió directamente a TypeScript para su uso en pdf-lib
.pdfbox
es una biblioteca de generación y modificación de PDF escrita en Java. Esta biblioteca fue una referencia invaluable al implementar la creación de formularios y completar API para pdf-lib
.jspdf
es una biblioteca de generación de PDF para el navegador.pdfmake
es una biblioteca de generación de PDF para el navegador.hummus
es una biblioteca de generación y modificación de PDF para entornos Node. hummus
es un contenedor de nodo alrededor de una biblioteca C++, por lo que no funciona en muchos entornos JavaScript, como el navegador o React Native.react-native-pdf-lib
es una biblioteca de generación y modificación de PDF para entornos React Native. react-native-pdf-lib
es un contenedor para las bibliotecas de C++ y Java.pdfassembler
es una biblioteca de generación y modificación de PDF para Node y el navegador. Se requiere cierto conocimiento sobre la estructura lógica de los documentos PDF para su uso. Este repositorio solía contener un archivo llamado pdf_specification.pdf
en el directorio raíz. Esta era una copia de la especificación PDF 1.7, que Adobe pone a disposición de forma gratuita. El 30/08/2021, recibimos una queja de la DMCA que nos exigía que elimináramos el archivo de este repositorio. Simplemente eliminar el archivo mediante una nueva confirmación de master
fue insuficiente para satisfacer la queja. El archivo debía eliminarse por completo del historial de git del repositorio. Desafortunadamente, el archivo se agregó hace más de dos años, lo que significó que tuvimos que reescribir el historial de git del repositorio y forzar el envío a master
.
Eliminamos el archivo y reescribimos el historial del repositorio usando BFG Repo-Cleaner como se describe aquí. Para mayor transparencia, estos son los comandos exactos que ejecutamos:
$ git clone [email protected]:Hopding/pdf-lib.git
$ cd pdf-lib
$ rm pdf_specification.pdf
$ git commit -am 'Remove pdf_specification.pdf'
$ bfg --delete-files pdf_specification.pdf
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
$ git push --force
Si eres usuario de pdf-lib
, ¡no debería importarte! ¿Seguir usando pdf-lib
como de costumbre? !
Si es un desarrollador pdf-lib
(lo que significa que ha bifurcado pdf-lib
y/o tiene un PR abierto), esto le afecta. Si bifurcó o clonó el repositorio antes del 30/08/2021, entonces el historial de git de su bifurcación no está sincronizado con la rama master
de este repositorio. Desafortunadamente, esto probablemente le supondrá un dolor de cabeza. ¡Lo siento! No queríamos reescribir la historia, pero realmente no había otra alternativa.
Es importante tener en cuenta que el código fuente de pdf-lib no ha cambiado en absoluto. Es exactamente igual que antes de la reescritura del historial de git. El repositorio todavía tiene exactamente la misma cantidad de confirmaciones (e incluso el mismo contenido de confirmación, excepto la confirmación que agregó pdf_specification.pdf
). Lo que ha cambiado son los SHA de esas confirmaciones.
La forma más sencilla de abordar este hecho es:
Consulte esta respuesta de StackOverflow para obtener una explicación excelente y detallada de lo que implica una reescritura del historial de git.
MIT