forked from sheetjs/sheetjs
		
	explicitly share styles and themes
This commit is contained in:
		
							parent
							
								
									5a3774e36e
								
							
						
					
					
						commit
						7888070603
					
				| @ -113,7 +113,6 @@ var parse_rs = (function parse_rs_factory() { | ||||
| 					if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0]; | ||||
| 			} | ||||
| 		} | ||||
| 		/* TODO: These should be generated styles, not inline */ | ||||
| 		var style = []; | ||||
| 		if(font.b) style.push("font-weight: bold;"); | ||||
| 		if(font.i) style.push("font-style: italic;"); | ||||
|  | ||||
| @ -1,4 +0,0 @@ | ||||
| var styles = {}; // shared styles
 | ||||
| 
 | ||||
| var themes = {}; // shared themes
 | ||||
| 
 | ||||
| @ -1,5 +1,5 @@ | ||||
| /* 18.8.21 fills CT_Fills */ | ||||
| function parse_fills(t, opts) { | ||||
| function parse_fills(t, styles, opts) { | ||||
| 	styles.Fills = []; | ||||
| 	var fill = {}; | ||||
| 	t[0].match(tagregex).forEach(function(x) { | ||||
| @ -39,13 +39,13 @@ function parse_fills(t, opts) { | ||||
| 				break; | ||||
| 			case '<fgColor/>': case '</fgColor>': break; | ||||
| 
 | ||||
| 			default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills'); | ||||
| 			default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills'); | ||||
| 		} | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| /* 18.8.31 numFmts CT_NumFmts */ | ||||
| function parse_numFmts(t, opts) { | ||||
| function parse_numFmts(t, styles, opts) { | ||||
| 	styles.NumberFmt = []; | ||||
| 	var k/*Array<number>*/ = (keys(SSF._table)/*:any*/); | ||||
| 	for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]]; | ||||
| @ -77,7 +77,7 @@ function write_numFmts(NF/*:{[n:number]:string}*/, opts) { | ||||
| } | ||||
| 
 | ||||
| /* 18.8.10 cellXfs CT_CellXfs */ | ||||
| function parse_cellXfs(t, opts) { | ||||
| function parse_cellXfs(t, styles, opts) { | ||||
| 	styles.CellXf = []; | ||||
| 	t[0].match(tagregex).forEach(function(x) { | ||||
| 		var y = parsexmltag(x); | ||||
| @ -121,24 +121,25 @@ var cellXfRegex = /<cellXfs([^>]*)>.*<\/cellXfs>/; | ||||
| var fillsRegex = /<fills([^>]*)>.*<\/fills>/; | ||||
| 
 | ||||
| return function parse_sty_xml(data, opts) { | ||||
| 	var styles = {}; | ||||
| 	if(!data) return styles; | ||||
| 	/* 18.8.39 styleSheet CT_Stylesheet */ | ||||
| 	var t; | ||||
| 
 | ||||
| 	/* numFmts CT_NumFmts ? */ | ||||
| 	if((t=data.match(numFmtRegex))) parse_numFmts(t, opts); | ||||
| 	if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts); | ||||
| 
 | ||||
| 	/* fonts CT_Fonts ? */ | ||||
| 	/*if((t=data.match(/<fonts([^>]*)>.*<\/fonts>/))) parse_fonts(t, opts);*/ | ||||
| 
 | ||||
| 	/* fills CT_Fills */ | ||||
| 	if((t=data.match(fillsRegex))) parse_fills(t, opts); | ||||
| 	if((t=data.match(fillsRegex))) parse_fills(t, styles, opts); | ||||
| 
 | ||||
| 	/* borders CT_Borders ? */ | ||||
| 	/* cellStyleXfs CT_CellStyleXfs ? */ | ||||
| 
 | ||||
| 	/* cellXfs CT_CellXfs ? */ | ||||
| 	if((t=data.match(cellXfRegex))) parse_cellXfs(t, opts); | ||||
| 	if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts); | ||||
| 
 | ||||
| 	/* dxfs CT_Dxfs ? */ | ||||
| 	/* tableStyles CT_TableStyles ? */ | ||||
|  | ||||
| @ -42,6 +42,7 @@ function parse_BrtXF(data, length/*:number*/) { | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.50 Styles */ | ||||
| function parse_sty_bin(data, opts) { | ||||
| 	var styles = {}; | ||||
| 	styles.NumberFmt = ([]/*:any*/); | ||||
| 	for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y]; | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"; | ||||
| 
 | ||||
| /* 20.1.6.2 clrScheme CT_ColorScheme */ | ||||
| function parse_clrScheme(t, opts) { | ||||
| function parse_clrScheme(t, themes, opts) { | ||||
| 	themes.themeElements.clrScheme = []; | ||||
| 	var color = {}; | ||||
| 	(t[0].match(tagregex)||[]).forEach(function(x) { | ||||
| @ -59,23 +59,23 @@ function parse_clrScheme(t, opts) { | ||||
| 				} | ||||
| 				break; | ||||
| 
 | ||||
| 			default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in clrScheme'; | ||||
| 			default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme'); | ||||
| 		} | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| /* 20.1.4.1.18 fontScheme CT_FontScheme */ | ||||
| function parse_fontScheme(t, opts) { } | ||||
| function parse_fontScheme(t, themes, opts) { } | ||||
| 
 | ||||
| /* 20.1.4.1.15 fmtScheme CT_StyleMatrix */ | ||||
| function parse_fmtScheme(t, opts) { } | ||||
| function parse_fmtScheme(t, themes, opts) { } | ||||
| 
 | ||||
| var clrsregex = /<a:clrScheme([^>]*)>[^\u2603]*<\/a:clrScheme>/; | ||||
| var fntsregex = /<a:fontScheme([^>]*)>[^\u2603]*<\/a:fontScheme>/; | ||||
| var fmtsregex = /<a:fmtScheme([^>]*)>[^\u2603]*<\/a:fmtScheme>/; | ||||
| 
 | ||||
| /* 20.1.6.10 themeElements CT_BaseStyles */ | ||||
| function parse_themeElements(data, opts) { | ||||
| function parse_themeElements(data, themes, opts) { | ||||
| 	themes.themeElements = {}; | ||||
| 
 | ||||
| 	var t; | ||||
| @ -89,7 +89,7 @@ function parse_themeElements(data, opts) { | ||||
| 		['fmtScheme', fmtsregex, parse_fmtScheme] | ||||
| 	].forEach(function(m) { | ||||
| 		if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements'); | ||||
| 		m[2](t, opts); | ||||
| 		m[2](t, themes, opts); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| @ -98,18 +98,19 @@ var themeltregex = /<a:themeElements([^>]*)>[^\u2603]*<\/a:themeElements>/; | ||||
| /* 14.2.7 Theme Part */ | ||||
| function parse_theme_xml(data/*:string*/, opts) { | ||||
| 	/* 20.1.6.9 theme CT_OfficeStyleSheet */ | ||||
| 	if(!data || data.length === 0) return themes; | ||||
| 	if(!data || data.length === 0) return parse_theme_xml(write_theme()); | ||||
| 
 | ||||
| 	var t; | ||||
| 	var themes = {}; | ||||
| 
 | ||||
| 	/* themeElements CT_BaseStyles */ | ||||
| 	if(!(t=data.match(themeltregex))) throw 'themeElements not found in theme'; | ||||
| 	parse_themeElements(t[0], opts); | ||||
| 	parse_themeElements(t[0], themes, opts); | ||||
| 
 | ||||
| 	return themes; | ||||
| } | ||||
| 
 | ||||
| function write_theme() { | ||||
| function write_theme(Themes, opts)/*:string*/ { | ||||
| 	var o = [XML_HEADER]; | ||||
| 	o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">'; | ||||
| 	o[o.length] =  '<a:themeElements>'; | ||||
| @ -264,15 +265,15 @@ function write_theme() { | ||||
| 	o[o.length] =     '</a:gradFill>'; | ||||
| 	o[o.length] =    '</a:bgFillStyleLst>'; | ||||
| 	o[o.length] =   '</a:fmtScheme>'; | ||||
| 
 | ||||
| 	o[o.length] =  '</a:themeElements>'; | ||||
| 
 | ||||
| 	o[o.length] =  '<a:objectDefaults>'; | ||||
| 	o[o.length] =   '<a:spDef>'; | ||||
| 	o[o.length] =    '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="1"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef></a:style>'; | ||||
| 	o[o.length] =   '</a:spDef>'; | ||||
| 	o[o.length] =   '<a:lnDef>'; | ||||
| 	o[o.length] =    '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style>'; | ||||
| 	o[o.length] =     '</a:lnDef>'; | ||||
| 	o[o.length] =   '</a:lnDef>'; | ||||
| 	o[o.length] =  '</a:objectDefaults>'; | ||||
| 	o[o.length] =  '<a:extraClrSchemeLst/>'; | ||||
| 	o[o.length] = '</a:theme>'; | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* [MS-XLS] 2.4.326 TODO: payload is a zip file */ | ||||
| function parse_Theme(blob, length) { | ||||
| function parse_Theme(blob, length, opts) { | ||||
| 	var dwThemeVersion = blob.read_shift(4); | ||||
| 	if(dwThemeVersion === 124226) return; | ||||
| 	blob.l += length-4; | ||||
|  | ||||
| @ -22,7 +22,7 @@ function get_cell_style(styles, cell, opts) { | ||||
| 	return len; | ||||
| } | ||||
| 
 | ||||
| function safe_format(p, fmtid, fillid, opts) { | ||||
| function safe_format(p, fmtid, fillid, opts, themes, styles) { | ||||
| 	if(p.t === 'z') return; | ||||
| 	if(p.t === 'd' && typeof p.v === 'string') p.v = new Date(p.v); | ||||
| 	try { | ||||
|  | ||||
| @ -8,7 +8,7 @@ var hlinkregex = /<(?:\w*:)?hyperlink[^>]*\/>/g; | ||||
| var dimregex = /"(\w*:\w*)"/; | ||||
| var colregex = /<(?:\w*:)?col[^>]*\/>/g; | ||||
| /* 18.3 Worksheets */ | ||||
| function parse_ws_xml(data/*:?string*/, opts, rels)/*:Worksheet*/ { | ||||
| function parse_ws_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| 	if(!data) return data; | ||||
| 	/* 18.3.1.99 worksheet CT_Worksheet */ | ||||
| 	var s = ({}/*:any*/); | ||||
| @ -39,7 +39,7 @@ function parse_ws_xml(data/*:?string*/, opts, rels)/*:Worksheet*/ { | ||||
| 
 | ||||
| 	/* 18.3.1.80 sheetData CT_SheetData ? */ | ||||
| 	var mtch=data.match(sheetdataregex); | ||||
| 	if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess); | ||||
| 	if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles); | ||||
| 
 | ||||
| 	/* 18.3.1.48 hyperlinks CT_Hyperlinks */ | ||||
| 	var hlink = data.match(hlinkregex); | ||||
| @ -173,7 +173,7 @@ var parse_ws_xml_data = (function parse_ws_xml_data_factory() { | ||||
| 	var refregex = /ref=["']([^"']*)["']/; | ||||
| 	var match_v = matchtag("v"), match_f = matchtag("f"); | ||||
| 
 | ||||
| return function parse_ws_xml_data(sdata, s, opts, guess) { | ||||
| return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 	var ri = 0, x = "", cells = [], cref = [], idx = 0, i=0, cc=0, d="", p/*:any*/; | ||||
| 	var tag, tagr = 0, tagc = 0; | ||||
| 	var sstr, ftag; | ||||
| @ -288,7 +288,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) { | ||||
| 					if(opts.cellStyles && cf.fillId != null) fillid = cf.fillId; | ||||
| 				} | ||||
| 			} | ||||
| 			safe_format(p, fmtid, fillid, opts); | ||||
| 			safe_format(p, fmtid, fillid, opts, themes, styles); | ||||
| 			s[tag.r] = p; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -256,7 +256,7 @@ function parse_BrtShrFmla(data, length, opts) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.61 Worksheet */ | ||||
| function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ { | ||||
| function parse_ws_bin(data, opts, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| 	if(!data) return data; | ||||
| 	if(!rels) rels = {'!id':{}}; | ||||
| 	var s = {}; | ||||
| @ -311,7 +311,7 @@ function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ { | ||||
| 					case 'e': p.v = val[1]; p.w = BErr[p.v]; break; | ||||
| 					case 'str': p.t = 's'; p.v = utf8read(val[1]); break; | ||||
| 				} | ||||
| 				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts); | ||||
| 				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles); | ||||
| 				s[encode_col(C=val[0].c) + rr] = p; | ||||
| 				if(opts.cellFormula) { | ||||
| 					af = false; | ||||
|  | ||||
| @ -3,9 +3,9 @@ function parse_wb(data, name/*:string*/, opts)/*:WorkbookFile*/ { | ||||
| 	return parse_wb_xml((data/*:any*/), opts); | ||||
| } | ||||
| 
 | ||||
| function parse_ws(data, name/*:string*/, opts, rels, wb)/*:Worksheet*/ { | ||||
| 	if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb); | ||||
| 	return parse_ws_xml((data/*:any*/), opts, rels, wb); | ||||
| function parse_ws(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| 	if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb, themes, styles); | ||||
| 	return parse_ws_xml((data/*:any*/), opts, rels, wb, themes, styles); | ||||
| } | ||||
| 
 | ||||
| function parse_sty(data, name/*:string*/, opts) { | ||||
|  | ||||
| @ -149,7 +149,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		biff: 8, // BIFF version
 | ||||
| 		codepage: 0, // CP from CodePage record
 | ||||
| 		winlocked: 0, // fLockWn from WinProtect
 | ||||
| 		wtf: false | ||||
| 		WTF: !!options && !!options.wtf | ||||
| 	}/*:any*/); | ||||
| 	if(options.password) opts.password = options.password; | ||||
| 	var mergecells = []; | ||||
|  | ||||
| @ -35,6 +35,7 @@ var parse_content_xml = (function() { | ||||
| 		var rept = 1, isstub = false; | ||||
| 		var i = 0; | ||||
| 		xlmlregex.lastIndex = 0; | ||||
| 		str = str.replace(/<!--([^\u2603]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,""); | ||||
| 		while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) { | ||||
| 
 | ||||
| 			case 'table': case '工作表': // 9.1.2 <table:table>
 | ||||
| @ -388,7 +389,7 @@ var parse_content_xml = (function() { | ||||
| 				if(Rn[2] === 'uof:') break; // TODO: uof
 | ||||
| 				if(Rn[2] === '表:') break; // TODO: uof
 | ||||
| 				if(Rn[2] === '字:') break; // TODO: uof
 | ||||
| 				if(opts.WTF) throw Rn; | ||||
| 				if(opts.WTF) throw new Error(Rn); | ||||
| 		} | ||||
| 		var out = { | ||||
| 			Sheets: Sheets, | ||||
|  | ||||
| @ -6,10 +6,10 @@ function safe_parse_wbrels(wbrels, sheets) { | ||||
| 	return !wbrels || wbrels.length === 0 ? null : wbrels; | ||||
| } | ||||
| 
 | ||||
| function safe_parse_ws(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, opts, wb) { | ||||
| function safe_parse_ws(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, opts, wb, themes, styles) { | ||||
| 	try { | ||||
| 		sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path); | ||||
| 		sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb); | ||||
| 		sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb, themes, styles); | ||||
| 	} catch(e) { if(opts.WTF) throw e; } | ||||
| } | ||||
| 
 | ||||
| @ -42,14 +42,14 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 	if(dir.workbooks[0].slice(-3) == "bin") xlsb = true; | ||||
| 	if(xlsb) set_cp(1200); | ||||
| 
 | ||||
| 	var themes = ({}/*:any*/); | ||||
| 	var styles = ({}/*:any*/); | ||||
| 	if(!opts.bookSheets && !opts.bookProps) { | ||||
| 		strs = []; | ||||
| 		if(dir.sst) strs=parse_sst(getzipdata(zip, dir.sst.replace(/^\//,'')), dir.sst, opts); | ||||
| 
 | ||||
| 		styles = {}; | ||||
| 		if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts); | ||||
| 
 | ||||
| 		themes = {}; | ||||
| 		if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts); | ||||
| 	} | ||||
| 
 | ||||
| @ -112,7 +112,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 			path = path.replace(/sheet0\./,"sheet."); | ||||
| 		} | ||||
| 		relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels"); | ||||
| 		safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb); | ||||
| 		safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb, themes, styles); | ||||
| 	} | ||||
| 
 | ||||
| 	if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts); | ||||
|  | ||||
| @ -78,7 +78,7 @@ function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ { | ||||
| 	/* TODO: something more intelligent with themes */ | ||||
| 
 | ||||
| 	f = "xl/theme/theme1.xml"; | ||||
| 	zip.file(f, write_theme()); | ||||
| 	zip.file(f, write_theme(wb.Themes, opts)); | ||||
| 	ct.themes.push(f); | ||||
| 	add_rels(opts.wbrels, ++rId, "theme/theme1.xml", RELS.THEME); | ||||
| 
 | ||||
|  | ||||
| @ -15,6 +15,7 @@ type Workbook = { | ||||
| 
 | ||||
| 	Props?: any; | ||||
| 	Custprops?: any; | ||||
| 	Themes?: any; | ||||
| 
 | ||||
| 	SSF?: {[n:number]:string}; | ||||
| 	cfb?: any; | ||||
|  | ||||
							
								
								
									
										6
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										6
									
								
								test.js
									
									
									
									
									
								
							| @ -601,7 +601,7 @@ function diffsty(ws, r1,r2) { | ||||
| } | ||||
| 
 | ||||
| describe('parse features', function() { | ||||
| 	it('should have comment as part of cell properties', function(){ | ||||
| 	if(fs.existsSync(paths.swcxlsx)) it('should have comment as part of cell properties', function(){ | ||||
| 		var X = require(modp); | ||||
| 		var sheet = 'Sheet1'; | ||||
| 		var wb1=X.readFile(paths.swcxlsx); | ||||
| @ -620,7 +620,7 @@ describe('parse features', function() { | ||||
| 	}); | ||||
| 
 | ||||
| 	describe('should parse core properties and custom properties', function() { | ||||
| 		var wb1, wb2; | ||||
| 		var wb1, wb2, wb3, wb4; | ||||
| 		var bef = (function() { | ||||
| 			wb1 = X.readFile(paths.cpxlsx); | ||||
| 			wb2 = X.readFile(paths.cpxlsb); | ||||
| @ -1142,7 +1142,7 @@ describe('corner cases', function() { | ||||
| 			["foo","bar",new Date("2014-02-19T14:30Z"), "0.3"], | ||||
| 			["baz", null, "q\"ux"] | ||||
| 		]; | ||||
| 		ws = sheet_from_array_of_arrays(data); | ||||
| 		var ws = sheet_from_array_of_arrays(data); | ||||
| 		ws.A1.f = ""; ws.A1.w = ""; | ||||
| 		delete ws.C3.w; delete ws.C3.z; ws.C3.XF = {ifmt:14}; | ||||
| 		ws.A4.t = "e"; | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| Subproject commit e0b7060b10ef972ad48869faa4efffd089e1a428 | ||||
| Subproject commit 664ad78895cb8dad33e8e993614555baf7d999ae | ||||
							
								
								
									
										106
									
								
								tests.lst
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										106
									
								
								tests.lst
									
									
									
									
									
								
							| @ -353,8 +353,8 @@ openpyxl_r_null_file.xlsx.pending | ||||
| phonetic_text.xlsx | ||||
| pivot_table_named_range.xlsx | ||||
| rich_text_stress.xlsx | ||||
| roo-xls_numbers1.xlsx | ||||
| roo-xls_type_excel.xlsx | ||||
| roo_numbers1.xlsx | ||||
| # roo_type_excel.xlsx # incorrect baseline | ||||
| roo_1900_base.xlsx | ||||
| roo_1904_base.xlsx | ||||
| roo_Bibelbund.xlsx | ||||
| @ -538,8 +538,8 @@ formula_stress_test.ods | ||||
| merge_cells.ods | ||||
| number_format.ods | ||||
| rich_text_stress.ods | ||||
| roo-xls_numbers1.ods | ||||
| roo-xls_type_excel.ods | ||||
| roo_numbers1.ods | ||||
| roo_type_excel.ods | ||||
| roo_Bibelbund.ods | ||||
| roo_Bibelbund1.ods | ||||
| roo_advanced_header.ods | ||||
| @ -1193,34 +1193,34 @@ pyExcelerator_mini-mini.xls | ||||
| pyExcelerator_mini.xls | ||||
| pyExcelerator_oo14.xls | ||||
| rich_text_stress.xls | ||||
| roo-xls_1900_base.xls | ||||
| roo-xls_1904_base.xls | ||||
| roo-xls_Bibelbund.xls | ||||
| roo-xls_bad_excel_date.xls | ||||
| roo-xls_bbu.xls | ||||
| roo-xls_boolean.xls | ||||
| roo-xls_borders.xls | ||||
| roo-xls_bug-row-column-fixnum-float.xls | ||||
| roo-xls_comments.xls | ||||
| roo-xls_datetime.xls | ||||
| roo-xls_datetime_floatconv.xls | ||||
| roo-xls_emptysheets.xls | ||||
| roo-xls_false_encoding.xls | ||||
| roo-xls_formula.xls | ||||
| roo-xls_formula_parse_error.xls | ||||
| roo-xls_link.xls | ||||
| roo-xls_matrix.xls | ||||
| roo-xls_named_cells.xls | ||||
| roo-xls_numbers1.xls | ||||
| roo-xls_only_one_sheet.xls | ||||
| roo-xls_paragraph.xls | ||||
| roo-xls_prova.xls | ||||
| roo-xls_simple_spreadsheet.xls | ||||
| roo-xls_simple_spreadsheet_from_italo.xls | ||||
| roo-xls_style.xls | ||||
| roo-xls_time-test.xls | ||||
| roo-xls_type_excelx.xls | ||||
| roo-xls_type_openoffice.xls | ||||
| roo_1900_base.xls | ||||
| roo_1904_base.xls | ||||
| roo_Bibelbund.xls | ||||
| roo_bad_excel_date.xls | ||||
| roo_bbu.xls | ||||
| roo_boolean.xls | ||||
| roo_borders.xls | ||||
| roo_bug-row-column-fixnum-float.xls | ||||
| roo_comments.xls | ||||
| roo_datetime.xls | ||||
| roo_datetime_floatconv.xls | ||||
| roo_emptysheets.xls | ||||
| roo_false_encoding.xls | ||||
| roo_formula.xls | ||||
| roo_formula_parse_error.xls | ||||
| roo_link.xls | ||||
| roo_matrix.xls | ||||
| roo_named_cells.xls | ||||
| roo_numbers1.xls | ||||
| roo_only_one_sheet.xls | ||||
| roo_paragraph.xls | ||||
| roo_prova.xls | ||||
| roo_simple_spreadsheet.xls | ||||
| roo_simple_spreadsheet_from_italo.xls | ||||
| roo_style.xls | ||||
| roo_time-test.xls | ||||
| roo_type_excelx.xls | ||||
| # roo_type_openoffice.xls # incorrect baseline | ||||
| roo_whitespace.xls | ||||
| smart_tags_2007.xls | ||||
| sushi.xls | ||||
| @ -1300,27 +1300,27 @@ protect_stress_test_xml.xml | ||||
| rich_text_stress.xls.xml | ||||
| rich_text_stress.xlsb.xml | ||||
| rich_text_stress.xlsx.xml | ||||
| roo-xls_Bibelbund.xml | ||||
| roo-xls_bbu.xml | ||||
| roo-xls_boolean.xml | ||||
| roo-xls_borders.xml | ||||
| roo-xls_bug-row-column-fixnum-float.xml | ||||
| roo-xls_datetime.xml | ||||
| roo-xls_datetime_floatconv.xml | ||||
| roo-xls_emptysheets.xml | ||||
| roo-xls_excel2003.xml | ||||
| roo-xls_excel2003_namespace.xml | ||||
| roo-xls_false_encoding.xml | ||||
| roo-xls_formula.xml | ||||
| roo-xls_formula_parse_error.xml | ||||
| roo-xls_numbers1.xml | ||||
| roo-xls_only_one_sheet.xml | ||||
| roo-xls_paragraph.xml | ||||
| roo-xls_simple_spreadsheet.xml | ||||
| roo-xls_simple_spreadsheet_from_italo.xml | ||||
| roo-xls_style.xml | ||||
| roo-xls_time-test.xml | ||||
| roo-xls_whitespace.xml | ||||
| roo_Bibelbund.xml | ||||
| # roo_bbu.xml # SSF TODO | ||||
| # roo_boolean.xml # SSF TODO | ||||
| roo_borders.xml | ||||
| roo_bug-row-column-fixnum-float.xml | ||||
| # roo_datetime.xml # SSF TODO | ||||
| # roo_datetime_floatconv.xml # SSF TODO | ||||
| roo_emptysheets.xml | ||||
| # roo_excel2003.xml # SSF TODO | ||||
| roo_excel2003_namespace.xml | ||||
| # roo_false_encoding.xml # SSF TODO | ||||
| roo_formula.xml | ||||
| roo_formula_parse_error.xml | ||||
| # roo_numbers1.xml # SSF TODO | ||||
| roo_only_one_sheet.xml | ||||
| roo_paragraph.xml | ||||
| # roo_simple_spreadsheet.xml # SSF TODO | ||||
| # roo_simple_spreadsheet_from_italo.xml # SSF TODO | ||||
| roo_style.xml | ||||
| # roo_time-test.xml # SSF TODO | ||||
| # roo_whitespace.xml # SSF TODO | ||||
| # roo_sheet1.xml | ||||
| smart_tags_2007.xml | ||||
| sushi.xml | ||||
|  | ||||
							
								
								
									
										83
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										83
									
								
								xlsx.flow.js
									
									
									
									
									
								
							| @ -4666,7 +4666,6 @@ var parse_rs = (function parse_rs_factory() { | ||||
| 					if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0]; | ||||
| 			} | ||||
| 		} | ||||
| 		/* TODO: These should be generated styles, not inline */ | ||||
| 		var style = []; | ||||
| 		if(font.b) style.push("font-weight: bold;"); | ||||
| 		if(font.i) style.push("font-style: italic;"); | ||||
| @ -5072,12 +5071,8 @@ var XLMLPatternTypeMap = { | ||||
| 	"ThinHorzCross": "lightGrid" | ||||
| }; | ||||
| 
 | ||||
| var styles = {}; // shared styles
 | ||||
| 
 | ||||
| var themes = {}; // shared themes
 | ||||
| 
 | ||||
| /* 18.8.21 fills CT_Fills */ | ||||
| function parse_fills(t, opts) { | ||||
| function parse_fills(t, styles, opts) { | ||||
| 	styles.Fills = []; | ||||
| 	var fill = {}; | ||||
| 	t[0].match(tagregex).forEach(function(x) { | ||||
| @ -5117,13 +5112,13 @@ function parse_fills(t, opts) { | ||||
| 				break; | ||||
| 			case '<fgColor/>': case '</fgColor>': break; | ||||
| 
 | ||||
| 			default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills'); | ||||
| 			default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills'); | ||||
| 		} | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| /* 18.8.31 numFmts CT_NumFmts */ | ||||
| function parse_numFmts(t, opts) { | ||||
| function parse_numFmts(t, styles, opts) { | ||||
| 	styles.NumberFmt = []; | ||||
| 	var k/*Array<number>*/ = (keys(SSF._table)/*:any*/); | ||||
| 	for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]]; | ||||
| @ -5155,7 +5150,7 @@ function write_numFmts(NF/*:{[n:number]:string}*/, opts) { | ||||
| } | ||||
| 
 | ||||
| /* 18.8.10 cellXfs CT_CellXfs */ | ||||
| function parse_cellXfs(t, opts) { | ||||
| function parse_cellXfs(t, styles, opts) { | ||||
| 	styles.CellXf = []; | ||||
| 	t[0].match(tagregex).forEach(function(x) { | ||||
| 		var y = parsexmltag(x); | ||||
| @ -5199,24 +5194,25 @@ var cellXfRegex = /<cellXfs([^>]*)>.*<\/cellXfs>/; | ||||
| var fillsRegex = /<fills([^>]*)>.*<\/fills>/; | ||||
| 
 | ||||
| return function parse_sty_xml(data, opts) { | ||||
| 	var styles = {}; | ||||
| 	if(!data) return styles; | ||||
| 	/* 18.8.39 styleSheet CT_Stylesheet */ | ||||
| 	var t; | ||||
| 
 | ||||
| 	/* numFmts CT_NumFmts ? */ | ||||
| 	if((t=data.match(numFmtRegex))) parse_numFmts(t, opts); | ||||
| 	if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts); | ||||
| 
 | ||||
| 	/* fonts CT_Fonts ? */ | ||||
| 	/*if((t=data.match(/<fonts([^>]*)>.*<\/fonts>/))) parse_fonts(t, opts);*/ | ||||
| 
 | ||||
| 	/* fills CT_Fills */ | ||||
| 	if((t=data.match(fillsRegex))) parse_fills(t, opts); | ||||
| 	if((t=data.match(fillsRegex))) parse_fills(t, styles, opts); | ||||
| 
 | ||||
| 	/* borders CT_Borders ? */ | ||||
| 	/* cellStyleXfs CT_CellStyleXfs ? */ | ||||
| 
 | ||||
| 	/* cellXfs CT_CellXfs ? */ | ||||
| 	if((t=data.match(cellXfRegex))) parse_cellXfs(t, opts); | ||||
| 	if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts); | ||||
| 
 | ||||
| 	/* dxfs CT_Dxfs ? */ | ||||
| 	/* tableStyles CT_TableStyles ? */ | ||||
| @ -5293,6 +5289,7 @@ function parse_BrtXF(data, length/*:number*/) { | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.50 Styles */ | ||||
| function parse_sty_bin(data, opts) { | ||||
| 	var styles = {}; | ||||
| 	styles.NumberFmt = ([]/*:any*/); | ||||
| 	for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y]; | ||||
| 
 | ||||
| @ -5385,7 +5382,7 @@ function write_sty_bin(data, opts) { | ||||
| RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"; | ||||
| 
 | ||||
| /* 20.1.6.2 clrScheme CT_ColorScheme */ | ||||
| function parse_clrScheme(t, opts) { | ||||
| function parse_clrScheme(t, themes, opts) { | ||||
| 	themes.themeElements.clrScheme = []; | ||||
| 	var color = {}; | ||||
| 	(t[0].match(tagregex)||[]).forEach(function(x) { | ||||
| @ -5443,23 +5440,23 @@ function parse_clrScheme(t, opts) { | ||||
| 				} | ||||
| 				break; | ||||
| 
 | ||||
| 			default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in clrScheme'; | ||||
| 			default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme'); | ||||
| 		} | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| /* 20.1.4.1.18 fontScheme CT_FontScheme */ | ||||
| function parse_fontScheme(t, opts) { } | ||||
| function parse_fontScheme(t, themes, opts) { } | ||||
| 
 | ||||
| /* 20.1.4.1.15 fmtScheme CT_StyleMatrix */ | ||||
| function parse_fmtScheme(t, opts) { } | ||||
| function parse_fmtScheme(t, themes, opts) { } | ||||
| 
 | ||||
| var clrsregex = /<a:clrScheme([^>]*)>[^\u2603]*<\/a:clrScheme>/; | ||||
| var fntsregex = /<a:fontScheme([^>]*)>[^\u2603]*<\/a:fontScheme>/; | ||||
| var fmtsregex = /<a:fmtScheme([^>]*)>[^\u2603]*<\/a:fmtScheme>/; | ||||
| 
 | ||||
| /* 20.1.6.10 themeElements CT_BaseStyles */ | ||||
| function parse_themeElements(data, opts) { | ||||
| function parse_themeElements(data, themes, opts) { | ||||
| 	themes.themeElements = {}; | ||||
| 
 | ||||
| 	var t; | ||||
| @ -5473,7 +5470,7 @@ function parse_themeElements(data, opts) { | ||||
| 		['fmtScheme', fmtsregex, parse_fmtScheme] | ||||
| 	].forEach(function(m) { | ||||
| 		if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements'); | ||||
| 		m[2](t, opts); | ||||
| 		m[2](t, themes, opts); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| @ -5482,18 +5479,19 @@ var themeltregex = /<a:themeElements([^>]*)>[^\u2603]*<\/a:themeElements>/; | ||||
| /* 14.2.7 Theme Part */ | ||||
| function parse_theme_xml(data/*:string*/, opts) { | ||||
| 	/* 20.1.6.9 theme CT_OfficeStyleSheet */ | ||||
| 	if(!data || data.length === 0) return themes; | ||||
| 	if(!data || data.length === 0) return parse_theme_xml(write_theme()); | ||||
| 
 | ||||
| 	var t; | ||||
| 	var themes = {}; | ||||
| 
 | ||||
| 	/* themeElements CT_BaseStyles */ | ||||
| 	if(!(t=data.match(themeltregex))) throw 'themeElements not found in theme'; | ||||
| 	parse_themeElements(t[0], opts); | ||||
| 	parse_themeElements(t[0], themes, opts); | ||||
| 
 | ||||
| 	return themes; | ||||
| } | ||||
| 
 | ||||
| function write_theme() { | ||||
| function write_theme(Themes, opts)/*:string*/ { | ||||
| 	var o = [XML_HEADER]; | ||||
| 	o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">'; | ||||
| 	o[o.length] =  '<a:themeElements>'; | ||||
| @ -5648,22 +5646,22 @@ function write_theme() { | ||||
| 	o[o.length] =     '</a:gradFill>'; | ||||
| 	o[o.length] =    '</a:bgFillStyleLst>'; | ||||
| 	o[o.length] =   '</a:fmtScheme>'; | ||||
| 
 | ||||
| 	o[o.length] =  '</a:themeElements>'; | ||||
| 
 | ||||
| 	o[o.length] =  '<a:objectDefaults>'; | ||||
| 	o[o.length] =   '<a:spDef>'; | ||||
| 	o[o.length] =    '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="1"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef></a:style>'; | ||||
| 	o[o.length] =   '</a:spDef>'; | ||||
| 	o[o.length] =   '<a:lnDef>'; | ||||
| 	o[o.length] =    '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style>'; | ||||
| 	o[o.length] =     '</a:lnDef>'; | ||||
| 	o[o.length] =   '</a:lnDef>'; | ||||
| 	o[o.length] =  '</a:objectDefaults>'; | ||||
| 	o[o.length] =  '<a:extraClrSchemeLst/>'; | ||||
| 	o[o.length] = '</a:theme>'; | ||||
| 	return o.join(""); | ||||
| } | ||||
| /* [MS-XLS] 2.4.326 TODO: payload is a zip file */ | ||||
| function parse_Theme(blob, length) { | ||||
| function parse_Theme(blob, length, opts) { | ||||
| 	var dwThemeVersion = blob.read_shift(4); | ||||
| 	if(dwThemeVersion === 124226) return; | ||||
| 	blob.l += length-4; | ||||
| @ -8248,7 +8246,7 @@ function get_cell_style(styles, cell, opts) { | ||||
| 	return len; | ||||
| } | ||||
| 
 | ||||
| function safe_format(p, fmtid, fillid, opts) { | ||||
| function safe_format(p, fmtid, fillid, opts, themes, styles) { | ||||
| 	if(p.t === 'z') return; | ||||
| 	if(p.t === 'd' && typeof p.v === 'string') p.v = new Date(p.v); | ||||
| 	try { | ||||
| @ -8292,7 +8290,7 @@ var hlinkregex = /<(?:\w*:)?hyperlink[^>]*\/>/g; | ||||
| var dimregex = /"(\w*:\w*)"/; | ||||
| var colregex = /<(?:\w*:)?col[^>]*\/>/g; | ||||
| /* 18.3 Worksheets */ | ||||
| function parse_ws_xml(data/*:?string*/, opts, rels)/*:Worksheet*/ { | ||||
| function parse_ws_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| 	if(!data) return data; | ||||
| 	/* 18.3.1.99 worksheet CT_Worksheet */ | ||||
| 	var s = ({}/*:any*/); | ||||
| @ -8323,7 +8321,7 @@ function parse_ws_xml(data/*:?string*/, opts, rels)/*:Worksheet*/ { | ||||
| 
 | ||||
| 	/* 18.3.1.80 sheetData CT_SheetData ? */ | ||||
| 	var mtch=data.match(sheetdataregex); | ||||
| 	if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess); | ||||
| 	if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles); | ||||
| 
 | ||||
| 	/* 18.3.1.48 hyperlinks CT_Hyperlinks */ | ||||
| 	var hlink = data.match(hlinkregex); | ||||
| @ -8457,7 +8455,7 @@ var parse_ws_xml_data = (function parse_ws_xml_data_factory() { | ||||
| 	var refregex = /ref=["']([^"']*)["']/; | ||||
| 	var match_v = matchtag("v"), match_f = matchtag("f"); | ||||
| 
 | ||||
| return function parse_ws_xml_data(sdata, s, opts, guess) { | ||||
| return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 	var ri = 0, x = "", cells = [], cref = [], idx = 0, i=0, cc=0, d="", p/*:any*/; | ||||
| 	var tag, tagr = 0, tagc = 0; | ||||
| 	var sstr, ftag; | ||||
| @ -8572,7 +8570,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) { | ||||
| 					if(opts.cellStyles && cf.fillId != null) fillid = cf.fillId; | ||||
| 				} | ||||
| 			} | ||||
| 			safe_format(p, fmtid, fillid, opts); | ||||
| 			safe_format(p, fmtid, fillid, opts, themes, styles); | ||||
| 			s[tag.r] = p; | ||||
| 		} | ||||
| 	} | ||||
| @ -8878,7 +8876,7 @@ function parse_BrtShrFmla(data, length, opts) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.61 Worksheet */ | ||||
| function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ { | ||||
| function parse_ws_bin(data, opts, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| 	if(!data) return data; | ||||
| 	if(!rels) rels = {'!id':{}}; | ||||
| 	var s = {}; | ||||
| @ -8933,7 +8931,7 @@ function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ { | ||||
| 					case 'e': p.v = val[1]; p.w = BErr[p.v]; break; | ||||
| 					case 'str': p.t = 's'; p.v = utf8read(val[1]); break; | ||||
| 				} | ||||
| 				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts); | ||||
| 				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles); | ||||
| 				s[encode_col(C=val[0].c) + rr] = p; | ||||
| 				if(opts.cellFormula) { | ||||
| 					af = false; | ||||
| @ -9704,9 +9702,9 @@ function parse_wb(data, name/*:string*/, opts)/*:WorkbookFile*/ { | ||||
| 	return parse_wb_xml((data/*:any*/), opts); | ||||
| } | ||||
| 
 | ||||
| function parse_ws(data, name/*:string*/, opts, rels, wb)/*:Worksheet*/ { | ||||
| 	if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb); | ||||
| 	return parse_ws_xml((data/*:any*/), opts, rels, wb); | ||||
| function parse_ws(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ { | ||||
| 	if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb, themes, styles); | ||||
| 	return parse_ws_xml((data/*:any*/), opts, rels, wb, themes, styles); | ||||
| } | ||||
| 
 | ||||
| function parse_sty(data, name/*:string*/, opts) { | ||||
| @ -10756,7 +10754,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ { | ||||
| 		biff: 8, // BIFF version
 | ||||
| 		codepage: 0, // CP from CodePage record
 | ||||
| 		winlocked: 0, // fLockWn from WinProtect
 | ||||
| 		wtf: false | ||||
| 		WTF: !!options && !!options.wtf | ||||
| 	}/*:any*/); | ||||
| 	if(options.password) opts.password = options.password; | ||||
| 	var mergecells = []; | ||||
| @ -12763,6 +12761,7 @@ var parse_content_xml = (function() { | ||||
| 		var rept = 1, isstub = false; | ||||
| 		var i = 0; | ||||
| 		xlmlregex.lastIndex = 0; | ||||
| 		str = str.replace(/<!--([^\u2603]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,""); | ||||
| 		while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) { | ||||
| 
 | ||||
| 			case 'table': case '工作表': // 9.1.2 <table:table>
 | ||||
| @ -13116,7 +13115,7 @@ var parse_content_xml = (function() { | ||||
| 				if(Rn[2] === 'uof:') break; // TODO: uof
 | ||||
| 				if(Rn[2] === '表:') break; // TODO: uof
 | ||||
| 				if(Rn[2] === '字:') break; // TODO: uof
 | ||||
| 				if(opts.WTF) throw Rn; | ||||
| 				if(opts.WTF) throw new Error(Rn); | ||||
| 		} | ||||
| 		var out = { | ||||
| 			Sheets: Sheets, | ||||
| @ -13296,10 +13295,10 @@ function safe_parse_wbrels(wbrels, sheets) { | ||||
| 	return !wbrels || wbrels.length === 0 ? null : wbrels; | ||||
| } | ||||
| 
 | ||||
| function safe_parse_ws(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, opts, wb) { | ||||
| function safe_parse_ws(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, opts, wb, themes, styles) { | ||||
| 	try { | ||||
| 		sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path); | ||||
| 		sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb); | ||||
| 		sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb, themes, styles); | ||||
| 	} catch(e) { if(opts.WTF) throw e; } | ||||
| } | ||||
| 
 | ||||
| @ -13332,14 +13331,14 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 	if(dir.workbooks[0].slice(-3) == "bin") xlsb = true; | ||||
| 	if(xlsb) set_cp(1200); | ||||
| 
 | ||||
| 	var themes = ({}/*:any*/); | ||||
| 	var styles = ({}/*:any*/); | ||||
| 	if(!opts.bookSheets && !opts.bookProps) { | ||||
| 		strs = []; | ||||
| 		if(dir.sst) strs=parse_sst(getzipdata(zip, dir.sst.replace(/^\//,'')), dir.sst, opts); | ||||
| 
 | ||||
| 		styles = {}; | ||||
| 		if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts); | ||||
| 
 | ||||
| 		themes = {}; | ||||
| 		if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts); | ||||
| 	} | ||||
| 
 | ||||
| @ -13402,7 +13401,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ { | ||||
| 			path = path.replace(/sheet0\./,"sheet."); | ||||
| 		} | ||||
| 		relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels"); | ||||
| 		safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb); | ||||
| 		safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb, themes, styles); | ||||
| 	} | ||||
| 
 | ||||
| 	if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts); | ||||
| @ -13510,7 +13509,7 @@ function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ { | ||||
| 	/* TODO: something more intelligent with themes */ | ||||
| 
 | ||||
| 	f = "xl/theme/theme1.xml"; | ||||
| 	zip.file(f, write_theme()); | ||||
| 	zip.file(f, write_theme(wb.Themes, opts)); | ||||
| 	ct.themes.push(f); | ||||
| 	add_rels(opts.wbrels, ++rId, "theme/theme1.xml", RELS.THEME); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										83
									
								
								xlsx.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										83
									
								
								xlsx.js
									
									
									
									
									
								
							| @ -4614,7 +4614,6 @@ var parse_rs = (function parse_rs_factory() { | ||||
| 					if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0]; | ||||
| 			} | ||||
| 		} | ||||
| 		/* TODO: These should be generated styles, not inline */ | ||||
| 		var style = []; | ||||
| 		if(font.b) style.push("font-weight: bold;"); | ||||
| 		if(font.i) style.push("font-style: italic;"); | ||||
| @ -5020,12 +5019,8 @@ var XLMLPatternTypeMap = { | ||||
| 	"ThinHorzCross": "lightGrid" | ||||
| }; | ||||
| 
 | ||||
| var styles = {}; // shared styles
 | ||||
| 
 | ||||
| var themes = {}; // shared themes
 | ||||
| 
 | ||||
| /* 18.8.21 fills CT_Fills */ | ||||
| function parse_fills(t, opts) { | ||||
| function parse_fills(t, styles, opts) { | ||||
| 	styles.Fills = []; | ||||
| 	var fill = {}; | ||||
| 	t[0].match(tagregex).forEach(function(x) { | ||||
| @ -5065,13 +5060,13 @@ function parse_fills(t, opts) { | ||||
| 				break; | ||||
| 			case '<fgColor/>': case '</fgColor>': break; | ||||
| 
 | ||||
| 			default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills'); | ||||
| 			default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills'); | ||||
| 		} | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| /* 18.8.31 numFmts CT_NumFmts */ | ||||
| function parse_numFmts(t, opts) { | ||||
| function parse_numFmts(t, styles, opts) { | ||||
| 	styles.NumberFmt = []; | ||||
| 	var k/*Array<number>*/ = (keys(SSF._table)); | ||||
| 	for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]]; | ||||
| @ -5103,7 +5098,7 @@ function write_numFmts(NF, opts) { | ||||
| } | ||||
| 
 | ||||
| /* 18.8.10 cellXfs CT_CellXfs */ | ||||
| function parse_cellXfs(t, opts) { | ||||
| function parse_cellXfs(t, styles, opts) { | ||||
| 	styles.CellXf = []; | ||||
| 	t[0].match(tagregex).forEach(function(x) { | ||||
| 		var y = parsexmltag(x); | ||||
| @ -5147,24 +5142,25 @@ var cellXfRegex = /<cellXfs([^>]*)>.*<\/cellXfs>/; | ||||
| var fillsRegex = /<fills([^>]*)>.*<\/fills>/; | ||||
| 
 | ||||
| return function parse_sty_xml(data, opts) { | ||||
| 	var styles = {}; | ||||
| 	if(!data) return styles; | ||||
| 	/* 18.8.39 styleSheet CT_Stylesheet */ | ||||
| 	var t; | ||||
| 
 | ||||
| 	/* numFmts CT_NumFmts ? */ | ||||
| 	if((t=data.match(numFmtRegex))) parse_numFmts(t, opts); | ||||
| 	if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts); | ||||
| 
 | ||||
| 	/* fonts CT_Fonts ? */ | ||||
| 	/*if((t=data.match(/<fonts([^>]*)>.*<\/fonts>/))) parse_fonts(t, opts);*/ | ||||
| 
 | ||||
| 	/* fills CT_Fills */ | ||||
| 	if((t=data.match(fillsRegex))) parse_fills(t, opts); | ||||
| 	if((t=data.match(fillsRegex))) parse_fills(t, styles, opts); | ||||
| 
 | ||||
| 	/* borders CT_Borders ? */ | ||||
| 	/* cellStyleXfs CT_CellStyleXfs ? */ | ||||
| 
 | ||||
| 	/* cellXfs CT_CellXfs ? */ | ||||
| 	if((t=data.match(cellXfRegex))) parse_cellXfs(t, opts); | ||||
| 	if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts); | ||||
| 
 | ||||
| 	/* dxfs CT_Dxfs ? */ | ||||
| 	/* tableStyles CT_TableStyles ? */ | ||||
| @ -5241,6 +5237,7 @@ function parse_BrtXF(data, length) { | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.50 Styles */ | ||||
| function parse_sty_bin(data, opts) { | ||||
| 	var styles = {}; | ||||
| 	styles.NumberFmt = ([]); | ||||
| 	for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y]; | ||||
| 
 | ||||
| @ -5333,7 +5330,7 @@ function write_sty_bin(data, opts) { | ||||
| RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"; | ||||
| 
 | ||||
| /* 20.1.6.2 clrScheme CT_ColorScheme */ | ||||
| function parse_clrScheme(t, opts) { | ||||
| function parse_clrScheme(t, themes, opts) { | ||||
| 	themes.themeElements.clrScheme = []; | ||||
| 	var color = {}; | ||||
| 	(t[0].match(tagregex)||[]).forEach(function(x) { | ||||
| @ -5391,23 +5388,23 @@ function parse_clrScheme(t, opts) { | ||||
| 				} | ||||
| 				break; | ||||
| 
 | ||||
| 			default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in clrScheme'; | ||||
| 			default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme'); | ||||
| 		} | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| /* 20.1.4.1.18 fontScheme CT_FontScheme */ | ||||
| function parse_fontScheme(t, opts) { } | ||||
| function parse_fontScheme(t, themes, opts) { } | ||||
| 
 | ||||
| /* 20.1.4.1.15 fmtScheme CT_StyleMatrix */ | ||||
| function parse_fmtScheme(t, opts) { } | ||||
| function parse_fmtScheme(t, themes, opts) { } | ||||
| 
 | ||||
| var clrsregex = /<a:clrScheme([^>]*)>[^\u2603]*<\/a:clrScheme>/; | ||||
| var fntsregex = /<a:fontScheme([^>]*)>[^\u2603]*<\/a:fontScheme>/; | ||||
| var fmtsregex = /<a:fmtScheme([^>]*)>[^\u2603]*<\/a:fmtScheme>/; | ||||
| 
 | ||||
| /* 20.1.6.10 themeElements CT_BaseStyles */ | ||||
| function parse_themeElements(data, opts) { | ||||
| function parse_themeElements(data, themes, opts) { | ||||
| 	themes.themeElements = {}; | ||||
| 
 | ||||
| 	var t; | ||||
| @ -5421,7 +5418,7 @@ function parse_themeElements(data, opts) { | ||||
| 		['fmtScheme', fmtsregex, parse_fmtScheme] | ||||
| 	].forEach(function(m) { | ||||
| 		if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements'); | ||||
| 		m[2](t, opts); | ||||
| 		m[2](t, themes, opts); | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| @ -5430,18 +5427,19 @@ var themeltregex = /<a:themeElements([^>]*)>[^\u2603]*<\/a:themeElements>/; | ||||
| /* 14.2.7 Theme Part */ | ||||
| function parse_theme_xml(data, opts) { | ||||
| 	/* 20.1.6.9 theme CT_OfficeStyleSheet */ | ||||
| 	if(!data || data.length === 0) return themes; | ||||
| 	if(!data || data.length === 0) return parse_theme_xml(write_theme()); | ||||
| 
 | ||||
| 	var t; | ||||
| 	var themes = {}; | ||||
| 
 | ||||
| 	/* themeElements CT_BaseStyles */ | ||||
| 	if(!(t=data.match(themeltregex))) throw 'themeElements not found in theme'; | ||||
| 	parse_themeElements(t[0], opts); | ||||
| 	parse_themeElements(t[0], themes, opts); | ||||
| 
 | ||||
| 	return themes; | ||||
| } | ||||
| 
 | ||||
| function write_theme() { | ||||
| function write_theme(Themes, opts) { | ||||
| 	var o = [XML_HEADER]; | ||||
| 	o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">'; | ||||
| 	o[o.length] =  '<a:themeElements>'; | ||||
| @ -5596,22 +5594,22 @@ function write_theme() { | ||||
| 	o[o.length] =     '</a:gradFill>'; | ||||
| 	o[o.length] =    '</a:bgFillStyleLst>'; | ||||
| 	o[o.length] =   '</a:fmtScheme>'; | ||||
| 
 | ||||
| 	o[o.length] =  '</a:themeElements>'; | ||||
| 
 | ||||
| 	o[o.length] =  '<a:objectDefaults>'; | ||||
| 	o[o.length] =   '<a:spDef>'; | ||||
| 	o[o.length] =    '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="1"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef></a:style>'; | ||||
| 	o[o.length] =   '</a:spDef>'; | ||||
| 	o[o.length] =   '<a:lnDef>'; | ||||
| 	o[o.length] =    '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style>'; | ||||
| 	o[o.length] =     '</a:lnDef>'; | ||||
| 	o[o.length] =   '</a:lnDef>'; | ||||
| 	o[o.length] =  '</a:objectDefaults>'; | ||||
| 	o[o.length] =  '<a:extraClrSchemeLst/>'; | ||||
| 	o[o.length] = '</a:theme>'; | ||||
| 	return o.join(""); | ||||
| } | ||||
| /* [MS-XLS] 2.4.326 TODO: payload is a zip file */ | ||||
| function parse_Theme(blob, length) { | ||||
| function parse_Theme(blob, length, opts) { | ||||
| 	var dwThemeVersion = blob.read_shift(4); | ||||
| 	if(dwThemeVersion === 124226) return; | ||||
| 	blob.l += length-4; | ||||
| @ -8195,7 +8193,7 @@ function get_cell_style(styles, cell, opts) { | ||||
| 	return len; | ||||
| } | ||||
| 
 | ||||
| function safe_format(p, fmtid, fillid, opts) { | ||||
| function safe_format(p, fmtid, fillid, opts, themes, styles) { | ||||
| 	if(p.t === 'z') return; | ||||
| 	if(p.t === 'd' && typeof p.v === 'string') p.v = new Date(p.v); | ||||
| 	try { | ||||
| @ -8239,7 +8237,7 @@ var hlinkregex = /<(?:\w*:)?hyperlink[^>]*\/>/g; | ||||
| var dimregex = /"(\w*:\w*)"/; | ||||
| var colregex = /<(?:\w*:)?col[^>]*\/>/g; | ||||
| /* 18.3 Worksheets */ | ||||
| function parse_ws_xml(data, opts, rels) { | ||||
| function parse_ws_xml(data, opts, rels, wb, themes, styles) { | ||||
| 	if(!data) return data; | ||||
| 	/* 18.3.1.99 worksheet CT_Worksheet */ | ||||
| 	var s = ({}); | ||||
| @ -8270,7 +8268,7 @@ function parse_ws_xml(data, opts, rels) { | ||||
| 
 | ||||
| 	/* 18.3.1.80 sheetData CT_SheetData ? */ | ||||
| 	var mtch=data.match(sheetdataregex); | ||||
| 	if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess); | ||||
| 	if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles); | ||||
| 
 | ||||
| 	/* 18.3.1.48 hyperlinks CT_Hyperlinks */ | ||||
| 	var hlink = data.match(hlinkregex); | ||||
| @ -8404,7 +8402,7 @@ var parse_ws_xml_data = (function parse_ws_xml_data_factory() { | ||||
| 	var refregex = /ref=["']([^"']*)["']/; | ||||
| 	var match_v = matchtag("v"), match_f = matchtag("f"); | ||||
| 
 | ||||
| return function parse_ws_xml_data(sdata, s, opts, guess) { | ||||
| return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) { | ||||
| 	var ri = 0, x = "", cells = [], cref = [], idx = 0, i=0, cc=0, d="", p; | ||||
| 	var tag, tagr = 0, tagc = 0; | ||||
| 	var sstr, ftag; | ||||
| @ -8519,7 +8517,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) { | ||||
| 					if(opts.cellStyles && cf.fillId != null) fillid = cf.fillId; | ||||
| 				} | ||||
| 			} | ||||
| 			safe_format(p, fmtid, fillid, opts); | ||||
| 			safe_format(p, fmtid, fillid, opts, themes, styles); | ||||
| 			s[tag.r] = p; | ||||
| 		} | ||||
| 	} | ||||
| @ -8825,7 +8823,7 @@ function parse_BrtShrFmla(data, length, opts) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.61 Worksheet */ | ||||
| function parse_ws_bin(data, opts, rels, wb) { | ||||
| function parse_ws_bin(data, opts, rels, wb, themes, styles) { | ||||
| 	if(!data) return data; | ||||
| 	if(!rels) rels = {'!id':{}}; | ||||
| 	var s = {}; | ||||
| @ -8880,7 +8878,7 @@ function parse_ws_bin(data, opts, rels, wb) { | ||||
| 					case 'e': p.v = val[1]; p.w = BErr[p.v]; break; | ||||
| 					case 'str': p.t = 's'; p.v = utf8read(val[1]); break; | ||||
| 				} | ||||
| 				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts); | ||||
| 				if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles); | ||||
| 				s[encode_col(C=val[0].c) + rr] = p; | ||||
| 				if(opts.cellFormula) { | ||||
| 					af = false; | ||||
| @ -9651,9 +9649,9 @@ function parse_wb(data, name, opts) { | ||||
| 	return parse_wb_xml((data), opts); | ||||
| } | ||||
| 
 | ||||
| function parse_ws(data, name, opts, rels, wb) { | ||||
| 	if(name.slice(-4)===".bin") return parse_ws_bin((data), opts, rels, wb); | ||||
| 	return parse_ws_xml((data), opts, rels, wb); | ||||
| function parse_ws(data, name, opts, rels, wb, themes, styles) { | ||||
| 	if(name.slice(-4)===".bin") return parse_ws_bin((data), opts, rels, wb, themes, styles); | ||||
| 	return parse_ws_xml((data), opts, rels, wb, themes, styles); | ||||
| } | ||||
| 
 | ||||
| function parse_sty(data, name, opts) { | ||||
| @ -10699,7 +10697,7 @@ function parse_workbook(blob, options) { | ||||
| 		biff: 8, // BIFF version
 | ||||
| 		codepage: 0, // CP from CodePage record
 | ||||
| 		winlocked: 0, // fLockWn from WinProtect
 | ||||
| 		wtf: false | ||||
| 		WTF: !!options && !!options.wtf | ||||
| 	}); | ||||
| 	if(options.password) opts.password = options.password; | ||||
| 	var mergecells = []; | ||||
| @ -12706,6 +12704,7 @@ var parse_content_xml = (function() { | ||||
| 		var rept = 1, isstub = false; | ||||
| 		var i = 0; | ||||
| 		xlmlregex.lastIndex = 0; | ||||
| 		str = str.replace(/<!--([^\u2603]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,""); | ||||
| 		while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) { | ||||
| 
 | ||||
| 			case 'table': case '工作表': // 9.1.2 <table:table>
 | ||||
| @ -13059,7 +13058,7 @@ var parse_content_xml = (function() { | ||||
| 				if(Rn[2] === 'uof:') break; // TODO: uof
 | ||||
| 				if(Rn[2] === '表:') break; // TODO: uof
 | ||||
| 				if(Rn[2] === '字:') break; // TODO: uof
 | ||||
| 				if(opts.WTF) throw Rn; | ||||
| 				if(opts.WTF) throw new Error(Rn); | ||||
| 		} | ||||
| 		var out = { | ||||
| 			Sheets: Sheets, | ||||
| @ -13238,10 +13237,10 @@ function safe_parse_wbrels(wbrels, sheets) { | ||||
| 	return !wbrels || wbrels.length === 0 ? null : wbrels; | ||||
| } | ||||
| 
 | ||||
| function safe_parse_ws(zip, path, relsPath, sheet, sheetRels, sheets, opts, wb) { | ||||
| function safe_parse_ws(zip, path, relsPath, sheet, sheetRels, sheets, opts, wb, themes, styles) { | ||||
| 	try { | ||||
| 		sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path); | ||||
| 		sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb); | ||||
| 		sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb, themes, styles); | ||||
| 	} catch(e) { if(opts.WTF) throw e; } | ||||
| } | ||||
| 
 | ||||
| @ -13274,14 +13273,14 @@ function parse_zip(zip, opts) { | ||||
| 	if(dir.workbooks[0].slice(-3) == "bin") xlsb = true; | ||||
| 	if(xlsb) set_cp(1200); | ||||
| 
 | ||||
| 	var themes = ({}); | ||||
| 	var styles = ({}); | ||||
| 	if(!opts.bookSheets && !opts.bookProps) { | ||||
| 		strs = []; | ||||
| 		if(dir.sst) strs=parse_sst(getzipdata(zip, dir.sst.replace(/^\//,'')), dir.sst, opts); | ||||
| 
 | ||||
| 		styles = {}; | ||||
| 		if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts); | ||||
| 
 | ||||
| 		themes = {}; | ||||
| 		if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts); | ||||
| 	} | ||||
| 
 | ||||
| @ -13344,7 +13343,7 @@ function parse_zip(zip, opts) { | ||||
| 			path = path.replace(/sheet0\./,"sheet."); | ||||
| 		} | ||||
| 		relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels"); | ||||
| 		safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb); | ||||
| 		safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb, themes, styles); | ||||
| 	} | ||||
| 
 | ||||
| 	if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts); | ||||
| @ -13450,7 +13449,7 @@ f = "docProps/app.xml"; | ||||
| 	/* TODO: something more intelligent with themes */ | ||||
| 
 | ||||
| 	f = "xl/theme/theme1.xml"; | ||||
| 	zip.file(f, write_theme()); | ||||
| 	zip.file(f, write_theme(wb.Themes, opts)); | ||||
| 	ct.themes.push(f); | ||||
| 	add_rels(opts.wbrels, ++rId, "theme/theme1.xml", RELS.THEME); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user