Cache: Sau khi lưu biểu mẫu này, phải xóa bộ nhớ đệm (cache) của trình duyệt để những thay đổi hiện ra:

Firefox, Chrome, Safari, Opera — Shift­Reload / Tải lại       Internet Explorer — Ctrl­Refresh / Làm tươi       Konqueror — Reload / Tải lại

Nếu bạn viết mã JavaScript, chú ý đọc hướng dẫn để tránh mâu thuẫn với mã mặc định của mạng.

/*
 * Transformation varié du wikicode d'une page, incluant : 
 *
 * Recherche deux pages avant la page courante pour en extraire un modèle nr
 * et l'insère dans la page courante après avoir incrémenté le numéro de page.
 * De même pour un modèle tiret depuis la page précédente.
 *
 * Typographie (pas implémenté)
 *
 *
 * Le gadget fonctionne en trois niveau : 1) automatiquement lors de la création
 * d'une page 2) automatiquement lors de l'édition d'une page 3) sur l'appui
 * d'un bouton par l'utilisateur.
 *
 * Questions :
 *
 * Le bouton rh doit-il apparaître dans les autres espaces de noms que Page ?
 *
 * Voir la variable no_mise_en_page, c'est assez maladroit comme façon de faire,
 * plusieurs problèmes à résoudre :
 * Un gadget peut avoir besoin d'inhiber complètement ce gadget et s'en
 * servir comme librairie.
 * Un gadget peut avoir besoin de faire une requête api et la requête dans ce
 * gadget est redondante et doit pouvoir être éviter.
 * Un gadget ou script utilisateur peut vouloir étendre ce gadget, en particulier
 * pour la typographie.
 *
 *
 * À faire :
 *
 * Typographie.
 *
 * application d'un dico définit par l'utilisateur mais seulement en level = "on_button"
 *
 *
 * Bugs  :
 *
 * See also the FIXME comment(s) for caveats.
 *
 */

// Some code here come from left and right, mainly [[User:InductiveLoad]]

// From http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter
var roman_converter = {

    to_roman : function (num) {
	if (!+num)
		return false;
	var	digits = String(+num).split(""),
		key = ["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM",
		       "","X","XX","XXX","XL","L","LX","LXX","LXXX","XC",
		       "","I","II","III","IV","V","VI","VII","VIII","IX"],
		roman = "",
		i = 3;
	while (i--)
		roman = (key[+digits.pop() + (i * 10)] || "") + roman;
	return Array(+digits.join("") + 1).join("M") + roman;
    },

    to_int : function (s) {
	var	str = s.toUpperCase(),
		validator = /^M*(?:D?C{0,3}|C[MD])(?:L?X{0,3}|X[CL])(?:V?I{0,3}|I[XV])$/,
		token = /[MDLV]|C[MD]?|X[CL]?|I[XV]?/g,
		key = {M:1000,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1},
		num = 0, m;
	if (!(str && validator.test(str)))
		return false;
	while ((m = token.exec(str)))
		num += key[m[0]];
	return num;
    }
};


function levenshtein(s1, s2, case_sensitive) {
    if (s1.length < s2.length)
        return levenshtein(s2, s1);
    if (!s1)
        return s2.length;

    if (!case_sensitive) {
        s1 = s1.toLowerCase();
        s2 = s2.toLowerCase();
    }
 
    previous_row = [];
    for (var i = 0; i < s2.length+1; ++i)
        previous_row.push(i);
    for (var i = 0; i < s1.length; ++i) {
        current_row = [];
        current_row.push(i + 1);
        for (var j = 0; j < s2.length; ++j) {
            var insert = previous_row[j + 1] + 1;
            var del = current_row[j] + 1;
            var subst = previous_row[j] + (s1[i] != s2[j]);
            current_row.push(Math.min(insert, del, subst));
        }
        previous_row = current_row;
    }

    return previous_row.slice(-1)[0];
}

mise_en_page = {
    level : '',
    increment_arabic : function (rh){
        try {
            // Avoid to incr 100%, likely to be css style.
            var r = new RegExp("(\\d+)(?![%\\d])");
            var page = Number(r.exec(rh)[1]) + 2;

            return rh.replace(/\d+(?![%\d])/, page.toString());
        } catch(err) {
            return '';
        }
    },

    increment_roman : function (rh) {
        try {
            var r = new RegExp("^(.*?)([ivxlcm]+|[IVXLCM]+)(?![a-zA-ZéèàÉÈÀ])(.*?)$");

            var regex_res = r.exec(rh);

            var numeral = regex_res[2];

            var lower_case = numeral.toUpperCase() != numeral;

            var number = roman_converter.to_int(numeral) + 2;

            numeral = roman_converter.to_roman(number);
            if (lower_case)
                numeral = numeral.toLowerCase();

            return regex_res[1] + numeral + regex_res[3];
        }
        catch(err) { 
            return '';
        }
    },

    has_rh : function () {
        var header = document.getElementsByName('wpHeaderTextbox')[0];
        return !header || header.value.search(/{{([Rr]h|[Rr]unning header|[[Rr]unningHeader|[Cc]dt|[Cc]hạy đầu trang) *\|[^\n]*}}/) != -1;
    },

    has_tiret : function () {
        var textbox = document.getElementById("wpTextbox1");
        return !textbox || textbox.value.search(/{{([Cc]nc|[Cc]hữ nối cuối) *(\|[^}]*)}}/) != -1;
    },

    has_nowiki : function () {
        var textbox = document.getElementById("wpTextbox1");
        return !textbox || textbox.value.search(/<nowiki *\/>/) != -1;
    },

    has_manchette : function () {
        var textbox = document.getElementsByName('wpHeaderTextbox')[0];
        return !textbox || textbox.value.search(/{{[Tt]ạo lề *(\|[^}]*)*}}/) != -1;
    },

    set_manchette : function (content) {
        var header = document.getElementsByName('wpHeaderTextbox')[0];
        if (!header || mise_en_page.has_manchette())
            return;
        var r = new RegExp(/{{([Tt]ạo lề) *(\|[^}]*)*}}/);
        var match = r.exec(content);
        if (match)
            header.value += match[0]; 
    },

    set_rh : function (content) {
        var header = document.getElementsByName('wpHeaderTextbox')[0];
        if (!header || mise_en_page.has_rh())
            return;
        var result = mise_en_page.split_content(content);
        if (!result || !result.header) {
            return;
        }
        var r = new RegExp(/({{([Rr]h|[Rr]unning header|[[Rr]unningHeader|[Cc]dt|[Cc]hạy đầu trang) *\|)([^\n]*)}}/);
        var match = r.exec(result.header);
        if (match) {
            // match[3] == xxx(\|yyy)*, choose the field to incr, it's likely the one that can be incr
            // and which is the shortest.
            var params = match[3].split('|');
            var i;
            var last_found = -1;
            for (i = 0; i < params.length; ++i) {
                if (!params[i].length)
                    continue;
                var found = mise_en_page.increment_arabic(params[i]);
                    
                if (found === '') {
                    found = mise_en_page.increment_roman(params[i]);
                }

                if (found !== '') {
                    if (last_found == -1 || params[i].length < params[last_found].length) {
                        last_found = i;
                    }
                }
            }

            if (last_found != -1) {
                found = mise_en_page.increment_arabic(params[last_found]);
                    
                if (found === '')
                    found = mise_en_page.increment_roman(params[last_found]);

                if (found !== '')
                    params[last_found] = found;
            }
            header.value += match[1] + params.join("|") + '}}';
        }

        var textbox = document.getElementById("wpTextbox1");
        match = header.value.match(/{{([Rr]h|[Rr]unning header|[[Rr]unningHeader|[Cc]dt|[Cc]hạy đầu trang) *\|([^\n]*)}}/);
        if (match && textbox) {
            var search = match[2].replace(/\|/g, " ").replace(/^ *| *$/, "");
            var lines = textbox.value.split("\n");
            if (lines.length) {
                var dist = levenshtein(search, lines[0], false);
                var nr_line = 1;
                var tot_length = lines[0].length;
                for (var i = 1; i < lines.length; ++i) {
                    if (lines[i].length) {
                        var dist1 = levenshtein(search, lines[0] + " " + lines[i], false);
                        if (dist1 <= dist) {
                            dist = dist1;
                            nr_line = i + 1;
                            tot_length += lines[i].length;
                        }
                        break;
                    }
                }

                if (dist < 15 && dist < tot_length * 0.70) {
                    lines = lines.slice(nr_line);
                    while (lines.length && !lines[0].length) {
                        lines.shift();
                    }
                    textbox.value = lines.join("\n");
                }
            }
        }
    },

    set_tiret : function (previous_page_content) {
        var wpTextbox1 = document.getElementById("wpTextbox1");
        if (wpTextbox1 && !mise_en_page.has_tiret()) {
            var tiret = new RegExp(/{{([Tt])iret *\|(.*?)\|(.*?)}}/);
            var match = tiret.exec(previous_page_content);
            if (match) {
                 /* {{tiret|dit|-il}} --> {{tiret2|dit-|il}}  et {{tiret|''aban|don''}} --> {{tiret2|aban|don}} */
                 var part1 = match[2].replace(/''(.*)''/, "$1");
                 part1 = part1.replace(/''(.*)/, "$1");
                 part1 = part1.replace(/(.*)''/, "$1");
                 var part2 = match[3];
                 part2 = part2.replace(/''(.*)/, "$1");
                 part2 = part2.replace(/(.*)''/, "$1");
                 var has_italic = false;
                 if (part1 != match[2] || part2 != match[3])
                     has_italic = true;
                 if (part2[0] == '-') {
                     part2 = part2.slice(1);
                     part1 += '-';
                 }

                 var text = wpTextbox1.value;

                 var section = text.match(/^##[^#]*##\n(<nowiki[ ]*\/>\n\n)?/);
                 if (!section) {
                     section = [ "" ];
                     text = text.replace(/^<nowiki[ ]*\/>\n\n*(.*)/, "$1");
                 }

                 text = text.slice(section[0].length);

                 var offset = text.indexOf(part2);
                 if (offset != -1 && offset < 16)
                     text = text.slice(offset + part2.length);

                 var tiret2 = match[0].replace(tiret, "{" + "{$1|" + part1 + "|" + part2 + "}}");
                 if (text.search(/[a-zA-Zçéèà]/) == 0)
                     text = " " + text;

                 if (has_italic)
                     tiret2 = "''" + tiret2;

                 wpTextbox1.value = section[0] + tiret2 + text;
            }
        }
    },

    split_content : function (content) {
        var result = {}
        var re = /^<noinclude>([\s\S]*?)\n*<\/noinclude>([\s\S]*)<noinclude>([\s\S]*?)<\/noinclude>\n*$/;
        m = content.match(re);
        if (m) {
            result['header'] = m[1];
            result['body']   = m[2];
            result['footer'] = m[3];
        } else {
            var re2 = /^<noinclude>([\s\S]*?)\n*<\/noinclude>([\s\S]*?)\n$/;
            var m2 = content.match(re2);
            if (m2) {
                result['header'] = m2[1];
                // IE & Opera mis-implement non greedy match
                var re3 = /^([\s\S]*)<noinclude>([\s\S]*)<\/noinclude>\s*$/;
                var m3 = m2[2].match( re3 );
                if (m3) {
                    result['body']   = m3[1];
                    result['footer'] = m3[2];
                } else {
                    result['body']   = m2[2];
                    result['footer'] = '';
                }
            }
        }
        return result;
    },

    set_nowiki : function (previous_page_content) {
        /* FIXME: ne devrait pas être fait si le nowiki est caché par une autre gadget */
        if (mise_en_page.has_tiret())
            return;

        var wpTextbox1 = document.getElementById("wpTextbox1");
        if (!wpTextbox1 || mise_en_page.has_nowiki())
            return;

        /* First check if the text start with a <br />, if yes replace it by a nowiki and return */
        var content =  wpTextbox1.value;
        var section = content.match(/^##[^#]*##\n/);
        if (!section)
            section = [ "" ];
        content = content.slice(section[0].length);
        if (content.search(/^<br *\/>/) == 0) {
            content = section[0] + content.replace(/^<br *\/>/, "<nowiki/>");
            wpTextbox1.value = content;
            return;
        }

        // FIXME: do we need all of this or only rely on the previous page content finishing by a [.?!»] ?
        previous_page_content = mise_en_page.split_content(previous_page_content)['body'];
        previous_page_content = previous_page_content.replace(/<ref>(.|\n)*?<\/ref>/gm, '');
        var lines = previous_page_content.split('\n');
        /* bug du '\n' https://bugzilla.wikimedia.org/show_bug.cgi?id=26028 */
        while (lines.length && lines[lines.length - 1].length == 0) {
            lines.pop();
        }
        var count_empty = 0;
        for (var idx in lines) {
            if (!lines[idx].length)
                count_empty += 1;
        }

        content = wpTextbox1.value.replace(/\s*(.)/, "$1");
        var match = previous_page_content.match(/([.!?»]<section end="[^"]*"\/>|[.!?»])$/);
        var avg_length = previous_page_content.length / (lines.length - count_empty);
        var last_length = lines[lines.length - 1].length;
        if (avg_length > 30 && avg_length < 100 && last_length < avg_length * 0.60) {
            if (content.length)
                wpTextbox1.value = '<nowiki />\n\n' + content;
        } else if (match) {
            if (content.length)
                wpTextbox1.value = '<nowiki />\n\n' + content;
        }
    },

    split_paragraph : function (text) {
        var lines = text.split("\n");
        var avg_length = text.length / lines.length;
        if (avg_length > 40) {
            var result = [];
            for (idx in lines) {
                if (lines[idx].indexOf('— ') == 0)
                    result[result.length] = "";
                result[result.length] = lines[idx];
                if (lines[idx] && lines[idx].length < avg_length * 0.75)
                    result[result.length] = "";
            }
            text = result.join("\n");
            // in case paragraph mark already exists.
            text = text.replace(/\n\n\n\n/g, "\n\n");
            text = text.replace(/\n\n\n/g, "\n\n");
        }
        // Perhaps a better place to strip blank line at start/end ?
        text = text.replace(/^\n*/, "");
        text = text.replace(/\s*$/, "");

        return text;
    },

    handle_paragraph : function() {
        var textbox = document.getElementById("wpTextbox1");
        if (textbox)
            textbox.value = mise_en_page.split_paragraph(textbox.value);
    },

    pagename : null,
    previous_page : null,

    get_data : function (data, pagename) {
        for (var ids in data.query.pages) {
            if (ids > 0 && data.query.pages[ids].title == pagename) {
                return data.query.pages[ids];
            }
        }
        return null;
    },

    // FIXME: we need to allow end user to specify if he wants section propagation
    // for a given book but that need to refactorize the whole code and to ensure
    // its /common.js is loaded before this script. Alternative is to add bookname
    // prefix in need_section_prefix array.
    need_section : function (pagename) {
	var need_section_prefix = [
		'Rozier - Cours d’agriculture,', 
		'Chénier - Poésies choisies, ed. Derocquigny, 1907.djvu',
		'Chénier - Œuvres poétiques, édition Moland, 1889',
		];
	for (var i = 0; i < need_section_prefix.length; ++i) {
		if (pagename.indexOf(need_section_prefix[i]) === 0)
			return true;
	}
	return false;
    },

    // try to propage section, handling in a special way an existing section called ## début ##
    last_match : function (regex, text) {
        var last_match = null;
        var match;
        while (match = regex.exec(text))
           last_match = match;
        return last_match;
    },

    propagate_section : function (previous_page_content) {
         if (!mise_en_page.need_section(mw.config.get("wgTitle")))
             return;
         var r = new RegExp("<section end=\"(.*?)\"", "g");
         var match = mise_en_page.last_match(r, previous_page_content);
         if (match) {
             var textbox = document.getElementById("wpTextbox1");
             // FIXME: Michaud must be handled differently, see Utilisateur:Phe/Michaud.js
             textbox.value = '## ' + match[1] + ' ##\n' + textbox.value;
         }
    },

    fill_rh : function (data) {
        var api_page = mise_en_page.get_data(data, mise_en_page.pagename);
        if (api_page) {
            var content = api_page.revisions[0]['*'];
            mise_en_page.set_rh(content);
            mise_en_page.set_manchette(content);
        }
        api_page = mise_en_page.get_data(data, mise_en_page.previous_page);
        if (api_page) {
            var content = api_page.revisions[0]['*'];
            mise_en_page.set_tiret(content);
            mise_en_page.set_nowiki(content);
            if (mise_en_page.level == 'auto_create') {
                mise_en_page.propagate_section(content);
		// FIXME: should we propagate <poem> here, but
		// where to place the </poem>?
	    }
        }
    },

    rh_and_tiret : function () {
        if (!mise_en_page.has_rh() || !mise_en_page.has_tiret() || !mise_en_page.has_nowiki()) {
            var r = new RegExp("(\\d+)$");
            var page = Number(r.exec(mw.config.get('wgPageName'))[1]);

            mise_en_page.pagename = 'Trang:' + mw.config.get('wgTitle').replace(/\d+$/g, page - 2);
            mise_en_page.previous_page = 'Trang:' + mw.config.get('wgTitle').replace(/\d+$/g, page - 1);

	    $.ajax({
		url: mw.config.get('wgServer') + mw.util.wikiScript( 'api' ),
		dataType: 'json',
		data: {
			'format': 'json',
			'action': 'query',
			'titles': mise_en_page.pagename + '|' + mise_en_page.previous_page,
			'prop': 'revisions',
			'rvprop': 'content',
		},
		success: mise_en_page.fill_rh
	    });
        }
    },

    /*
     * Typographie : même lorsque l'on travaille en mode création de page
     * il n'est pas sur de changer aveuglément tout le texte, d'où le
     * le split du texte en fragment où les regexps sont appliqués
     */
    typographie_fragment : function(text, typo_def) {
        var lng = typo_def.length;
        if (lng % 2 != 0)
            return text;  /* FIXME, il faut lever une exception ici ? */
        for (var i = 0; i < lng; i += 2) {
            search = new RegExp(typo_def[i + 0], "g");
            text = text.replace(search, typo_def[i + 1]);
        }
        return text;
    },

    typographie : function (text, typo_def) {
        var new_text = '';
        var last_match = 0;
        // Split the text in part which are safe to transform, e.g we don't want
        // to apply typographie_fragment on a <math>.*</math> or a &nbsp; etc.
        var splitter = new RegExp("<math>.*</math>|<[a-zA-z0-9 =\"']>|[</[a-zA-z0-9 =\"']+>|style=\".*\"|&nbsp;|&mdash;|<!--.*-->|\n:[:]*|\n;[;]*|[[][[].*]]", "gm");
        while ((result = splitter.exec(text)) != null) {
            new_text += mise_en_page.typographie_fragment(text.slice(last_match, splitter.lastIndex - result[0].length), typo_def);
            new_text += result;
            last_match = splitter.lastIndex;
        }
        new_text += mise_en_page.typographie_fragment(text.slice(last_match), typo_def)
        return new_text;
    },

    typographie_textbox : function(pagename_filter, typo_def) {
        if (!pagename_filter.test(mw.config.get("wgPageName")))
            return;

        var wpTextbox1 = document.getElementById("wpTextbox1");
        if (!wpTextbox1)
            return;

        wpTextbox1.value = mise_en_page.typographie(wpTextbox1.value, typo_def);
    },

    get_create_typo : function() {
        var char_min = 'a-zéèàùâêîôûŷäëïöüÿçœæſñ';
        var char_maj = 'A-ZÉÈÀÂÙÊÎÔÛŶÄËÏÖÏŸÇŒÆÑ';
        var char     = char_min + char_maj;
        var bw       = '([^' + char + ']|^)';
        var ew       = '([^' + char + ']|$)';
        var ch       = '[' + char + ']';

        var on_create_typo_def = [
            bw + 'flg\.', '$1fig.',
            bw + '(toi|moi|lui|elle)-môme' + ew, '$1$2-même$3',
            bw + '(nous|vous|elles|eux)-mômes' + ew, '$1$2-mêmes$3',
            'fi', 'fi',
            'fl', 'fl',
            '\s*Digitized by\s*', '',
            '\s*Google\s*', ''
        ];

        return on_create_typo_def;
    },

    line_hyphen_length : function (line) {
	if (line.length >= 8) {
	    if (line.slice(-1) == '-' || line.slice(-1) == '¬')
		return 1;
	    else if (line.slice(-2) == '- ' || line.slice(-2) == '¬ ')
		return 2;
            // this occur for half-broken text layer
	    else if (line.slice(-3) == '-  ' || line.slice(-3) == '¬  ')
		return 3;
	}
	return 0;
    },

    next_word_length : function (next_line) {
	var regexp = new RegExp("^([«»]*[ ]*)['’a-zéèàùâêîôûŷäëïöüÿçœæſñãåóA-ZÉÈÀÂÙÊÎÔÛŶÄËÏÖÏŸÇŒÆÑ-]+( : | :|:|, |,| , | ,| ; | ;|; |;| !|!| \\?|\\?|\\. |\\.| |\\)\\. |\\), )?");
	var result = regexp.exec(next_line);
        if (result && regexp.lastIndex == 0)
            return result[0].length;
	return -1;
    },

    last_word_length : function (cur_line) {
	var regexp = new RegExp("['’a-zéèàùâêîôûŷäëïöüÿçœæſñãåóA-ZÉÈÀÂÙÊÎÔÛŶÄËÏÖÏŸÇŒÆÑ-]+$");
	var result = regexp.exec(cur_line);
	if (result)
	    return cur_line.length - result[0].length;
	return -1;
    },

    validate_hyphen : function (last_word, next_word) {
        var blacklist_first_last = {
            "au" : [ "dessus", "dessous", "devant" ],
            "celui" : [ "ci", "là" ],
            "basse" : [ "cour" ],
            "beau" : [ "frère", "père" ],
            "beaux" : [ "arts", "frères" ],
            "ci" : [ "dessus", "dessous", "devant" ],
            "disent" : [ "ils", "elles" ],
            "dit" : [ "celui", "celle", "ceux", "celles", "il", "elle" ],
            "en" : [ "sorte" ],
            "grand" : [ "duc", "père", "mère", "oncle" ],
            "non" : [ "seulement" ],
            "petit" : [ "fils", "neveu" ],
            "peut" : [ "être" ],
            "quelques" : [ "uns", "unes" ],
            "rendez" : [ "vous" ],
            "sur" : [ "le-champ" ],
            "sur-le" : [ "champ" ],
            "toute" : [ "puissance" ],
        };
        var blacklist_last_first = {
            "même" : [ "toi", "moi", "lui", "elle", "qu‘elle", "qu'elle" ],
            "dire" : [ "c’est-à", "c'est-à" ],
            "à-dire" : [ "c’est", "c'est" ],
            "mêmes" : [ "eux", "elles", "qu’eux", "qu'eux", "qu’elles", "qu'elles", "nous", "vous" ],
        };
        var blacklist_first = {
            "très" : true,
            "arrière" : true,
        };
        var blacklist_last = {
            "un"    : true, "deux"  : true, "trois" : true, "quatre" : true,
            "cinq"  : true, "six"   : true, "sept"  : true, "huit"   : true,
            "neuf"  : true, "dix"   : true, "onze"  : true, "douze"  : true,
            "treize": true, "quatorze" : true, "quinze" : true, "seize" : true, "vingt" : true,
            "nous"  : true, "vous"  : true, "il"    : true,  "ils"   : true,
            "elle"  : true, "elles" : true, "tu"    : true,
            "on"    : true, "y"     : true,
        };

        next_word = next_word.replace(/( : | :|:|, |,| , | ,| ; | ;|; |;| !|!| \?|\?|\. |\.| |\)\. |\), )$/, "");
        next_word = next_word.replace(/ *$/, "");

        if (next_word[0].toUpperCase() == next_word[0])
            return false;

        if (blacklist_first[last_word])
            return false;

        if (blacklist_last[next_word])
            return false;

        if (blacklist_first_last[last_word] && $.inArray(next_word, blacklist_first_last[last_word]) != -1)
            return false;

        if (blacklist_last_first[next_word] && $.inArray(last_word, blacklist_last_first[next_word]) != -1)
            return false;

        return true;
    },

    tweak_next_word : function (next_word) {
        return next_word.replace(/^[«»]*[ ]*(.*)$/, '$1');
    },
   
    remove_hyphen : function (text) {
        var lines = text.split("\n");
        var delete_lines = [];
        if (lines.length > 1) {
            for (var i = 0; i < lines.length - 1; ++i) {
                var cur_line = lines[i];
                var next_line = lines[i + 1];
		var hyphen_length = mise_en_page.line_hyphen_length(cur_line);
		var next_w_length = mise_en_page.next_word_length(next_line);
                if (hyphen_length && next_w_length != -1) {
		    cur_line = cur_line.slice(0, -hyphen_length);
		    var last_w_length = mise_en_page.last_word_length(cur_line);
		    var next_word = next_line.slice(0, next_w_length);
                    next_word = mise_en_page.tweak_next_word(next_word);
		    var last_word = cur_line.slice(last_w_length);
		    if (!mise_en_page.validate_hyphen(last_word, next_word))
                        cur_line += '-';
                    lines[i] = cur_line + next_word;
                    lines[i + 1] = next_line.slice(next_w_length);
                    if (!lines[i+1].length)
                        delete_lines.push(i+1);
		}
            }
            while (delete_lines.length) {
                var idx = delete_lines.pop();
                lines.splice(idx, 1);
            }
	    text = lines.join("\n");
        }
        return text;
    },

    handle_hyphen : function () {
        var textbox = document.getElementById("wpTextbox1");
        if (textbox)
            textbox.value = mise_en_page.remove_hyphen(textbox.value);
    },

    /*
     * level == "auto_create", automatic call on a Page: creation
     * level == "auto_edit", automatic call on a Page: edition excluding case "auto_create"
     * level == "on_button", called on an explicit user action
     */
    exec : function (level) {
        mise_en_page.level = level;
        /* for auto run level, check if we are inhibited by another gadget, this
         * allow for another gadget to take over this one and use it as a library,
         * typically because it wants to do its own api request.
         */
        if (level == "auto_create" && !window.no_mise_en_page) {
            mise_en_page.rh_and_tiret();
            mise_en_page.typographie_textbox(/.*/, mise_en_page.get_create_typo());
            mise_en_page.handle_paragraph();
            mise_en_page.handle_hyphen();
        } else if (level == "auto_edit" && !window.no_mise_en_page) {
            /* no rh and tiret, it's not enough safe in this mode */
        } else if (level == "on_button") {
            mise_en_page.rh_and_tiret();
            mise_en_page.typographie_textbox(/.*/, mise_en_page.get_create_typo());
        } else {
            mw.log("mise_en_page.exec(level) called with an unknown level : " + level);
        }
    },

    editForm : function() {
	window.insert_button.editForm( {
		'img_classic'  : '//upload.wikimedia.org/wikipedia/commons/thumb/b/bc/Button_running_header.svg/23px-Button_running_header.svg.png',
		'img_advanced' : '//upload.wikimedia.org/wikipedia/commons/c/c1/LibreOffice_3.4_tango_icon_lc_graphicfiltertoolbox.png',
		'tooltip'      : 'Mise en page',
		'img_id'       : 'wsMiseEnPage',
		'on_click'     : function() { mise_en_page.exec("on_button"); }
	} );
    },
};

$(function () { 
    if (mw.config.get('wgCanonicalNamespace') == 'Trang' && $.inArray(mw.config.get("wgAction"), [ "edit", "submit" ]) != -1) {
        if ($('.mw-newarticletext').length) {
            mise_en_page.exec("auto_create");
        } else {
            mise_en_page.exec("auto_edit");
        }
        mw.loader.using( 'user.options' ).done( mise_en_page.editForm );
    }
});