415 lines
12 KiB
JavaScript
415 lines
12 KiB
JavaScript
/* global OpenDocument */
|
|
|
|
OpenDocument.StyleManager = function () {
|
|
this.maps = new Map([
|
|
["cell-named", new Map()],
|
|
["row-named", new Map()],
|
|
["cell-automatic", new Map()],
|
|
["column-named", new Map()],
|
|
["column-automatic", new Map()]
|
|
]);
|
|
this.matchingClassMaps = new Map([
|
|
["cell", new Map()],
|
|
["row", new Map()],
|
|
["column", new Map()]
|
|
]);
|
|
for(let object of OpenDocument.StyleManager.DEFAULT_STYLES ) {
|
|
this.putStyle(object.type + "-named", _buildDefault(object));
|
|
}
|
|
this.automaticStyleNumber = 1;
|
|
this.currencyMap = new Map();
|
|
OpenDocument.StyleManager.readDocumentStyleSheets(this);
|
|
|
|
function _buildDefault(object) {
|
|
let style = new OpenDocument.Style(object.type, object.name);
|
|
if (object.parent) {
|
|
style.setParent(object.parent);
|
|
}
|
|
for(let propertyName in object.properties) {
|
|
let stylePropertyDef = OpenDocument.Style.getStylePropertyDef(object.type, propertyName);
|
|
if (stylePropertyDef) {
|
|
style.putStyleProperty(stylePropertyDef, object.properties[propertyName]);
|
|
}
|
|
}
|
|
return style;
|
|
}
|
|
};
|
|
|
|
OpenDocument.StyleManager.prototype.putStyle = function (mapName, style, styleKey) {
|
|
if (!styleKey) {
|
|
styleKey = style.styleName;
|
|
}
|
|
var map = this.maps.get(mapName);
|
|
if (map.has(styleKey)) {
|
|
let existingStyle = map.get(styleKey);
|
|
existingStyle.copyProperties(style);
|
|
} else {
|
|
map.set(styleKey, style);
|
|
}
|
|
};
|
|
|
|
OpenDocument.StyleManager.prototype.hasStyle = function (mapName, styleKey) {
|
|
var map = this.maps.get(mapName);
|
|
if (map) {
|
|
return map.has(styleKey);
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
|
|
OpenDocument.StyleManager.prototype.getStyle = function (mapName, styleKey) {
|
|
var map = this.maps.get(mapName);
|
|
if (map) {
|
|
return map.get(styleKey);
|
|
} else {
|
|
return null;
|
|
}
|
|
return this.map.get(styleKey);
|
|
};
|
|
|
|
OpenDocument.StyleManager.prototype.getAutomaticCellStyleName = function (type, parentStyleName, currencyCode) {
|
|
var styleKey = type + ":";
|
|
if (type === "currency") {
|
|
styleKey += currencyCode + ":";
|
|
}
|
|
styleKey += parentStyleName;
|
|
if (this.hasStyle("cell-automatic", styleKey)) {
|
|
return this.getStyle("cell-automatic", styleKey).styleName;
|
|
}
|
|
var name = OpenDocument.CELLSTYLE_PREFIX + this.automaticStyleNumber;
|
|
this.automaticStyleNumber++;
|
|
var dataStyleName = null;
|
|
switch(type) {
|
|
case "date":
|
|
dataStyleName = OpenDocument.ISODATE_DATASTYLE_NAME;
|
|
break;
|
|
case "currency":
|
|
let number;
|
|
if (this.currencyMap.has(currencyCode)) {
|
|
number = this.currencyMap.get(currencyCode);
|
|
} else {
|
|
number = this.automaticStyleNumber;
|
|
this.automaticStyleNumber++;
|
|
this.currencyMap.set(currencyCode, number);
|
|
}
|
|
dataStyleName = OpenDocument.DATASTYLE_PREFIX + number;
|
|
break;
|
|
}
|
|
var cellStyle = new OpenDocument.Style("cell", name);
|
|
if (parentStyleName) {
|
|
cellStyle.setParent(parentStyleName);
|
|
} else {
|
|
cellStyle.setParent(OpenDocument.DEFAULT_CELLSTYLE_NAME);
|
|
}
|
|
if (dataStyleName) {
|
|
cellStyle.setDataStyle(dataStyleName);
|
|
}
|
|
this.putStyle("cell-automatic", cellStyle, styleKey);
|
|
return name;
|
|
};
|
|
|
|
OpenDocument.StyleManager.prototype.getMatchingStyleName = function (type, element) {
|
|
var map = this.matchingClassMaps.get(type);
|
|
if (map) {
|
|
for(let className of element.classList) {
|
|
if (map.has(className)) {
|
|
return map.get(className);
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
};
|
|
/**
|
|
*
|
|
* @param {OpenDocument.XmlWriter} xmlWriter
|
|
* @returns {undefined}
|
|
*/
|
|
OpenDocument.StyleManager.prototype.writeStyles = function (mapName, xmlWriter) {
|
|
var map = this.maps.get(mapName);
|
|
if (map) {
|
|
for(let style of map.values()) {
|
|
style.write(xmlWriter);
|
|
}
|
|
}
|
|
};
|
|
|
|
OpenDocument.StyleManager.prototype.writeDataStyles = function (xmlWriter) {
|
|
xmlWriter
|
|
.addDateStyle();
|
|
for(let entry of this.currencyMap) {
|
|
xmlWriter
|
|
.addCurrencyStyle(entry[0], entry[1]);
|
|
}
|
|
};
|
|
|
|
OpenDocument.StyleManager.readDocumentStyleSheets = function (styleManager) {
|
|
var styleSheetList = document.styleSheets;
|
|
for(let i = 0, len = styleSheetList.length; i < len; i++) {
|
|
OpenDocument.StyleManager.readStyleSheet(styleManager, styleSheetList[i]);
|
|
}
|
|
};
|
|
|
|
OpenDocument.StyleManager.readStyleSheet = function (styleManager, styleSheet) {
|
|
var ruleList = styleSheet.cssRules;
|
|
for(let i = 0, len = ruleList.length; i < len; i++) {
|
|
let rule = ruleList[i];
|
|
if ((rule.selectorText) && (rule.style)) {
|
|
let selectorArray = _parseSelectorText(rule.selectorText);
|
|
for(let selector of selectorArray) {
|
|
_addStyle(selector, rule.style);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
function _parseSelectorText(selectorText) {
|
|
let resultArray = new Array();
|
|
for(let token of selectorText.split(',')) {
|
|
let result = __parseToken(token);
|
|
if (result) {
|
|
switch(result[0]) {
|
|
case "cell":
|
|
case "row":
|
|
case "column":
|
|
resultArray.push(result);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return resultArray;
|
|
|
|
|
|
function __parseToken(token) {
|
|
token = token.trim();
|
|
let idx = token.indexOf(' ');
|
|
let followingPart = "";
|
|
if (idx !== -1) {
|
|
followingPart = token.substring(idx +1).trim();
|
|
token = token.substring(0, idx);
|
|
}
|
|
let dotIndex = token.indexOf('.');
|
|
if (dotIndex === -1) {
|
|
return null;
|
|
}
|
|
let type = token.substring(0, dotIndex);
|
|
let name = token.substring(dotIndex + 1);
|
|
return [type, name, followingPart];
|
|
}
|
|
}
|
|
|
|
function _addStyle(selector, cssStyleDeclaration) {
|
|
let type = selector[0];
|
|
let style = new OpenDocument.Style(type, selector[1]);
|
|
let borderBuffer = false;
|
|
if (type === "cell") {
|
|
borderBuffer = new OpenDocument.StyleManager.BorderBuffer();
|
|
}
|
|
for(let i = 0, len = cssStyleDeclaration.length; i < len; i++) {
|
|
let propertyName = cssStyleDeclaration[i];
|
|
let propertyValue = cssStyleDeclaration.getPropertyValue(propertyName);
|
|
if (borderBuffer) {
|
|
let borderTest = propertyName.match(/^border-([a-z]+)-([a-z]+)/);
|
|
if (borderTest) {
|
|
borderBuffer.putSubproperty(borderTest[1], borderTest[2], propertyValue);
|
|
continue;
|
|
}
|
|
}
|
|
if (propertyName === "content") {
|
|
__parseDeclarationText(propertyValue);
|
|
} else {
|
|
let stylePropertyDef = OpenDocument.Style.getStylePropertyDef(type, propertyName);
|
|
if (stylePropertyDef) {
|
|
style.putStyleProperty(stylePropertyDef, propertyValue);
|
|
}
|
|
}
|
|
}
|
|
if (borderBuffer) {
|
|
borderBuffer.fillStyle(style);
|
|
}
|
|
_parseFollowingPart(selector[2]);
|
|
styleManager.putStyle(type + "-named", style);
|
|
|
|
function __parseDeclarationText(declarationText) {
|
|
let start = declarationText.indexOf('"');
|
|
if (start === -1) {
|
|
return;
|
|
}
|
|
let end = declarationText.lastIndexOf('"');
|
|
if (end === start) {
|
|
return;
|
|
}
|
|
let tokens = declarationText.substring(start + 1, end).split(';');
|
|
for(let token of tokens) {
|
|
let paire = token.split(':');
|
|
if (paire.length === 2) {
|
|
let name = paire[0].trim();
|
|
let value = paire[1].trim();
|
|
let stylePropertyDef = OpenDocument.Style.getStylePropertyDef(type, name);
|
|
if (stylePropertyDef) {
|
|
style.putStyleProperty(stylePropertyDef, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function _parseFollowingPart(followingPart) {
|
|
if (!followingPart) {
|
|
return;
|
|
}
|
|
let tokens = new Array();
|
|
for(let token of followingPart.split(" ")) {
|
|
token = token.trim();
|
|
if (token.length > 0) {
|
|
tokens.push(token);
|
|
}
|
|
}
|
|
let index = 0;
|
|
let length = tokens.length - 1;
|
|
while(index < length) {
|
|
let operatorToken = tokens[index];
|
|
switch(operatorToken) {
|
|
case '~':
|
|
for(let i = index +1; i <= length; i++) {
|
|
__addMatchingClasses(tokens[i]);
|
|
}
|
|
index = length;
|
|
break;
|
|
case '+':
|
|
__setParent(tokens[index +1]);
|
|
index ++;
|
|
break;
|
|
}
|
|
index ++;
|
|
}
|
|
}
|
|
|
|
function __addMatchingClasses(token) {
|
|
if (!token) {
|
|
return;
|
|
}
|
|
let map = styleManager.matchingClassMaps.get(type);
|
|
if (!map) {
|
|
return;
|
|
}
|
|
if (token.startsWith('.')) {
|
|
map.set(token.substring(1), style.styleName);
|
|
}
|
|
}
|
|
|
|
function __setParent(token) {
|
|
if (!token) {
|
|
return;
|
|
}
|
|
let dotIndex = token.indexOf('.');
|
|
if (dotIndex !== -1) {
|
|
style.setParent(token.substring(dotIndex + 1));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
OpenDocument.StyleManager.BorderBuffer = function () {
|
|
this.map = new Map([
|
|
["bottom", false],
|
|
["left", false],
|
|
["right", false],
|
|
["top", false]
|
|
]);
|
|
};
|
|
|
|
OpenDocument.StyleManager.BorderBuffer.prototype.putSubproperty = function (position, subproperty, value) {
|
|
if (!this.map.has(position)) {
|
|
return;
|
|
}
|
|
let positionObject = this.map.get(position);
|
|
if (!positionObject) {
|
|
positionObject = {
|
|
width: "0.75pt",
|
|
color: "rgb(0, 0, 0)",
|
|
style: "solid"
|
|
};
|
|
this.map.set(position, positionObject);
|
|
}
|
|
if (positionObject.hasOwnProperty(subproperty)) {
|
|
if (subproperty === "color") {
|
|
value = OpenDocument.Style.formatColor(value);
|
|
}
|
|
positionObject[subproperty] = value;
|
|
};
|
|
};
|
|
|
|
OpenDocument.StyleManager.BorderBuffer.prototype.fillStyle = function (style) {
|
|
for(let entry of this.map) {
|
|
let position = entry[0];
|
|
let object = entry[1];
|
|
if (object) {
|
|
let stylePropertyDef = OpenDocument.Style.getStylePropertyDef("type", "border-" + position);
|
|
if (stylePropertyDef) {
|
|
let value = object.width + " " + object.style + " " + object.color;
|
|
style.putStyleProperty(stylePropertyDef, value);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
OpenDocument.StyleManager.DEFAULT_STYLES = [
|
|
{
|
|
type: "cell",
|
|
name: "Standard",
|
|
parent: "",
|
|
properties: {
|
|
}
|
|
},
|
|
{
|
|
type: "cell",
|
|
name: "Bold",
|
|
parent: "Standard",
|
|
properties: {
|
|
"font-weight": "bold"
|
|
}
|
|
},
|
|
{
|
|
type: "cell",
|
|
name: "Italic",
|
|
parent: "Standard",
|
|
properties: {
|
|
"font-weight": "italic"
|
|
}
|
|
},
|
|
{
|
|
type: "cell",
|
|
name: "BoldItalic",
|
|
parent: "Standard",
|
|
properties: {
|
|
"font-weight": "bold",
|
|
"font-style": "italic"
|
|
}
|
|
},
|
|
{
|
|
type: "cell",
|
|
name: "Header",
|
|
properties: {
|
|
"font-weight": "bold",
|
|
"text-align": "center",
|
|
"vertical-align": "middle"
|
|
}
|
|
},
|
|
{
|
|
type: "row",
|
|
name: "Standard",
|
|
parent: "",
|
|
properties: {
|
|
}
|
|
},
|
|
{
|
|
type: "row",
|
|
name: "Header",
|
|
parent: "",
|
|
properties: {
|
|
}
|
|
}
|
|
];
|