diff --git a/doc/api/hooks_server-side.md b/doc/api/hooks_server-side.md index 6ef65cc54..962c6e123 100644 --- a/doc/api/hooks_server-side.md +++ b/doc/api/hooks_server-side.md @@ -357,7 +357,7 @@ Things in context: 1. Pad object -This hook will allow a plug-in developer to include more properties and attributes to support during HTML Export. An Array should be returned. +This hook will allow a plug-in developer to include more properties and attributes to support during HTML Export. An Array should be returned. If a value in this array is a string, the exported HTML will contain tags like `` for the content where attributes are `['tag_name', 'true']`; if a value in this array is a pair `['tag_name', 'value']`, the exported HTML will contain tags like `` for the content where attributes are `['tag_name', 'value']`. Example: ``` @@ -368,6 +368,15 @@ exports.exportHtmlAdditionalTags = function(hook, pad, cb){ }; ``` +Example when attributes are stores as `['color', 'red']` on the attribute pool: +``` +// Add the props to be supported in export +exports.exportHtmlAdditionalTags = function(hook, pad, cb){ + var padId = pad.id; + cb([["color", "red"], ["color", "blue"]]); +}; +``` + ## userLeave Called from src/node/handler/PadMessageHandler.js diff --git a/src/node/utils/ExportHtml.js b/src/node/utils/ExportHtml.js index 9e1ba1249..53469c9b9 100644 --- a/src/node/utils/ExportHtml.js +++ b/src/node/utils/ExportHtml.js @@ -19,6 +19,7 @@ var async = require("async"); var Changeset = require("ep_etherpad-lite/static/js/Changeset"); var padManager = require("../db/PadManager"); var ERR = require("async-stacktrace"); +var _ = require('underscore'); var Security = require('ep_etherpad-lite/static/js/security'); var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); var _analyzeLine = require('./ExportHelper')._analyzeLine; @@ -78,8 +79,15 @@ function getHTMLFromAtext(pad, atext, authorColors) var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough']; hooks.aCallAll("exportHtmlAdditionalTags", pad, function(err, newProps){ + // newProps can be simply a string (which means it is stored as attribute in the form of ['tag', 'true']) + // or it can be a pair of values in an Array (for the case when it is stored as ['tag', 'value']). + // The later scenario will generate HTML with tags like newProps.forEach(function (propName, i){ - tags.push(propName); + if (_.isArray(propName)) { + tags.push('span data-' + propName[0] + '="' + propName[1] + '"'); + } else { + tags.push(propName); + } props.push(propName); }); }); @@ -130,7 +138,12 @@ function getHTMLFromAtext(pad, atext, authorColors) // this pad, and if yes puts its attrib id->props value into anumMap props.forEach(function (propName, i) { - var propTrueNum = apool.putAttrib([propName, true], true); + var attrib = [propName, true]; + if (_.isArray(propName)) { + // propName can be in the form of ['color', 'red'] + attrib = propName; + } + var propTrueNum = apool.putAttrib(attrib, true); if (propTrueNum >= 0) { anumMap[propTrueNum] = i; @@ -154,6 +167,11 @@ function getHTMLFromAtext(pad, atext, authorColors) var property = props[i]; + // we are not insterested on properties in the form of ['color', 'red'] + if (_.isArray(property)) { + return false; + } + if(property.substr(0,6) === "author"){ return stripDotFromAuthorID(property); } @@ -165,6 +183,11 @@ function getHTMLFromAtext(pad, atext, authorColors) return false; } + function isSpanWithData(i){ + var property = props[i]; + return _.isArray(property); + } + function emitOpenTag(i) { openTags.unshift(i); @@ -186,8 +209,9 @@ function getHTMLFromAtext(pad, atext, authorColors) { openTags.shift(); var spanClass = getSpanClassFor(i); + var spanWithData = isSpanWithData(i); - if(spanClass){ + if(spanClass || spanWithData){ assem.append(''); } else { assem.append('