vendredi 29 août 2014

numérotation des titres automatique sous Google Doc

Dans la version google doc 2014, il n'est pas possible de faire, simplement, une numérotation automatique des titres.
Oui, il est possible de créer la structure du document en premier, et d'utiliser les listes numérotées, mais si on écrit le document de façon séquentielle, c'est mort.

Voici un script Google App Script qui fait le travail. Il est basé sur des solutions que l'on trouve sur internet, et ajoute un peu  de configurabilité (des séparateurs notamment).

Dans un document google docs, ouvrir l'editeur de script (Tools->Script editor), puis copy/paste de ce code, puis selectionner la fonction à démarrer, puis l'executer, ceci ajoute un menu avec deux actions.


function onOpen() {  
  DocumentApp.getUi().createMenu('Laurent')  
    .addItem('add Heading Numbering', 'addHeaderNumbering')  
    .addItem('remove Heading Numbering', 'removeHeaderNumbering')  
    .addToUi();  
 }  
 // quote regular expression characters  
 RegExp.quote = function(str) {  
   return (str+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");  
 };  
 // inserted between numbers (customizable)  
 var numSeparator = '.'  
 // added between numbering and text (customizable)  
 var lastSeparator = '\t'  
 // heading concerned (prefix and levels)  
 var headTxt='Heading '  
 var headFirst=1  
 var headLast=6  
 // build regex  
 var reHeading = new RegExp("^"+headTxt+"(["+headFirst+"-"+headLast+"])$");  
 var reNumbering=new RegExp("^["+RegExp.quote(numSeparator)+"0-9]+"+RegExp.quote(lastSeparator))  
 function addHeaderNumbering () {  
  setHeaderNumbering(1)  
 }  
 function removeHeaderNumbering () {  
  setHeaderNumbering(0)  
 }  
 function setHeaderNumbering(addNumber) {  
  // empty array for numbering  
  var counterHeader = Array.apply(null, new Array(headLast-headFirst+1)).map(Number.prototype.valueOf,0);  
  // loop on all document paragraphs  
  var paragraphs = DocumentApp.getActiveDocument().getBody().getParagraphs();  
  for(var i=0; i < paragraphs.length; ++i) {  
   var currentPar = paragraphs[i];  
   var headStr = String(currentPar.getHeading())  
   var isHeading=headStr.match(reHeading)  
   // get headings  
   if (isHeading) {  
    var levelIndex=isHeading.pop()-headFirst;  
    // increment current level before using it  
    ++counterHeader[levelIndex];  
    var numbering = '';  
    // build numbering if necessary  
    if (addNumber){  
     for ( var j = 0; j < counterHeader.length; ++j) {  
      if (j <= levelIndex) {  
       numbering += counterHeader[j] + (j == levelIndex ? '' : numSeparator);  
      } else {  
       counterHeader[j] = 0;  
      }  
     }  
     numbering+=lastSeparator  
    }  
    currentPar.setText(numbering+currentPar.getText().split(reNumbering).pop());   
   }  
  }  
 }