Nettoyer le code HTML pour LibreOffice Writer

Menu principal

Ce bookmarklet permet de nettoyer le code HTML copié d’une page web pour pouvoir le coller dans un document LibreOffice Writer

Nettoyage du code HTML

Le nettoyage du code HTML est effectué avec les caractéristiques suivantes :

Installation

Cette extension se présente sous la format d’un bookmarklet. Pour pouvoir l’installer, glissez-déposer le lien ci-dessous dans la barre des favoris de votre navigateur

Clean HTML

Ne cliquez pas sur ce lien depuis cette fenêtre ! Glissez-déposer le dans votre barre de favoris.

Une fois installé, allez sur une page, sélectionnez le texte et cliquez sur le lien dans votre barre de favoris.

Code source

javascript
(function () {
  const usefulAttributes = ["href", "src", "alt"]
  function isUsefulAttribute(attribute) {
    return (usefulAttributes.indexOf(attribute.name.toLowerCase()) != -1)
  }

  const badTags = ["script", "noscript"]
  function isBadTag(element) {
    return (element.nodeType == Node.ELEMENT_NODE)
      && (badTags.indexOf(element.nodeName.toLowerCase()) != -1)
  }

  const usefulTags = [
    "p", "h1", "h2", "h3", "h4", "h5", "h6", "strong", "em", "ul", "ol", "li",
    "sup", "sub", "a", "img", "pre"
  ]
  function isUsefulTag(element) {
    return (element.nodeType == Node.ELEMENT_NODE)
      && (usefulTags.indexOf(element.nodeName.toLowerCase()) != -1)
  }

  function isALink(element) {
    return (element.nodeType == Node.ELEMENT_NODE)
      && (element.nodeName.toLowerCase() == "a")
      && (element.hasAttribute("href"))
  }

  function isAnImage(element) {
    return (element.nodeType == Node.ELEMENT_NODE)
      && (element.nodeName.toLowerCase() == "img")
  }

  function convertImage(src, callback) {
    const image = new Image()
    image.crossOrigin = "Anonymous"
    image.onload = function () {
      const canvas = document.createElement("canvas")
      const context = canvas.getContext("2d")
      canvas.height = this.naturalHeight
      canvas.width = this.naturalWidth
      context.drawImage(this, 0, 0)
      const dataURL = canvas.toDataURL("image/png")
      callback(dataURL)
    }

    image.src = src
  }

  const typographicRules = [
    [/ +/g, " "],
    [/'/g, "’"],
    [/ ([?!%€$»:;])/g, " $1"],
    [/« /g, "« "],
    [/\.\.\./g, "…"],
    [/([0-9]) ?([%€$£])/g, "$1 $2"],
    [/([0-9]{1,3})[ .]([0-9]{3})[ .]([0-9]{3})/g, "$1$2$3"],
    [/([0-9]{1,3})[ .]([0-9]{3})/g, "$1$2"],
  ]
  function applyTypography(str) {
    for ([regex, replacement] of typographicRules) {
      str = str.replace(regex, replacement)
    }

    return str
  }

  function cleanTags(fragment) {
    let cleaned

    if (isBadTag(fragment)) return document.createDocumentFragment()

    if (isUsefulTag(fragment)) {
      cleaned = document.createElement(fragment.nodeName)
      for (const attribute of fragment.attributes) {
        if (!isUsefulAttribute(attribute)) continue
        cleaned.setAttributeNode(attribute.cloneNode())
      }

      if (isAnImage(fragment)) {
        convertImage(
          fragment.getAttribute("src"),
          (src) => { cleaned.setAttribute("src", src) }
        )
      } else if (isALink(fragment)) {
        const absoluteLink = new URL(
          fragment.getAttribute("href"),
          fragment.baseURI
        ).href
        cleaned.setAttribute("href", absoluteLink)
      }
    } else if (fragment.nodeType == Node.TEXT_NODE) {
      cleaned = document.createTextNode(applyTypography(fragment.data))
    } else {
      cleaned = document.createDocumentFragment()
    }

    for (const child of fragment.childNodes) {
      cleaned.appendChild(cleanTags(child))
    }

    return cleaned
  }

  function createPopup(fragment) {
    const copyTab = window.open("", "_blank", "popup").document
    copyTab.title = "CleanHTML"
    copyTab.body.appendChild(fragment)
    copyTab.close()
  }

  const selection = window.getSelection()
  if (selection.rangeCount < 1) { return }

  const elements = document.createDocumentFragment()
  for (let i = 0; i < selection.rangeCount; i++) {
    elements.appendChild(window.getSelection().getRangeAt(i).cloneContents())
  }

  createPopup(cleanTags(elements))
})()