Webux Lab

Par Studio Webux

Confluence vers Markdown

TG
Tommy Gingras Studio Webux S.E.N.C 2020-01-11

Confluence vers Markdown

Introduction

Voici une méthode pour exporter le contenu des pages confluence en Markdown.

Les exemples utilisés dans cet article sont fait avec Confluence Server 6.4.1 Aucune autre version n’a été essayée.

Pré-requis

Étape 1 - Installer les dépendances

L’outil utilisé pour convertir l’export confluence vers markdown est pandoc avec le module confluence-to-markdown

voici le lien pour installer l’outil : PANDOC

Ensuite, il faut créer un projet pour être en mesure de lancer les scripts

npm init
npm install --save fs fs-extra path line-reader confluence-to-markdown

Étape 2 - Création des scripts

parser.js

// Author : Tommy Gingras - Studiowebux S.E.N.C
// Description : TBD
// Date : 2020-01-10
"use strict";

const fs = require("fs-extra");
const path = require("path");

let filenames = [];
const BASE_PATH = path.join(__dirname, "docs");

fs.readdir(path.join(BASE_PATH), (err, files) => {
  files.forEach((file) => {
    if (file.includes(".md")) {
      const text = generateText(file);
      addTextAtBeginning(text, path.join(BASE_PATH, file));
      // be able to remove the first title element in the file
      filenames.push(file);
    } else {
      console.log(`<!> ${file} <!> This is not a .md file`);
    }
  });

  console.log("Done !");
  console.log(filenames);
});

function generateText(filename) {
  const id = filename.replace(/\.md/g, "");
  const title = id
    .replace(/_\./g, " ?.")
    .replace(/t_s(_|\.|$)/g, "t's ")
    .replace(/n_t(_|\.|$)/g, "n't ")
    .replace(/_|(\.md)/g, " ");

  return `---\nid: ${id}\ntitle: ${title}\n---\n\n`;
}

function addTextAtBeginning(text, file) {
  var data = fs.readFileSync(file); //read existing contents into data
  if (data.includes("---\nid:")) {
    console.log(`<!> ${file} <!> Header already present`);
    return;
  }
  var fd = fs.openSync(file, "w+");
  let buffer = Buffer.from(text);

  // data.replace(/#\ .*/, "");

  fs.writeSync(fd, buffer, 0, buffer.length, 0); //write new data
  fs.writeSync(fd, data, 0, data.length, buffer.length); //append old data
  fs.close(fd);
}

sitemap.js

// Author : Tommy Gingras - Studiowebux S.E.N.C
// Description : TBD
// Date : 2020-01-10
"use strict";

const fs = require("fs");
const lineReader = require("line-reader");
const path = require("path");

const SITEMAP = path.join("website", "sidebars.json");
const INDEX = path.join("docs", "index.md");

let title;
let link;

let incomplete = false;

let last = {
  h1: {},
  h2: {},
  h3: {},
  h4: {},
};
let currentLine;
let lines = [];
lineReader.eachLine(
  "./docs/index.md",
  function (line) {
    if (line.match(/^(\s+)-(.*)/) && !line.match(/-(.*)\)/) && !incomplete) {
      // if the line is incomplete (split by an enter)
      incomplete = true;
      currentLine = line;
      return;
    } else if (incomplete) {
      // append the next line to the last line detected
      currentLine += ` ${line.trimLeft()}`;
      incomplete = false;
    } else if (line.match(/^(\s+)-(.*)/)) {
      // The line is complete, it starts with a - and finish with a )
      currentLine = line;
    } else {
      // skip this line...
      return;
    }
    lines.push(currentLine);
  },
  () => {
    let menu = {};
    let _model = {};
    lines.forEach((line, index) => {
      // console.log(line);
      title = line.substring(line.indexOf("[") + 1, line.indexOf("]"));
      link = line.substring(line.indexOf("(") + 1, line.indexOf(")"));

      if (line.match(/^(\s{4})-(.*)/)) {
        last.h1 = {
          title,
          link,
        };
        _model = [];
        menu[title] = _model;
      } else if (line.match(/^(\s{8})-(.*)/)) {
        last.h2 = {
          title,
          link,
        };
        if (lines[index + 1] && lines[index + 1].match(/^(\s{12})-(.*)/)) {
          // this entry is a subcategory
          _model.push({
            type: "subcategory",
            label: title,
            ids: [],
          });
        } else {
          _model.push(link);
        }
      } else if (line.match(/^(\s{12})-(.*)/)) {
        last.h3 = {
          title,
          link,
        };

        // if (title.indexOf("@") === 0) {
        //   _model
        //     .find(i => {
        //       return i.label === last.h2.title;
        //     })
        //     .ids.push({ type: "subcategory", label: title, ids: [] });
        //
        if (title.indexOf("@") === 0) {
          return;
        } else {
          _model
            .find((i) => {
              return i.label === last.h2.title;
            })
            .ids.push(link);
        }
      } else if (line.match(/^(\s{16})-(.*)/)) {
        last.h4 = {
          title,
          link,
        };

        let _h2 = _model.find((h2) => {
          return h2.label === last.h2.title;
        });
        _h2.ids.push(link);
      }
    });

    fs.writeFileSync(SITEMAP, JSON.stringify(menu, null, 2));
    console.log("Done");
  }
);

Étape 3 - Exporter un espace confluence

  1. Choisir HTML comme type d’export

  1. Choisir HTML pour exporter toutes les pages
  2. Choisir les pages à exporter

  1. Choisir Custom puis les pages à exporter
  2. Cliquer sur ‘here’ pour télécharger le space

Étape 4 - Exécuter les scripts

Décompresser le fichier d’export pour obtenir tous les fichiers HTML de l’espace Confluence.

Étape 4.1 - Convertir les fichiers HTML en Markdown

Les instructions : https://github.com/meridius/confluence-to-markdown#readme

cd node_modules/confluence-to-markdown
npm install
npm run start ../../WJF-4 ../../doc

Selon la structure de vos données, il faut changer le BASE_PATH

const BASE_PATH = path.join(__dirname, "doc", "WJF-4");

Puis retourner au dossier source et lancer la commande du parser

cd ../../
node parser.js

Voici le résultat du parser,

L’image montre bien l’ajout des headers pour fonctionner avec Docusaurus V1.

Maintenant, pour obtenir le menu il faut lancer le script sitemap

Vous pouvez modifier l’emplacement du fichier SITEMAP et INDEX

const SITEMAP = path.join("sidebars.json");
const INDEX = path.join("doc", "WJF-4", "index.md");
node sitemap.js

Conclusion

Voici comment exporter le contenu confluence et le transférer en Markdown pour être utilisé avec Docusaurus V1.


Recherche