102 lines
3.0 KiB
JavaScript
102 lines
3.0 KiB
JavaScript
exports.readStylesXml = readStylesXml;
|
|
exports.Styles = Styles;
|
|
exports.defaultStyles = new Styles({}, {});
|
|
|
|
function Styles(paragraphStyles, characterStyles, tableStyles, numberingStyles) {
|
|
return {
|
|
findParagraphStyleById: function(styleId) {
|
|
return paragraphStyles[styleId];
|
|
},
|
|
findCharacterStyleById: function(styleId) {
|
|
return characterStyles[styleId];
|
|
},
|
|
findTableStyleById: function(styleId) {
|
|
return tableStyles[styleId];
|
|
},
|
|
findNumberingStyleById: function(styleId) {
|
|
return numberingStyles[styleId];
|
|
}
|
|
};
|
|
}
|
|
|
|
Styles.EMPTY = new Styles({}, {}, {}, {});
|
|
|
|
function readStylesXml(root) {
|
|
var paragraphStyles = Object.create(null);
|
|
var characterStyles = Object.create(null);
|
|
var tableStyles = Object.create(null);
|
|
var numberingStyles = Object.create(null);
|
|
|
|
root.getElementsByTagName("w:style").forEach(function(styleElement) {
|
|
var style = readStyleElement(styleElement);
|
|
var styleSet;
|
|
|
|
switch (style.type) {
|
|
case "paragraph":
|
|
styleSet = paragraphStyles;
|
|
break;
|
|
|
|
case "character":
|
|
styleSet = characterStyles;
|
|
break;
|
|
|
|
case "table":
|
|
styleSet = tableStyles;
|
|
break;
|
|
|
|
case "numbering":
|
|
styleSet = numberingStyles;
|
|
break;
|
|
}
|
|
|
|
// Per 17.7.4.17 style (Style Definition) of ECMA-376 4th edition Part 1:
|
|
//
|
|
// > If multiple style definitions each declare the same value for their
|
|
// > styleId, then the first such instance shall keep its current
|
|
// > identifier with all other instances being reassigned in any manner
|
|
// > desired.
|
|
//
|
|
// For the purpose of conversion, there's no point holding onto styles
|
|
// with reassigned style IDs, so we ignore such style definitions.
|
|
|
|
if (styleSet && styleSet[style.styleId] === undefined) {
|
|
styleSet[style.styleId] = style;
|
|
}
|
|
});
|
|
|
|
return new Styles(paragraphStyles, characterStyles, tableStyles, numberingStyles);
|
|
}
|
|
|
|
function readStyleElement(styleElement) {
|
|
var type = styleElement.attributes["w:type"];
|
|
|
|
if (type === "numbering") {
|
|
return readNumberingStyleElement(type, styleElement);
|
|
} else {
|
|
var styleId = readStyleId(styleElement);
|
|
var name = styleName(styleElement);
|
|
return {type: type, styleId: styleId, name: name};
|
|
}
|
|
}
|
|
|
|
function styleName(styleElement) {
|
|
var nameElement = styleElement.first("w:name");
|
|
return nameElement ? nameElement.attributes["w:val"] : null;
|
|
}
|
|
|
|
function readNumberingStyleElement(type, styleElement) {
|
|
var styleId = readStyleId(styleElement);
|
|
|
|
var numId = styleElement
|
|
.firstOrEmpty("w:pPr")
|
|
.firstOrEmpty("w:numPr")
|
|
.firstOrEmpty("w:numId")
|
|
.attributes["w:val"];
|
|
|
|
return {type: type, numId: numId, styleId: styleId};
|
|
}
|
|
|
|
function readStyleId(styleElement) {
|
|
return styleElement.attributes["w:styleId"];
|
|
}
|