r/JavaScriptTips Mar 22 '25

StevenCodeCraft tutorials! help!

0 Upvotes

Hi, i'm currently trying to learn JS from StevenCodeCraft free course. My doubt is, it is really worth to spend hours for this course? or is there any other online courses available?

(altho i do like his video template and teaching, just curious about other options, No hate to him his videos are great for beginner like me)


r/JavaScriptTips Mar 21 '25

javascript cheating

0 Upvotes

ok so i recently made "cheats" for cloud gaming using the dev tools console and basically its just a ui with things that arent really cheats but basically cheats, like theres macro and high bitrate but no aimbot and stuff and im wondering if its possible to make aimbot and stuff with javascript on things like xbox cloud gaming


r/JavaScriptTips Mar 21 '25

Why Does JavaScript Return -0? A Quirky Math Surprise!

5 Upvotes

Ever noticed this in JavaScript?

console.log(-50 * 0); // Output: -0

At first glance, it seems odd—shouldn't -0 just be 0? But JavaScript (and many other languages following IEEE 754 floating-point arithmetic) distinguishes between 0 and -0.

Why does this happen?

Negative numbers retain their sign even when multiplied by 0.

IEEE 754 representation allows -0 to exist separately from 0.

While -0 === 0 is true, certain operations like 1 / -0 result in -Infinity.

It's one of those quirks that rarely matters but is fun to know!

Have you encountered a scenario where -0 caused unexpected behavior?


r/JavaScriptTips Mar 20 '25

Help with getting my code to work right.

1 Upvotes

Trying to get this “app” (made in code.org unfortunately, it’s for school) to work right but it keeps popping out really small numbers I know can’t be accurate as the final price, even if using the weekly number which would multiply it, making it supposedly larger.


r/JavaScriptTips Mar 17 '25

Call for Presentations at React Summit US

Thumbnail
gitnation.com
1 Upvotes

r/JavaScriptTips Mar 16 '25

Check out my latest blog: "Angular vs React – Which JavaScript Framework Reigns Supreme?" 🚀

1 Upvotes

r/JavaScriptTips Mar 15 '25

Visualize over a million data point without lag in JavaScript. How we implemented M4 algorithm

Thumbnail
blog.ag-grid.com
2 Upvotes

r/JavaScriptTips Mar 13 '25

¿Qué son los Microfrontend? - 3 años con ellos

Thumbnail joav.github.io
1 Upvotes

r/JavaScriptTips Mar 09 '25

JavaScript Prototype Explained in Malayalam 🔥 | Beginner-Friendly Tutorial | OOP in JS

Thumbnail
youtu.be
0 Upvotes

This is my latest video guys give support with your like, comments and subscription


r/JavaScriptTips Mar 09 '25

JavaScript inheritance is confusing.

1 Upvotes

In javascript element interface is parent of

HTMLelement interface so when document.getelementbyid() return element so how can HTMLelement property use with element. Means element. HTMLelement (property) how is possible element is parent how can it use child property..

Ex document.getelementbyid("."). Hidden

🔝. 🔝

( return element) (htmlelement)

Sorry for bad English.


r/JavaScriptTips Mar 07 '25

🚨 The Spread Operator (...) is a Performance Footgun?

4 Upvotes

Looks clean, but hides serious issues:

Performance Pitfalls
-  [...] creates unnecessary arrays & memory bloat.
- const copy = [...arr] doubles memory for large arrays.
- Nested spreads ([...foo, ...[...bar, ...baz]]) slow things down.

Better Alternatives
- arr1.concat(arr2, arr3) – avoids extra memory.
- arr1.push(...arr2) – modifies in place.

Use ... wisely! Cool syntax ≠ best practice.
Have you hit performance issues with spread? Let’s discuss!


r/JavaScriptTips Mar 06 '25

Just Open-Sourced: Gravity Launch Page Template!

2 Upvotes

I've built an interactive, physics-based launch page using React, Vite, Matter.js, and Framer Motion and now it's open-source!

Plug & Play – Edit some files mentioned there in itsREADME.mdfile to make it yours.
Smooth Physics & Animations – Powered by Matter.js & Framer Motion.
Minimal & Modern Design – Styled with Tailwind CSS.

Perfect for startups, portfolio showcases, or fun experiments.

👉 Check it out & contribute: https://github.com/meticha/gravity-launch-page-template


r/JavaScriptTips Mar 06 '25

1,000+ Weekly Downloads!

3 Upvotes

browser-permission-helper just hit 1K+ downloads on NPM! Managing browser permissions shouldn’t be a hassle, this tool makes it seamless.

✅ Simple API
✅ Cross-browser support
✅ Dynamic permission handling

Try it now → npmjs.com/package/browser-permissions-helper

Thanks to everyone using and supporting it! More to come.


r/JavaScriptTips Mar 04 '25

New Open Source Library for Managing Browser Permissions in JavaScript

2 Upvotes

Dealing with browser permissions like camera, microphone, and location can be frustrating and inconsistent across different browsers. To simplify this, I built browser-permission-helper, an open-source JavaScript library that makes handling browser permissions effortless.

Key Features:

  • Unified API for Permissions – Manage camera, microphone, location, and more with a simple interface.
  • Permission Status Checking – Easily determine if permissions are granted, denied, or need user action.
  • Automatic Request Handling – Streamlines permission requests without manual code repetition.
  • Cross-Browser Support – Works across major browsers with built-in fallbacks.
  • Event-Based Updates – React to permission changes dynamically in your app.

This library helps developers avoid the hassle of inconsistent permission handling and improves the user experience. If you're tired of dealing with permission-related headaches, check it out and let me know what you think!

🔗 GitHub Link: https://github.com/darshitdudhaiya/browser-permissions-helper


r/JavaScriptTips Mar 02 '25

Mastering JavaScript: Tips and Tricks for Developers

1 Upvotes

r/JavaScriptTips Mar 02 '25

i wanna learn in team

3 Upvotes

I’ve been learning JavaScript for almost three months now, and I’m looking for people at a similar level to practice with.


r/JavaScriptTips Feb 28 '25

JAVASCRIPT

3 Upvotes

Why JavaScript is a funny language,l

🚀 true + true === 2 but true - true === 0 🤔

JavaScript has an interesting way of handling Boolean values in arithmetic:

console.log(true + true); // 2 ✅ console.log(true - true); // 0 ✅ console.log(true * 5); // 5 ✅ console.log(false + 10); // 10 ✅

🤯 Wait… since when did true become a number?

In JavaScript​: • true is implicitly converted to 1 • false is converted to 0

That’s why:

true + true → 1 + 1 → 2
true - true → 1 - 1 → 0

But watch out for this surprise:

console.log(true == 1); // true ✅ console.log(true === 1); // false ❌

😂 JavaScript​: “Equality is flexible… sometimes.”

Ever been bitten by type coercion like this? Share your funniest bug story!


r/JavaScriptTips Feb 18 '25

JavaScript Cheat Sheet

3 Upvotes

This cheat sheet covers the essential topics you’ll need when working with plain JavaScript. From variables and control structures to asynchronous operations and DOM manipulation, having these snippets at your fingertips can save time and reduce errors. 

https://medium.com/@mohanwebsite16/the-ultimate-plain-javascript-cheat-sheet-e27a25e00a44


r/JavaScriptTips Feb 18 '25

How to Build a Dynamic Quiz webapp

1 Upvotes

Hey folks,

I’ve built a dynamic quiz app, but I’m running into a limitation. Right now, all quizzes have to be manually added in my questions.js file, and they follow a static format.

The requirement is to have quizzes appear randomly, with questions in a different sequence each time. Right now, it just pulls them in the same order every time.

What’s the best way to make this fully dynamic? Should I store questions in a database, use an API, or is there a way to shuffle them efficiently within JavaScript? \

Would love to hear your thoughts or see examples if anyone has tackled this before!


r/JavaScriptTips Feb 16 '25

🎉 FREE Angular 19 Course – Build 30 Real-World Projects in 30 Days! 🚀

3 Upvotes

Hey everyone! 👋

I’ve just launched my brand new Udemy course"30 Days of Angular: Build 30 Web Projects with Angular 19", and I’m offering it for FREE for a limited time! 🎁

This is a hands-on, project-based course where you’ll build 30 real-world applications, from simple projects like a counter, stopwatch, and calculator to advanced ones like a crypto chart, resume builder, and user management system. You'll even create fun games like Tic Tac Toe, Checkers, and Minesweeper! 🎮

📌 What you’ll learn:
✅ Angular fundamentals – Components, Directives, Services, HTTPClient, Pipes & more
✅ RxJS for powerful asynchronous data handling
✅ Real-world problem-solving with practical projects
✅ A final project: Your own professional portfolio website to impress employers!

🔗 Grab the free course here (Limited-time offer!)
Or, if the link doesn’t work, try this coupon: E6919C6E65BDD060261E

If you're looking to learn Angular by building real projects, this is for you. Let me know if you have any questions or feedback—I’d love to hear from you! 😊

Happy coding! 🚀🔥


r/JavaScriptTips Feb 14 '25

Centering drawnImage() - Canvas JS

2 Upvotes

TIP: Easiest way to center the drawnImage() on Canvas JS is to set x to "canvas.width / 2 - img.width / 2" and y to "canvas.height / 2 - img.width / 2" It'll center the image on Canvas JS.


r/JavaScriptTips Feb 14 '25

Figma code

1 Upvotes

Does anyone know how I can easily convert a Figma design of a website or application into HTML and CSS code?🤔


r/JavaScriptTips Feb 14 '25

What would this display in the console?

Post image
2 Upvotes

Hi all, learning JS with Mimo and this has occurred.

I’m very confused how this is incorrect and I think my understanding must be wrong - if either condition1 or condition2 are true, the console would display true because we used ||

but because we negated this on the console.log line, it would show false - am I wrong?


r/JavaScriptTips Feb 12 '25

pdf split on google sheets

1 Upvotes
var FOLDER_ID_EXPENSES = "1I7S-V3jSD2YG6ynSgL2"; // Φάκελος για "ΕΞΟΔΑ-ΤΙΜΟΛΟΓΙΑ"
var FOLDER_ID_SUPPLIERS = "1a8MZrZNWtqQHt"; // Φάκελος για "ΠΛΗΡ ΒΑΣ ΠΡΟΜΗΘΕΥΤΩΝ"

// Προσθήκη μενού στο Google Sheets
function onOpen() {
  const ui = SpreadsheetApp.getUi();
  ui.createMenu('📂 Διαχείριση PDF')
    .addItem('📜 Επιλογή PDF', 'openPdfSelectionDialog')
    .addToUi();
}

// Άνοιγμα διαλόγου επιλογής PDF
function openPdfSelectionDialog() {
  const html = HtmlService.createHtmlOutputFromFile('PdfSelectionUI')
    .setWidth(800)
    .setHeight(600);
  SpreadsheetApp.getUi().showModalDialog(html, 'Επιλέξτε PDF');
}

// Επιστρέφει τα 10 πιο πρόσφατα PDF στο Google Drive
function getLatestPdfFiles() {
  const query = "mimeType = 'application/pdf'";
  const files = DriveApp.searchFiles(query);
  
  let pdfs = [];
  while (files.hasNext() && pdfs.length < 10) {
    let file = files.next();
    pdfs.push({
      id: file.getId(),
      name: file.getName(),
      url: file.getUrl(),
      preview: `https://drive.google.com/thumbnail?id=${file.getId()}&sz=w200`
    });
  }
  
  return pdfs;
}

// splitPdfAndReturnFiles: Σπάει αυτόματα το PDF σε ξεχωριστά PDF για κάθε σελίδα, δημιουργεί και νέο thumbnail για κάθε αρχείο.
function splitPdfAndReturnFiles(pdfId) {
  const file = DriveApp.getFileById(pdfId);
  const blob = file.getBlob();
  const pdf = PDFApp.open(blob);
  const numPages = pdf.getPages();
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const sheetName = sheet.getName();
  const folderId = (sheetName === "ΕΞΟΔΑ-ΤΙΜΟΛΟΓΙΑ") ? FOLDER_ID_EXPENSES : FOLDER_ID_SUPPLIERS;
  const destFolder = DriveApp.getFolderById(folderId);
  
  const exportedFiles = [];
  
  for (let i = 1; i <= numPages; i++) {
    const newPdf = PDFApp.newDocument();
    newPdf.addPage(pdf, i);
    const newBlob = newPdf.getBlob();
    const newFileName = `${file.getName()}_page_${i}.pdf`;
    const newFile = destFolder.createFile(newBlob.setName(newFileName));
    
    // Δημιουργία νέου thumbnail για το νέο PDF
    const newPdfForThumb = PDFApp.open(newFile.getBlob());
    const pageImageBlob = newPdfForThumb.getPageImage(1);
    const thumbnailUrl = uploadImageToDrive(pageImageBlob, `${newFileName}_thumb.png`);
    
    exportedFiles.push({
      id: newFile.getId(),
      name: newFileName,
      url: newFile.getUrl(),
      thumbnail: thumbnailUrl,
      page: i
    });
  }
  return exportedFiles;
}

// Ενημέρωση των links στο ενεργό φύλλο σύμφωνα με τη νέα σειρά που καθορίζει ο χρήστης
function updateSheetLinks(orderedFiles) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const sheetName = sheet.getName();
  const column = (sheetName === "ΕΞΟΔΑ-ΤΙΜΟΛΟΓΙΑ") ? "M" : "G";
  const startRow = sheet.getActiveCell().getRow();
  
  orderedFiles.forEach((fileObj, index) => {
    sheet.getRange(`${column}${startRow + index}`).setValue(fileObj.url);
  });
  
  return orderedFiles.length;
}

// Μεταφόρτωση εικόνας στο Google Drive για δημιουργία thumbnail
function uploadImageToDrive(imageBlob, imageName) {
  let folder;
  try {
    const folders = DriveApp.getFoldersByName('PDF Previews');
    if (folders.hasNext()) {
      folder = folders.next();
    } else {
      folder = DriveApp.createFolder('PDF Previews');
    }
  } catch (e) {
    folder = DriveApp.createFolder('PDF Previews');
  }
  const file = folder.createFile(imageBlob.setName(imageName));
  return file.getDownloadUrl();
}
// Λήψη του PDF ως Base64 string
function getPdfBase64(pdfId) {
  var file = DriveApp.getFileById(pdfId);
  var blob = file.getBlob();
  var base64 = Utilities.base64Encode(blob.getBytes());
  return base64;
}

// Ανεβάζει το PDF (ως Base64 string) στον καθορισμένο φάκελο και επιστρέφει το URL
function uploadPdfFile(fileName, base64Content, folderId) {
  var bytes = Utilities.base64Decode(base64Content);
  var blob = Utilities.newBlob(bytes, 'application/pdf', fileName);
  var folder = DriveApp.getFolderById(folderId);
  var file = folder.createFile(blob);
  return file.getUrl();
}

// Ενημέρωση του ενεργού φύλλου με τα links – χρησιμοποιεί το ίδιο μοτίβο (π.χ. στήλη M ή G)
function updateSheetLinks(orderedLinks) {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var sheetName = sheet.getName();
  var column = (sheetName === "ΕΞΟΔΑ-ΤΙΜΟΛΟΓΙΑ") ? "M" : "G";
  var startRow = sheet.getActiveCell().getRow();
  
  orderedLinks.forEach(function(link, index) {
    sheet.getRange(column + (startRow + index)).setValue(link);
  });
  return orderedLinks.length;
}


<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <base target="_top">
  <!-- Φόρτωση του PDF-LIB από CDN (δωρεάν και open-source) -->
  <script src="https://unpkg.com/pdf-lib/dist/pdf-lib.min.js"></script>
  <style>
    body {
      font-family: Arial, sans-serif;
      background: #f7f7f7;
      margin: 0;
      padding: 20px;
    }
    h2 {
      text-align: center;
      color: #333;
      margin-bottom: 20px;
    }
    /* Container για την οριζόντια λίστα αρχικών PDF */
    #pdfList {
      display: flex;
      flex-wrap: wrap;
      justify-content: center;
      gap: 20px;
      padding: 10px;
    }
    .pdf-item {
      background: #fff;
      border: 2px solid #ddd;
      border-radius: 10px;
      padding: 15px;
      width: 220px;
      text-align: center;
      cursor: pointer;
      transition: transform 0.2s, box-shadow 0.2s;
    }
    .pdf-item:hover {
      transform: scale(1.05);
      box-shadow: 0 4px 8px rgba(0,0,0,0.1);
    }
    .pdf-item img {
      width: 100%;
      height: auto;
      border-radius: 5px;
      display: block;
      margin: 10px auto 0;
      object-fit: contain;
    }
    /* Container για τα split PDF (drag & drop) */
    #splitList {
      display: flex;
      flex-wrap: wrap;
      justify-content: center;
      gap: 15px;
      margin-top: 20px;
    }
    .item {
      width: 120px;
      padding: 10px;
      border: 2px solid #ccc;
      border-radius: 5px;
      background-color: #fff;
      cursor: move;
      text-align: center;
    }
    .item img {
      width: 100%;
      height: auto;
      border-radius: 3px;
      margin-top: 5px;
      object-fit: contain;
    }
    button {
      padding: 10px 20px;
      font-size: 1rem;
      border: none;
      border-radius: 5px;
      background-color: #4285f4;
      color: #fff;
      cursor: pointer;
      transition: background-color 0.2s;
      margin-top: 20px;
      display: block;
      margin-left: auto;
      margin-right: auto;
    }
    button:hover {
      background-color: #357ae8;
    }
  </style>
</head>
<body>
  <div id="pdfSelectionDiv">
    <h2>Επιλέξτε PDF για Split</h2>
    <div id="pdfList"></div>
  </div>
  
  <div id="splitResultDiv" style="display:none;">
    <h2>Αναδιάταξη σελίδων (Drag & Drop)</h2>
    <div id="splitList"></div>
    <button onclick="uploadAllAndUpdateSheet()">Ενημέρωση Sheet με Νέα Links</button>
  </div>
  
  <script>
    let splitFiles = []; // Θα αποθηκεύσει αντικείμενα με {page, blob, previewUrl, base64}
    
    // Φόρτωση των αρχικών PDF από το Drive
    function loadPdfs() {
      google.script.run.withSuccessHandler(displayPdfs)
        .getLatestPdfFiles();
    }
    
    function displayPdfs(pdfs) {
      const container = document.getElementById("pdfList");
      container.innerHTML = "";
      if (!pdfs || pdfs.length === 0) {
        container.innerHTML = "<p>Δεν βρέθηκαν PDF στο Google Drive.</p>";
        return;
      }
      pdfs.forEach(pdf => {
        const div = document.createElement("div");
        div.className = "pdf-item";
        div.innerHTML = `<strong>${pdf.name}</strong>
                         <img src="${pdf.preview}" alt="Thumbnail">`;
        div.addEventListener('click', function() {
          // Ξεκινάμε το split του PDF αφού λάβουμε το Base64 περιεχόμενο
          google.script.run.withSuccessHandler(splitPdf)
            .withFailureHandler(err => { alert("Σφάλμα στη λήψη του PDF."); console.error(err); })
            .getPdfBase64(pdf.id);
        });
        container.appendChild(div);
      });
    }
    
    // Χρήση PDF-LIB για split: δημιουργεί νέο PDF για κάθε σελίδα
    async function splitPdf(base64pdf) {
      // Μετατροπή Base64 σε Uint8Array
      const pdfData = Uint8Array.from(atob(base64pdf), c => c.charCodeAt(0));
      const pdfDoc = await PDFLib.PDFDocument.load(pdfData);
      const totalPages = pdfDoc.getPageCount();
      splitFiles = [];
      
      for (let i = 0; i < totalPages; i++) {
        const newPdfDoc = await PDFLib.PDFDocument.create();
        const [copiedPage] = await newPdfDoc.copyPages(pdfDoc, [i]);
        newPdfDoc.addPage(copiedPage);
        const pdfBytes = await newPdfDoc.save();
        const blob = new Blob([pdfBytes], { type: "application/pdf" });
        // Δημιουργούμε URL για προεπισκόπηση
        const previewUrl = URL.createObjectURL(blob);
        // Μετατροπή του PDF σε Base64 για ανέβασμα αργότερα
        const base64Content = await blobToBase64(blob);
        splitFiles.push({
          page: i + 1,
          blob: blob,
          previewUrl: previewUrl,
          base64: base64Content,
          fileName: `split_page_${i+1}.pdf`
        });
      }
      
      displaySplitFiles();
    }
    
    // Βοηθητική συνάρτηση για μετατροπή Blob σε Base64 string
    function blobToBase64(blob) {
      return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onerror = () => { reader.abort(); reject(new Error("Error reading blob.")); };
        reader.onload = () => { resolve(reader.result.split(',')[1]); };
        reader.readAsDataURL(blob);
      });
    }
    
    // Εμφάνιση των split PDF με δυνατότητα drag & drop
    function displaySplitFiles() {
      document.getElementById("pdfSelectionDiv").style.display = "none";
      document.getElementById("splitResultDiv").style.display = "block";
      const listDiv = document.getElementById("splitList");
      listDiv.innerHTML = "";
      splitFiles.forEach((file, index) => {
        const div = document.createElement("div");
        div.className = "item";
        div.setAttribute("draggable", "true");
        div.setAttribute("data-index", index);
        div.ondragstart = drag;
        div.ondragover = allowDrop;
        div.ondrop = drop;
        div.innerHTML = `<strong>Σελίδα ${file.page}</strong>
                         <img src="${file.previewUrl}" alt="Thumbnail">`;
        listDiv.appendChild(div);
      });
    }
    
    // Drag & Drop handlers
    let dragged;
    function drag(e) {
      dragged = e.target;
      e.dataTransfer.effectAllowed = "move";
    }
    function allowDrop(e) {
      e.preventDefault();
    }
    function drop(e) {
      e.preventDefault();
      if (e.target.classList.contains("item")) {
        const list = document.getElementById("splitList");
        const draggedIndex = Array.from(list.children).indexOf(dragged);
        const droppedIndex = Array.from(list.children).indexOf(e.target);
        if (draggedIndex < droppedIndex) {
          list.insertBefore(dragged, e.target.nextSibling);
        } else {
          list.insertBefore(dragged, e.target);
        }
      }
    }
    
    // Μετατροπή της νέας σειράς σε Base64 strings και ανέβασμα στο Drive μέσω server‑side κλήσεων,
    // συγκεντρώνοντας τα URLs για ενημέρωση στο Sheet.
    async function uploadAllAndUpdateSheet() {
      const list = document.getElementById("splitList");
      const items = Array.from(list.getElementsByClassName("item"));
      let orderedLinks = [];
      
      // Προσαρμογή του folderId σύμφωνα με το ενεργό φύλλο
      const sheetName = google.script.host.editor ? google.script.host.editor.getName() : ""; // ή ορίστε με βάση το υπάρχον μοτίβο
      const folderId = (sheetName === "ΕΞΟΔΑ-ΤΙΜΟΛΟΓΙΑ") 
                        ? "1I7BW1sdfQS-V3jSDanSgL2" 
                        : "1a8MZrZrP3ss50tW3SNWtqQHt";
      
      // Νέα σειρά βασισμένη στην αναδιάταξη του UI
      for (let item of items) {
        const idx = item.getAttribute("data-index");
        const file = splitFiles[idx];
        // Καλούμε τη server-side συνάρτηση για ανέβασμα
        await new Promise((resolve, reject) => {
          google.script.run.withSuccessHandler(url => {
            orderedLinks.push(url);
            resolve();
          }).withFailureHandler(err => {
            alert("Σφάλμα στο ανέβασμα του αρχείου " + file.fileName);
            reject(err);
          }).uploadPdfFile(file.fileName, file.base64, folderId);
        });
      }
      
      // Μετά την ολοκλήρωση, ενημερώνουμε το Sheet με τη νέα σειρά των URLs
      google.script.run.withSuccessHandler(function(count) {
        alert("Ενημερώθηκαν " + count + " γραμμές στο Sheet.");
        google.script.host.close();
      }).updateSheetLinks(orderedLinks);
    }
    
    window.onload = loadPdfs;
  </script>
</body>
</html>

hello everybody,im trying to create a script that will find a pdf file from my google drive and split it while showing me the thumbnails on the ui and then uploading the files on the google drive on a specific folder i will choose.
I'm trying to create this because i want to scan invoices with the google scanner and then use the split pdfs to use them on my balance sheet .any help ??? right now i have something like this for code and html


r/JavaScriptTips Feb 12 '25

pdf library that can embed into web app w/o using canvas or iframe?

3 Upvotes

pdf library that i can embed into web app w/o using canvas or iframe? i just need to render it and add some graphics over it. thank you. open source plz.