[{"data":1,"prerenderedAt":1368},["ShallowReactive",2],{"author-david-touzet":3,"author-articles-david-touzet":22,"authors":1052},{"id":4,"title":5,"body":6,"description":10,"extension":13,"meta":14,"name":15,"navigation":16,"path":17,"readingTime":18,"seo":19,"stem":20,"__hash__":21},"authors\u002Fauthors\u002Fdavid-touzet.md","Staff Engineer",{"type":7,"value":8,"toc":9},"minimark",[],{"title":10,"searchDepth":11,"depth":11,"links":12},"",2,[],"md",{},"David Touzet",true,"\u002Fauthors\u002Fdavid-touzet",1,{"title":5,"description":10},"authors\u002Fdavid-touzet","dHWwnQxb1Ubt-WwXWEODGEo9AFoq1cJUhfg3kdnYSBM",[23],{"id":24,"title":25,"author":26,"body":27,"date":1042,"description":1043,"extension":13,"lang":1044,"meta":1045,"navigation":16,"path":1046,"published":16,"readingTime":240,"seo":1047,"stem":1048,"tags":1049,"__hash__":1051},"articles\u002Farticles\u002F2022-04-28-recuperer-les-coordonnees-dans-un-fichier-pdf-avec-pdfjs-dist.md","Récupérer les coordonnées dans un fichier pdf avec pdfjs-dist","david-touzet",{"type":7,"value":28,"toc":1036},[29,34,38,41,51,54,57,62,75,86,110,113,133,136,141,145,148,151,248,251,327,330,948,951,976,984,987,992,1003,1013,1018,1032],[30,31,33],"h2",{"id":32},"contexte","Contexte",[35,36,37],"p",{},"Chez Indy on fait de la compta ",[35,39,40],{},"Presque chaque année, les documents changent (dans notre jargon on parle de millésime) et on doit\nmettre à jour notre générateur de document. Les documents sont mis à disposition par l'État et sont\ndes PDF sans zone de texte clairement définie.",[35,42,44,45],{"align":43},"center","\n  ",[46,47],"img",{"src":48,"alt":49,"style":50},"https:\u002F\u002Fmedia.giphy.com\u002Fmedia\u002FKDRv3QggAjyo\u002Fgiphy.gif","Gif","width:320px;max-width:100%;",[35,52,53],{},"Du coup nous prenons le pdf comme une image de fond et nous écrivons par dessus les bonnes données\nde chaque client. Il nous faut donc les bonnes coordonnées dans le pdf.",[35,55,56],{},"Nous avons plusieurs problématiques.",[58,59,61],"h3",{"id":60},"différence-entre-pdfs","Différence entre PDFs",[35,63,64,65,71,74],{},"La première difficulté est de voir la différence entre 2 millésimes. Nous utilisons pour ça l'outil\ndiff-pdf\n(",[66,67],"a",{"href":68,"rel":69},"https:\u002F\u002Fvslavik.github.io\u002Fdiff-pdf\u002F",[70],"nofollow",[66,72,68],{"href":68,"rel":73},[70],").",[35,76,77,78,82,85],{},"Pour l'installer sur mac c'est facile (pour les autres OS je vous laisse regarder ici :\n",[66,79],{"href":80,"rel":81},"https:\u002F\u002Fgithub.com\u002Fvslavik\u002Fdiff-pdf#obtaining-the-binaries",[70],[66,83,80],{"href":80,"rel":84},[70],")\n:",[87,88,92],"pre",{"className":89,"code":90,"language":91,"meta":10,"style":10},"language-sh shiki shiki-themes github-light github-dark","brew install diff-pdf\n","sh",[93,94,95],"code",{"__ignoreMap":10},[96,97,99,103,107],"span",{"class":98,"line":18},"line",[96,100,102],{"class":101},"sScJk","brew",[96,104,106],{"class":105},"sZZnC"," install",[96,108,109],{"class":105}," diff-pdf\n",[35,111,112],{},"Ensuite on peut facilement voir la différence entre 2 pdf avec la commande suivante :",[87,114,116],{"className":89,"code":115,"language":91,"meta":10,"style":10}," diff-pdf --view 2033-sd_3330.pdf 2033-sd_3723.pdf\n",[93,117,118],{"__ignoreMap":10},[96,119,120,123,127,130],{"class":98,"line":18},[96,121,122],{"class":101}," diff-pdf",[96,124,126],{"class":125},"sj4cs"," --view",[96,128,129],{"class":105}," 2033-sd_3330.pdf",[96,131,132],{"class":105}," 2033-sd_3723.pdf\n",[35,134,135],{},"La commande ouvrira une visionneuse (par contre c’est moche 😛).",[35,137,138],{},[46,139],{"alt":10,"src":140},"\u002Fimages\u002FUntitled-14.png",[30,142,144],{"id":143},"récupérer-les-coordonnées-dans-un-pdf","Récupérer les coordonnées dans un pdf",[35,146,147],{},"Afin d'avoir les coordonnées, nous pouvons utiliser facilement des outils web. Pour les curieux, le\nlien vers le code final se trouve en bas de l'article.",[35,149,150],{},"Nous commençons par créer le fichier html. Nous avons besoin d'un canvas. Nous allons aussi créer un\nspan où on mettra les coordonnées.",[87,152,156],{"className":153,"code":154,"language":155,"meta":10,"style":10},"language-html shiki shiki-themes github-light github-dark","\u003Cdiv id=\"app\">\n  \u003Cdiv class=\"coord\">Current: \u003Cspan id=\"coord\">\u003C\u002Fspan>\u003C\u002Fdiv>\n  \u003Ccanvas id=\"canvas\">\u003C\u002Fcanvas>\n\u003C\u002Fdiv>\n","html",[93,157,158,180,217,238],{"__ignoreMap":10},[96,159,160,164,168,171,174,177],{"class":98,"line":18},[96,161,163],{"class":162},"sVt8B","\u003C",[96,165,167],{"class":166},"s9eBZ","div",[96,169,170],{"class":101}," id",[96,172,173],{"class":162},"=",[96,175,176],{"class":105},"\"app\"",[96,178,179],{"class":162},">\n",[96,181,182,185,187,190,192,195,198,200,202,204,206,209,211,213,215],{"class":98,"line":11},[96,183,184],{"class":162},"  \u003C",[96,186,167],{"class":166},[96,188,189],{"class":101}," class",[96,191,173],{"class":162},[96,193,194],{"class":105},"\"coord\"",[96,196,197],{"class":162},">Current: \u003C",[96,199,96],{"class":166},[96,201,170],{"class":101},[96,203,173],{"class":162},[96,205,194],{"class":105},[96,207,208],{"class":162},">\u003C\u002F",[96,210,96],{"class":166},[96,212,208],{"class":162},[96,214,167],{"class":166},[96,216,179],{"class":162},[96,218,220,222,225,227,229,232,234,236],{"class":98,"line":219},3,[96,221,184],{"class":162},[96,223,224],{"class":166},"canvas",[96,226,170],{"class":101},[96,228,173],{"class":162},[96,230,231],{"class":105},"\"canvas\"",[96,233,208],{"class":162},[96,235,224],{"class":166},[96,237,179],{"class":162},[96,239,241,244,246],{"class":98,"line":240},4,[96,242,243],{"class":162},"\u003C\u002F",[96,245,167],{"class":166},[96,247,179],{"class":162},[35,249,250],{},"Un peu de css pour bien voir les positions.",[87,252,256],{"className":253,"code":254,"language":255,"meta":10,"style":10},"language-css shiki shiki-themes github-light github-dark",".coord {\n  background-color: black;\n  color: cornsilk;\n  width: 135px;\n  position: fixed;\n}\n","css",[93,257,258,266,280,292,308,321],{"__ignoreMap":10},[96,259,260,263],{"class":98,"line":18},[96,261,262],{"class":101},".coord",[96,264,265],{"class":162}," {\n",[96,267,268,271,274,277],{"class":98,"line":11},[96,269,270],{"class":125},"  background-color",[96,272,273],{"class":162},": ",[96,275,276],{"class":125},"black",[96,278,279],{"class":162},";\n",[96,281,282,285,287,290],{"class":98,"line":219},[96,283,284],{"class":125},"  color",[96,286,273],{"class":162},[96,288,289],{"class":125},"cornsilk",[96,291,279],{"class":162},[96,293,294,297,299,302,306],{"class":98,"line":240},[96,295,296],{"class":125},"  width",[96,298,273],{"class":162},[96,300,301],{"class":125},"135",[96,303,305],{"class":304},"szBVR","px",[96,307,279],{"class":162},[96,309,311,314,316,319],{"class":98,"line":310},5,[96,312,313],{"class":125},"  position",[96,315,273],{"class":162},[96,317,318],{"class":125},"fixed",[96,320,279],{"class":162},[96,322,324],{"class":98,"line":323},6,[96,325,326],{"class":162},"}\n",[35,328,329],{},"Puis nous allons créer le fichier index.ts",[87,331,335],{"className":332,"code":333,"language":334,"meta":10,"style":10},"language-ts shiki shiki-themes github-light github-dark","import { pdf } from \".\u002Fpdf\";\nimport * as pdfjsLib from \"pdfjs-dist\";\nimport pdfjsWorkerEntry from \"pdfjs-dist\u002Fbuild\u002Fpdf.worker.entry.js\";\npdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorkerEntry;\n\nconst canvas = document.getElementById(\"canvas\") as HTMLCanvasElement;\nconst ctx = canvas.getContext(\"2d\") as CanvasRenderingContext2D;\n\nconst load = async () => {\n  \u002F\u002F le pdf est en base64 car le site des impôts n'accepte pas les requêtes cors\n  const pdfDoc = await pdfjsLib.getDocument(pdf).promise;\n  const page = await pdfDoc.getPage(1);\n  const viewport = page.getViewport({ scale: 1.5 });\n  const renderContext = {\n    canvasContext: ctx,\n    viewport: viewport,\n  };\n  canvas.height = renderContext.viewport.height;\n  canvas.width = renderContext.viewport.width;\n  await page.render(renderContext).promise;\n\n  function getMousePos(e: MouseEvent) {\n    var rect = canvas.getBoundingClientRect();\n    return { x: e.clientX - rect.left, y: e.clientY - rect.top };\n  }\n\n  canvas.addEventListener(\n    \"click\",\n    function (e) {\n      const pos = getMousePos(e);\n\n      \u002F\u002F\u002F check x and y against the grid\n      const [x, y] = viewport.convertToPdfPoint(pos.x, pos.y) as any;\n      const currPos = [parseInt(x, 10), parseInt(y, 10)];\n\n      document.getElementById(\"coord\")!.textContent = `${currPos[0]}, ${currPos[1]}`;\n    },\n    false,\n  );\n};\n\nload();\n","ts",[93,336,337,353,373,387,397,402,435,465,470,491,498,521,547,572,584,590,596,602,613,624,638,643,667,686,706,712,717,729,738,751,767,772,778,816,850,855,909,915,923,929,935,940],{"__ignoreMap":10},[96,338,339,342,345,348,351],{"class":98,"line":18},[96,340,341],{"class":304},"import",[96,343,344],{"class":162}," { pdf } ",[96,346,347],{"class":304},"from",[96,349,350],{"class":105}," \".\u002Fpdf\"",[96,352,279],{"class":162},[96,354,355,357,360,363,366,368,371],{"class":98,"line":11},[96,356,341],{"class":304},[96,358,359],{"class":125}," *",[96,361,362],{"class":304}," as",[96,364,365],{"class":162}," pdfjsLib ",[96,367,347],{"class":304},[96,369,370],{"class":105}," \"pdfjs-dist\"",[96,372,279],{"class":162},[96,374,375,377,380,382,385],{"class":98,"line":219},[96,376,341],{"class":304},[96,378,379],{"class":162}," pdfjsWorkerEntry ",[96,381,347],{"class":304},[96,383,384],{"class":105}," \"pdfjs-dist\u002Fbuild\u002Fpdf.worker.entry.js\"",[96,386,279],{"class":162},[96,388,389,392,394],{"class":98,"line":240},[96,390,391],{"class":162},"pdfjsLib.GlobalWorkerOptions.workerSrc ",[96,393,173],{"class":304},[96,395,396],{"class":162}," pdfjsWorkerEntry;\n",[96,398,399],{"class":98,"line":310},[96,400,401],{"emptyLinePlaceholder":16},"\n",[96,403,404,407,410,413,416,419,422,424,427,430,433],{"class":98,"line":323},[96,405,406],{"class":304},"const",[96,408,409],{"class":125}," canvas",[96,411,412],{"class":304}," =",[96,414,415],{"class":162}," document.",[96,417,418],{"class":101},"getElementById",[96,420,421],{"class":162},"(",[96,423,231],{"class":105},[96,425,426],{"class":162},") ",[96,428,429],{"class":304},"as",[96,431,432],{"class":101}," HTMLCanvasElement",[96,434,279],{"class":162},[96,436,438,440,443,445,448,451,453,456,458,460,463],{"class":98,"line":437},7,[96,439,406],{"class":304},[96,441,442],{"class":125}," ctx",[96,444,412],{"class":304},[96,446,447],{"class":162}," canvas.",[96,449,450],{"class":101},"getContext",[96,452,421],{"class":162},[96,454,455],{"class":105},"\"2d\"",[96,457,426],{"class":162},[96,459,429],{"class":304},[96,461,462],{"class":101}," CanvasRenderingContext2D",[96,464,279],{"class":162},[96,466,468],{"class":98,"line":467},8,[96,469,401],{"emptyLinePlaceholder":16},[96,471,473,475,478,480,483,486,489],{"class":98,"line":472},9,[96,474,406],{"class":304},[96,476,477],{"class":101}," load",[96,479,412],{"class":304},[96,481,482],{"class":304}," async",[96,484,485],{"class":162}," () ",[96,487,488],{"class":304},"=>",[96,490,265],{"class":162},[96,492,494],{"class":98,"line":493},10,[96,495,497],{"class":496},"sJ8bj","  \u002F\u002F le pdf est en base64 car le site des impôts n'accepte pas les requêtes cors\n",[96,499,501,504,507,509,512,515,518],{"class":98,"line":500},11,[96,502,503],{"class":304},"  const",[96,505,506],{"class":125}," pdfDoc",[96,508,412],{"class":304},[96,510,511],{"class":304}," await",[96,513,514],{"class":162}," pdfjsLib.",[96,516,517],{"class":101},"getDocument",[96,519,520],{"class":162},"(pdf).promise;\n",[96,522,524,526,529,531,533,536,539,541,544],{"class":98,"line":523},12,[96,525,503],{"class":304},[96,527,528],{"class":125}," page",[96,530,412],{"class":304},[96,532,511],{"class":304},[96,534,535],{"class":162}," pdfDoc.",[96,537,538],{"class":101},"getPage",[96,540,421],{"class":162},[96,542,543],{"class":125},"1",[96,545,546],{"class":162},");\n",[96,548,550,552,555,557,560,563,566,569],{"class":98,"line":549},13,[96,551,503],{"class":304},[96,553,554],{"class":125}," viewport",[96,556,412],{"class":304},[96,558,559],{"class":162}," page.",[96,561,562],{"class":101},"getViewport",[96,564,565],{"class":162},"({ scale: ",[96,567,568],{"class":125},"1.5",[96,570,571],{"class":162}," });\n",[96,573,575,577,580,582],{"class":98,"line":574},14,[96,576,503],{"class":304},[96,578,579],{"class":125}," renderContext",[96,581,412],{"class":304},[96,583,265],{"class":162},[96,585,587],{"class":98,"line":586},15,[96,588,589],{"class":162},"    canvasContext: ctx,\n",[96,591,593],{"class":98,"line":592},16,[96,594,595],{"class":162},"    viewport: viewport,\n",[96,597,599],{"class":98,"line":598},17,[96,600,601],{"class":162},"  };\n",[96,603,605,608,610],{"class":98,"line":604},18,[96,606,607],{"class":162},"  canvas.height ",[96,609,173],{"class":304},[96,611,612],{"class":162}," renderContext.viewport.height;\n",[96,614,616,619,621],{"class":98,"line":615},19,[96,617,618],{"class":162},"  canvas.width ",[96,620,173],{"class":304},[96,622,623],{"class":162}," renderContext.viewport.width;\n",[96,625,627,630,632,635],{"class":98,"line":626},20,[96,628,629],{"class":304},"  await",[96,631,559],{"class":162},[96,633,634],{"class":101},"render",[96,636,637],{"class":162},"(renderContext).promise;\n",[96,639,641],{"class":98,"line":640},21,[96,642,401],{"emptyLinePlaceholder":16},[96,644,646,649,652,654,658,661,664],{"class":98,"line":645},22,[96,647,648],{"class":304},"  function",[96,650,651],{"class":101}," getMousePos",[96,653,421],{"class":162},[96,655,657],{"class":656},"s4XuR","e",[96,659,660],{"class":304},":",[96,662,663],{"class":101}," MouseEvent",[96,665,666],{"class":162},") {\n",[96,668,670,673,676,678,680,683],{"class":98,"line":669},23,[96,671,672],{"class":304},"    var",[96,674,675],{"class":162}," rect ",[96,677,173],{"class":304},[96,679,447],{"class":162},[96,681,682],{"class":101},"getBoundingClientRect",[96,684,685],{"class":162},"();\n",[96,687,689,692,695,698,701,703],{"class":98,"line":688},24,[96,690,691],{"class":304},"    return",[96,693,694],{"class":162}," { x: e.clientX ",[96,696,697],{"class":304},"-",[96,699,700],{"class":162}," rect.left, y: e.clientY ",[96,702,697],{"class":304},[96,704,705],{"class":162}," rect.top };\n",[96,707,709],{"class":98,"line":708},25,[96,710,711],{"class":162},"  }\n",[96,713,715],{"class":98,"line":714},26,[96,716,401],{"emptyLinePlaceholder":16},[96,718,720,723,726],{"class":98,"line":719},27,[96,721,722],{"class":162},"  canvas.",[96,724,725],{"class":101},"addEventListener",[96,727,728],{"class":162},"(\n",[96,730,732,735],{"class":98,"line":731},28,[96,733,734],{"class":105},"    \"click\"",[96,736,737],{"class":162},",\n",[96,739,741,744,747,749],{"class":98,"line":740},29,[96,742,743],{"class":304},"    function",[96,745,746],{"class":162}," (",[96,748,657],{"class":656},[96,750,666],{"class":162},[96,752,754,757,760,762,764],{"class":98,"line":753},30,[96,755,756],{"class":304},"      const",[96,758,759],{"class":125}," pos",[96,761,412],{"class":304},[96,763,651],{"class":101},[96,765,766],{"class":162},"(e);\n",[96,768,770],{"class":98,"line":769},31,[96,771,401],{"emptyLinePlaceholder":16},[96,773,775],{"class":98,"line":774},32,[96,776,777],{"class":496},"      \u002F\u002F\u002F check x and y against the grid\n",[96,779,781,783,786,789,792,795,798,800,803,806,809,811,814],{"class":98,"line":780},33,[96,782,756],{"class":304},[96,784,785],{"class":162}," [",[96,787,788],{"class":125},"x",[96,790,791],{"class":162},", ",[96,793,794],{"class":125},"y",[96,796,797],{"class":162},"] ",[96,799,173],{"class":304},[96,801,802],{"class":162}," viewport.",[96,804,805],{"class":101},"convertToPdfPoint",[96,807,808],{"class":162},"(pos.x, pos.y) ",[96,810,429],{"class":304},[96,812,813],{"class":125}," any",[96,815,279],{"class":162},[96,817,819,821,824,826,828,831,834,837,840,842,845,847],{"class":98,"line":818},34,[96,820,756],{"class":304},[96,822,823],{"class":125}," currPos",[96,825,412],{"class":304},[96,827,785],{"class":162},[96,829,830],{"class":101},"parseInt",[96,832,833],{"class":162},"(x, ",[96,835,836],{"class":125},"10",[96,838,839],{"class":162},"), ",[96,841,830],{"class":101},[96,843,844],{"class":162},"(y, ",[96,846,836],{"class":125},[96,848,849],{"class":162},")];\n",[96,851,853],{"class":98,"line":852},35,[96,854,401],{"emptyLinePlaceholder":16},[96,856,858,861,863,865,867,870,873,876,878,881,884,887,890,893,896,898,900,902,904,907],{"class":98,"line":857},36,[96,859,860],{"class":162},"      document.",[96,862,418],{"class":101},[96,864,421],{"class":162},[96,866,194],{"class":105},[96,868,869],{"class":162},")",[96,871,872],{"class":304},"!",[96,874,875],{"class":162},".textContent ",[96,877,173],{"class":304},[96,879,880],{"class":105}," `${",[96,882,883],{"class":162},"currPos",[96,885,886],{"class":105},"[",[96,888,889],{"class":125},"0",[96,891,892],{"class":105},"]",[96,894,895],{"class":105},"}, ${",[96,897,883],{"class":162},[96,899,886],{"class":105},[96,901,543],{"class":125},[96,903,892],{"class":105},[96,905,906],{"class":105},"}`",[96,908,279],{"class":162},[96,910,912],{"class":98,"line":911},37,[96,913,914],{"class":162},"    },\n",[96,916,918,921],{"class":98,"line":917},38,[96,919,920],{"class":125},"    false",[96,922,737],{"class":162},[96,924,926],{"class":98,"line":925},39,[96,927,928],{"class":162},"  );\n",[96,930,932],{"class":98,"line":931},40,[96,933,934],{"class":162},"};\n",[96,936,938],{"class":98,"line":937},41,[96,939,401],{"emptyLinePlaceholder":16},[96,941,943,946],{"class":98,"line":942},42,[96,944,945],{"class":101},"load",[96,947,685],{"class":162},[35,949,950],{},"La ligne suivante permet de faire fonctionner correctement pdfjs-dist avec un worker.",[87,952,954],{"className":332,"code":953,"language":334,"meta":10,"style":10},"import pdfjsWorkerEntry from \"pdfjs-dist\u002Fbuild\u002Fpdf.worker.entry.js\";\npdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorkerEntry;\n",[93,955,956,968],{"__ignoreMap":10},[96,957,958,960,962,964,966],{"class":98,"line":18},[96,959,341],{"class":304},[96,961,379],{"class":162},[96,963,347],{"class":304},[96,965,384],{"class":105},[96,967,279],{"class":162},[96,969,970,972,974],{"class":98,"line":11},[96,971,391],{"class":162},[96,973,173],{"class":304},[96,975,396],{"class":162},[35,977,978,979,983],{},"Le point important du code est à la ligne 33 avec ",[980,981,982],"strong",{},"viewport.convertToPdfPoint",". Cette méthode\npermet d'avoir les bonnes coordonnées à l'intérieur du pdf. Elle va convertir le x, y du navigateur\nen coordonnées du pdf.",[35,985,986],{},"Une fois que vous aurez cliqué sur une zone du pdf, vous allez voir les coordonnées dans le bloc\nnoir en haut à gauche.",[35,988,989],{},[46,990],{"alt":10,"src":991},"\u002Fimages\u002FUntitled-15.png",[35,993,994,995,999],{},"Vous pouvez voir le résultat ici :\n",[66,996],{"href":997,"rel":998},"https:\u002F\u002Ftypescript-qgcwq5.stackblitz.io\u002F",[70],[66,1000,1001],{"href":1001,"rel":1002},"https:\u002F\u002Ftypescript-qgcwq5.stackblitz.io",[70],[35,1004,1005,1006,1010],{},"Et voir le code là :\n",[66,1007],{"href":1008,"rel":1009},"https:\u002F\u002Fstackblitz.com\u002Fedit\u002Ftypescript-qgcwq5",[70],[66,1011,1008],{"href":1008,"rel":1012},[70],[35,1014,1015],{},[980,1016,1017],{},"❗ Le fichier pdf.ts est là car :",[1019,1020,1021,1027],"ul",{},[1022,1023,1024],"li",{},[980,1025,1026],{},"stackblitz (free) ne permet pas de déposer un fichier",[1022,1028,1029],{},[980,1030,1031],{},"impossible de récupérer les fichiers pdf via fetch directement par le site des impôts (ils\nbloquent les requêtes cors)",[1033,1034,1035],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":10,"searchDepth":11,"depth":11,"links":1037},[1038,1041],{"id":32,"depth":11,"text":33,"children":1039},[1040],{"id":60,"depth":219,"text":61},{"id":143,"depth":11,"text":144},"2022-04-28","Presque chaque année, les documents changent (dans notre jargon on parle de millésime) et on doit mettre à jour notre générateur de document.","fr",{},"\u002Farticles\u002F2022-04-28-recuperer-les-coordonnees-dans-un-fichier-pdf-avec-pdfjs-dist",{"title":25,"description":1043},"articles\u002F2022-04-28-recuperer-les-coordonnees-dans-un-fichier-pdf-avec-pdfjs-dist",[1050],"Tech","re8FaMpRM_q3RYqxufwEnr0HUHWaqmRI97_9hpijsBQ",[1053,1066,1078,1091,1104,1116,1128,1135,1148,1161,1173,1185,1198,1210,1222,1234,1246,1258,1270,1282,1295,1307,1319,1332,1344,1356],{"id":1054,"title":1055,"body":1056,"description":10,"extension":13,"meta":1060,"name":1061,"navigation":16,"path":1062,"readingTime":18,"seo":1063,"stem":1064,"__hash__":1065},"authors\u002Fauthors\u002Falexandre-guillon.md","Software Engineer",{"type":7,"value":1057,"toc":1058},[],{"title":10,"searchDepth":11,"depth":11,"links":1059},[],{},"Alexandre Guillon","\u002Fauthors\u002Falexandre-guillon",{"title":1055,"description":10},"authors\u002Falexandre-guillon","4tf48mjyjFNqItOHaulICbrjeCyMag1o6801uHeTz98",{"id":1067,"title":1055,"body":1068,"description":10,"extension":13,"meta":1072,"name":1073,"navigation":16,"path":1074,"readingTime":18,"seo":1075,"stem":1076,"__hash__":1077},"authors\u002Fauthors\u002Falexis-ablain.md",{"type":7,"value":1069,"toc":1070},[],{"title":10,"searchDepth":11,"depth":11,"links":1071},[],{},"Alexis Ablain","\u002Fauthors\u002Falexis-ablain",{"title":1055,"description":10},"authors\u002Falexis-ablain","_SIAtB7f-39e5t3GiJof81NP47s6MGo2n4gaHkTy1uQ",{"id":1079,"title":1080,"body":1081,"description":10,"extension":13,"meta":1085,"name":1086,"navigation":16,"path":1087,"readingTime":18,"seo":1088,"stem":1089,"__hash__":1090},"authors\u002Fauthors\u002Faxel-shaita.md","Engineering Manager",{"type":7,"value":1082,"toc":1083},[],{"title":10,"searchDepth":11,"depth":11,"links":1084},[],{},"Axel Shaïta","\u002Fauthors\u002Faxel-shaita",{"title":1080,"description":10},"authors\u002Faxel-shaita","fK0argUhsBkWLjpTAhY13oYLVzQthcEYkCEdtHWmIgE",{"id":1092,"title":1093,"body":1094,"description":10,"extension":13,"meta":1098,"name":1099,"navigation":16,"path":1100,"readingTime":18,"seo":1101,"stem":1102,"__hash__":1103},"authors\u002Fauthors\u002Fbaptiste-faure.md","Head of Talent Acquisition",{"type":7,"value":1095,"toc":1096},[],{"title":10,"searchDepth":11,"depth":11,"links":1097},[],{},"Baptiste Faure","\u002Fauthors\u002Fbaptiste-faure",{"title":1093,"description":10},"authors\u002Fbaptiste-faure","ELisToYtcgHmgdVWZkCclTPV6exZtfyXqhpx1jjbJHs",{"id":1105,"title":1055,"body":1106,"description":10,"extension":13,"meta":1110,"name":1111,"navigation":16,"path":1112,"readingTime":18,"seo":1113,"stem":1114,"__hash__":1115},"authors\u002Fauthors\u002Fbenjamin-bouillot.md",{"type":7,"value":1107,"toc":1108},[],{"title":10,"searchDepth":11,"depth":11,"links":1109},[],{},"Benjamin Bouillot","\u002Fauthors\u002Fbenjamin-bouillot",{"title":1055,"description":10},"authors\u002Fbenjamin-bouillot","tbhCFZyfTt7ZM5b5YgqQ2nhgnSTl8BweaQQryc87fHo",{"id":1117,"title":1080,"body":1118,"description":10,"extension":13,"meta":1122,"name":1123,"navigation":16,"path":1124,"readingTime":18,"seo":1125,"stem":1126,"__hash__":1127},"authors\u002Fauthors\u002Fcedric-nicoloso.md",{"type":7,"value":1119,"toc":1120},[],{"title":10,"searchDepth":11,"depth":11,"links":1121},[],{},"Cédric Nicoloso","\u002Fauthors\u002Fcedric-nicoloso",{"title":1080,"description":10},"authors\u002Fcedric-nicoloso","ibSoh4VZYiWYTuLOnZTedaAfcnvet1Q9H7ogW0LgorY",{"id":4,"title":5,"body":1129,"description":10,"extension":13,"meta":1133,"name":15,"navigation":16,"path":17,"readingTime":18,"seo":1134,"stem":20,"__hash__":21},{"type":7,"value":1130,"toc":1131},[],{"title":10,"searchDepth":11,"depth":11,"links":1132},[],{},{"title":5,"description":10},{"id":1136,"title":1137,"body":1138,"description":10,"extension":13,"meta":1142,"name":1143,"navigation":16,"path":1144,"readingTime":18,"seo":1145,"stem":1146,"__hash__":1147},"authors\u002Fauthors\u002Feloise-chizat.md","Data Engineer",{"type":7,"value":1139,"toc":1140},[],{"title":10,"searchDepth":11,"depth":11,"links":1141},[],{},"Eloïse Chizat","\u002Fauthors\u002Feloise-chizat",{"title":1137,"description":10},"authors\u002Feloise-chizat","Utd72Vm9qT4hh2ZbFi6a2_nXw5Wb494Ed_HL1ra5yw8",{"id":1149,"title":1150,"body":1151,"description":10,"extension":13,"meta":1155,"name":1156,"navigation":16,"path":1157,"readingTime":18,"seo":1158,"stem":1159,"__hash__":1160},"authors\u002Fauthors\u002Femmanuel-auclair.md","Staff engineer",{"type":7,"value":1152,"toc":1153},[],{"title":10,"searchDepth":11,"depth":11,"links":1154},[],{},"Emmanuel Auclair","\u002Fauthors\u002Femmanuel-auclair",{"title":1150,"description":10},"authors\u002Femmanuel-auclair","MtsA8THNLEn0dTtYEIQaGwDuf7MjQL55IOeei5gugEg",{"id":1162,"title":1055,"body":1163,"description":10,"extension":13,"meta":1167,"name":1168,"navigation":16,"path":1169,"readingTime":18,"seo":1170,"stem":1171,"__hash__":1172},"authors\u002Fauthors\u002Fhoreb-parraud.md",{"type":7,"value":1164,"toc":1165},[],{"title":10,"searchDepth":11,"depth":11,"links":1166},[],{},"Horeb Parraud","\u002Fauthors\u002Fhoreb-parraud",{"title":1055,"description":10},"authors\u002Fhoreb-parraud","ajjsnUX4ohZI-ghMdbb92q_taWDkKXVZSLZXoAeLQtg",{"id":1174,"title":1080,"body":1175,"description":10,"extension":13,"meta":1179,"name":1180,"navigation":16,"path":1181,"readingTime":18,"seo":1182,"stem":1183,"__hash__":1184},"authors\u002Fauthors\u002Fhugo-contreras.md",{"type":7,"value":1176,"toc":1177},[],{"title":10,"searchDepth":11,"depth":11,"links":1178},[],{},"Hugo Contreras","\u002Fauthors\u002Fhugo-contreras",{"title":1080,"description":10},"authors\u002Fhugo-contreras","2nc3VMu9ASq9Z6Pwx2-7-Ye991Pww4p-UEDBQFfjF-Q",{"id":1186,"title":1187,"body":1188,"description":10,"extension":13,"meta":1192,"name":1193,"navigation":16,"path":1194,"readingTime":18,"seo":1195,"stem":1196,"__hash__":1197},"authors\u002Fauthors\u002Fjulien-tassin.md","Head of Engineering",{"type":7,"value":1189,"toc":1190},[],{"title":10,"searchDepth":11,"depth":11,"links":1191},[],{},"Julien Tassin","\u002Fauthors\u002Fjulien-tassin",{"title":1187,"description":10},"authors\u002Fjulien-tassin","iUIHI7SITje38Jh9X9uvYs4-VsHx4eCdt6hAlyLFG_o",{"id":1199,"title":1055,"body":1200,"description":10,"extension":13,"meta":1204,"name":1205,"navigation":16,"path":1206,"readingTime":18,"seo":1207,"stem":1208,"__hash__":1209},"authors\u002Fauthors\u002Flaurent-renard.md",{"type":7,"value":1201,"toc":1202},[],{"title":10,"searchDepth":11,"depth":11,"links":1203},[],{},"Laurent Renard","\u002Fauthors\u002Flaurent-renard",{"title":1055,"description":10},"authors\u002Flaurent-renard","5BP7Ed-pt1SQHjh0UJ1XUrlLTcdlFaDoKBCP4deHq8A",{"id":1211,"title":1055,"body":1212,"description":10,"extension":13,"meta":1216,"name":1217,"navigation":16,"path":1218,"readingTime":18,"seo":1219,"stem":1220,"__hash__":1221},"authors\u002Fauthors\u002Fleo-martin.md",{"type":7,"value":1213,"toc":1214},[],{"title":10,"searchDepth":11,"depth":11,"links":1215},[],{},"Léo Martin","\u002Fauthors\u002Fleo-martin",{"title":1055,"description":10},"authors\u002Fleo-martin","eYxCHkRgbGDV7shKdTA9s7Tu0zGV4yDGFoKR5MHQntY",{"id":1223,"title":1055,"body":1224,"description":10,"extension":13,"meta":1228,"name":1229,"navigation":16,"path":1230,"readingTime":18,"seo":1231,"stem":1232,"__hash__":1233},"authors\u002Fauthors\u002Floic-bousquet.md",{"type":7,"value":1225,"toc":1226},[],{"title":10,"searchDepth":11,"depth":11,"links":1227},[],{},"Loïc Bousquet","\u002Fauthors\u002Floic-bousquet",{"title":1055,"description":10},"authors\u002Floic-bousquet","ko12qZwiGL8XNjAoy9oWypPkIjr29Pbq7vhdtgldqeQ",{"id":1235,"title":1055,"body":1236,"description":10,"extension":13,"meta":1240,"name":1241,"navigation":16,"path":1242,"readingTime":18,"seo":1243,"stem":1244,"__hash__":1245},"authors\u002Fauthors\u002Floic-poullain.md",{"type":7,"value":1237,"toc":1238},[],{"title":10,"searchDepth":11,"depth":11,"links":1239},[],{},"Loïc Poullain","\u002Fauthors\u002Floic-poullain",{"title":1055,"description":10},"authors\u002Floic-poullain","oRIyJhFRTqxy5dLCYQ2OnYZ1DB-gLDUM-85vTSYuTF0",{"id":1247,"title":1137,"body":1248,"description":10,"extension":13,"meta":1252,"name":1253,"navigation":16,"path":1254,"readingTime":18,"seo":1255,"stem":1256,"__hash__":1257},"authors\u002Fauthors\u002Fmaud-lelu.md",{"type":7,"value":1249,"toc":1250},[],{"title":10,"searchDepth":11,"depth":11,"links":1251},[],{},"Maud Lélu","\u002Fauthors\u002Fmaud-lelu",{"title":1137,"description":10},"authors\u002Fmaud-lelu","MMbsCKuE41OMHusrl12FIEsI-Trx7l8Nn_ANhvj2_y4",{"id":1259,"title":1080,"body":1260,"description":10,"extension":13,"meta":1264,"name":1265,"navigation":16,"path":1266,"readingTime":18,"seo":1267,"stem":1268,"__hash__":1269},"authors\u002Fauthors\u002Fnicolas-poirier.md",{"type":7,"value":1261,"toc":1262},[],{"title":10,"searchDepth":11,"depth":11,"links":1263},[],{},"Nicolas Poirier","\u002Fauthors\u002Fnicolas-poirier",{"title":1080,"description":10},"authors\u002Fnicolas-poirier","dXrJkYo8az4SN_D23aYc3fQ7z8s1dR2a0lt1ogjAjJs",{"id":1271,"title":1080,"body":1272,"description":10,"extension":13,"meta":1276,"name":1277,"navigation":16,"path":1278,"readingTime":18,"seo":1279,"stem":1280,"__hash__":1281},"authors\u002Fauthors\u002Fraphael-sauget.md",{"type":7,"value":1273,"toc":1274},[],{"title":10,"searchDepth":11,"depth":11,"links":1275},[],{},"Raphaël Sauget","\u002Fauthors\u002Fraphael-sauget",{"title":1080,"description":10},"authors\u002Fraphael-sauget","Uri9bcq0QDuxRA0PbBoNtu7p_5L3dALu4kzcXVW0xyM",{"id":1283,"title":1284,"body":1285,"description":10,"extension":13,"meta":1289,"name":1290,"navigation":16,"path":1291,"readingTime":18,"seo":1292,"stem":1293,"__hash__":1294},"authors\u002Fauthors\u002Fromain-koenig.md","Co-funder & Head of innovation",{"type":7,"value":1286,"toc":1287},[],{"title":10,"searchDepth":11,"depth":11,"links":1288},[],{},"Romain Koenig","\u002Fauthors\u002Fromain-koenig",{"title":1284,"description":10},"authors\u002Fromain-koenig","uyS8--eG2_ezyqRABcJnMJmQKKuSArhPWd14aUvFeEw",{"id":1296,"title":1080,"body":1297,"description":10,"extension":13,"meta":1301,"name":1302,"navigation":16,"path":1303,"readingTime":18,"seo":1304,"stem":1305,"__hash__":1306},"authors\u002Fauthors\u002Fromaric-juniet.md",{"type":7,"value":1298,"toc":1299},[],{"title":10,"searchDepth":11,"depth":11,"links":1300},[],{},"Romaric Juniet","\u002Fauthors\u002Fromaric-juniet",{"title":1080,"description":10},"authors\u002Fromaric-juniet","4Zb2artgT-eo-PHLXi3xi4d5t7s6PfhUxeSfXIikSUY",{"id":1308,"title":1055,"body":1309,"description":10,"extension":13,"meta":1313,"name":1314,"navigation":16,"path":1315,"readingTime":18,"seo":1316,"stem":1317,"__hash__":1318},"authors\u002Fauthors\u002Fstanyslas-bres.md",{"type":7,"value":1310,"toc":1311},[],{"title":10,"searchDepth":11,"depth":11,"links":1312},[],{},"Stanyslas Bres","\u002Fauthors\u002Fstanyslas-bres",{"title":1055,"description":10},"authors\u002Fstanyslas-bres","Xa0SahETuiN4q1jrmR2ych3moAqcZ2LbU7vSfEt2RuU",{"id":1320,"title":1321,"body":1322,"description":10,"extension":13,"meta":1326,"name":1327,"navigation":16,"path":1328,"readingTime":18,"seo":1329,"stem":1330,"__hash__":1331},"authors\u002Fauthors\u002Ftalent-acquisition.md","Talent Acquisition",{"type":7,"value":1323,"toc":1324},[],{"title":10,"searchDepth":11,"depth":11,"links":1325},[],{},"Équipe Talent Acquisition","\u002Fauthors\u002Ftalent-acquisition",{"description":10},"authors\u002Ftalent-acquisition","doDfE76txftQ4wIiKjJoDmSpyzSKk0tzlgVAp6-opAY",{"id":1333,"title":1055,"body":1334,"description":10,"extension":13,"meta":1338,"name":1339,"navigation":16,"path":1340,"readingTime":18,"seo":1341,"stem":1342,"__hash__":1343},"authors\u002Fauthors\u002Fvictor-borg.md",{"type":7,"value":1335,"toc":1336},[],{"title":10,"searchDepth":11,"depth":11,"links":1337},[],{},"Victor Borg","\u002Fauthors\u002Fvictor-borg",{"title":1055,"description":10},"authors\u002Fvictor-borg","-Za-JweoiP6hyclue_WkxMXdRUDTczPGlJf6AZckjUc",{"id":1345,"title":1055,"body":1346,"description":10,"extension":13,"meta":1350,"name":1351,"navigation":16,"path":1352,"readingTime":18,"seo":1353,"stem":1354,"__hash__":1355},"authors\u002Fauthors\u002Fvirgil-roger.md",{"type":7,"value":1347,"toc":1348},[],{"title":10,"searchDepth":11,"depth":11,"links":1349},[],{},"Virgil Roger","\u002Fauthors\u002Fvirgil-roger",{"title":1055,"description":10},"authors\u002Fvirgil-roger","DfVFe5j0bCgXeEr381ZYOM5DP4m-pWb93J9-m_muKJ0",{"id":1357,"title":1055,"body":1358,"description":10,"extension":13,"meta":1362,"name":1363,"navigation":16,"path":1364,"readingTime":18,"seo":1365,"stem":1366,"__hash__":1367},"authors\u002Fauthors\u002Fyukan-zhao.md",{"type":7,"value":1359,"toc":1360},[],{"title":10,"searchDepth":11,"depth":11,"links":1361},[],{},"Yukan Zhao","\u002Fauthors\u002Fyukan-zhao",{"title":1055,"description":10},"authors\u002Fyukan-zhao","LRPHugtAJnWHsmHxy9_SR5Zas_C5p-GR_uHEs1Fhk_E",1778159247146]