forked from sheetjs/sheetjs
		
	HTML TD 't' attribute (fixes #917)
note: @sheetjsdev authored commit, original PR date/author used
This commit is contained in:
		
							parent
							
								
									c9cab8078c
								
							
						
					
					
						commit
						b17a09849a
					
				| @ -1493,7 +1493,7 @@ The exported `read` and `readFile` functions accept an options argument: | ||||
| | :---------- | ------: | :--------------------------------------------------- | | ||||
| |`type`       |         | Input data encoding (see Input Type below)           | | ||||
| |`raw`        | false   | If true, plain text parsing will not parse values ** | | ||||
| |`codepage`   | 1252    | If specified, use code page when appropriate **      | | ||||
| |`codepage`   |         | If specified, use code page when appropriate **      | | ||||
| |`cellFormula`| true    | Save formulae to the .f field                        | | ||||
| |`cellHTML`   | true    | Parse rich text and save HTML to the `.h` field      | | ||||
| |`cellNF`     | false   | Save number format string to the `.z` field          | | ||||
| @ -2230,6 +2230,11 @@ Excel HTML worksheets include special metadata encoded in styles.  For example, | ||||
| `mso-number-format` is a localized string containing the number format.  Despite | ||||
| the metadata the output is valid HTML, although it does accept bare `&` symbols. | ||||
| 
 | ||||
| The writer adds type metadata to the TD elements via the `t` tag.  The parser | ||||
| looks for those tags and overrides the default interpretation. For example, text | ||||
| like `<td>12345</td>` will be parsed as numbers but `<td t="s">12345</td>` will | ||||
| be parsed as text. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| #### Rich Text Format (RTF) | ||||
|  | ||||
| @ -28,32 +28,25 @@ var HTML_ = (function() { | ||||
| 				var tag = parsexmltag(cell.slice(0, cell.indexOf(">"))); | ||||
| 				CS = tag.colspan ? +tag.colspan : 1; | ||||
| 				if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); | ||||
| 				var _t/*:string*/ = tag.t || ""; | ||||
| 				/* TODO: generate stub cells */ | ||||
| 				if(!m.length) { C += CS; continue; } | ||||
| 				m = htmldecode(unescapexml(m)); | ||||
| 				if(range.s.r > R) range.s.r = R; | ||||
| 				if(range.e.r < R) range.e.r = R; | ||||
| 				if(range.s.c > C) range.s.c = C; | ||||
| 				if(range.e.c < C) range.e.c = C; | ||||
| 				if(opts.dense) { | ||||
| 					if(!ws[R]) ws[R] = []; | ||||
| 					if(!m.length){} | ||||
| 					else if(opts.raw || !m.trim().length) ws[R][C] = {t:'s', v:m}; | ||||
| 					else if(m === 'TRUE') ws[R][C] = {t:'b', v:true}; | ||||
| 					else if(m === 'FALSE') ws[R][C] = {t:'b', v:false}; | ||||
| 					else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)}; | ||||
| 					else ws[R][C] = {t:'s', v:m}; | ||||
| 				} else { | ||||
| 					var coord/*:string*/ = encode_cell({r:R, c:C}); | ||||
| 					/* TODO: value parsing */ | ||||
| 					if(!m.length){} | ||||
| 					else if(opts.raw) ws[coord] = {t:'s', v:m}; | ||||
| 					else if(opts.raw || !m.trim().length) ws[coord] = {t:'s', v:m}; | ||||
| 					else if(m === 'TRUE') ws[coord] = {t:'b', v:true}; | ||||
| 					else if(m === 'FALSE') ws[coord] = {t:'b', v:false}; | ||||
| 					else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)}; | ||||
| 					else ws[coord] = {t:'s', v:m}; | ||||
| 				if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R; | ||||
| 				if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C; | ||||
| 				if(!m.length) continue; | ||||
| 				var o/*:Cell*/ = {t:'s', v:m}; | ||||
| 				if(opts.raw || !m.trim().length || _t == 's'){} | ||||
| 				else if(m === 'TRUE') o = {t:'b', v:true}; | ||||
| 				else if(m === 'FALSE') o = {t:'b', v:false}; | ||||
| 				else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)}; | ||||
| 				else if(!isNaN(fuzzydate(m).getDate())) { | ||||
| 					o = ({t:'d', v:parseDate(m)}/*:any*/); | ||||
| 					if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/); | ||||
| 					o.z = opts.dateNF || SSF._table[14]; | ||||
| 				} | ||||
| 				if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; } | ||||
| 				else ws[encode_cell({r:R, c:C})] = o; | ||||
| 				C += CS; | ||||
| 			} | ||||
| 		} | ||||
| @ -84,6 +77,7 @@ var HTML_ = (function() { | ||||
| 			var sp = {}; | ||||
| 			if(RS > 1) sp.rowspan = RS; | ||||
| 			if(CS > 1) sp.colspan = CS; | ||||
| 			sp.t = cell.t; | ||||
| 			if(o.editable) w = '<span contenteditable="true">' + w + '</span>'; | ||||
| 			sp.id = "sjs-" + coord; | ||||
| 			oo.push(writextag('td', w, sp)); | ||||
| @ -142,10 +136,10 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ { | ||||
| 			CS = +elt.getAttribute("colspan") || 1; | ||||
| 			if((RS = +elt.getAttribute("rowspan"))>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); | ||||
| 			var o/*:Cell*/ = {t:'s', v:v}; | ||||
| 			var _t/*:string*/ = elt.getAttribute("t") || ""; | ||||
| 			if(v != null) { | ||||
| 				if(v.length == 0) o.t = 'z'; | ||||
| 				else if(opts.raw){} | ||||
| 				else if(v.trim().length == 0) o.t = 's'; | ||||
| 				if(v.length == 0) o.t = _t || 'z'; | ||||
| 				else if(opts.raw || v.trim().length == 0 || _t == "s"){} | ||||
| 				else if(v === 'TRUE') o = {t:'b', v:true}; | ||||
| 				else if(v === 'FALSE') o = {t:'b', v:false}; | ||||
| 				else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)}; | ||||
|  | ||||
| @ -253,6 +253,11 @@ Excel HTML worksheets include special metadata encoded in styles.  For example, | ||||
| `mso-number-format` is a localized string containing the number format.  Despite | ||||
| the metadata the output is valid HTML, although it does accept bare `&` symbols. | ||||
| 
 | ||||
| The writer adds type metadata to the TD elements via the `t` tag.  The parser | ||||
| looks for those tags and overrides the default interpretation. For example, text | ||||
| like `<td>12345</td>` will be parsed as numbers but `<td t="s">12345</td>` will | ||||
| be parsed as text. | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| #### Rich Text Format (RTF) | ||||
|  | ||||
| @ -1364,7 +1364,7 @@ The exported `read` and `readFile` functions accept an options argument: | ||||
| | :---------- | ------: | :--------------------------------------------------- | | ||||
| |`type`       |         | Input data encoding (see Input Type below)           | | ||||
| |`raw`        | false   | If true, plain text parsing will not parse values ** | | ||||
| |`codepage`   | 1252    | If specified, use code page when appropriate **      | | ||||
| |`codepage`   |         | If specified, use code page when appropriate **      | | ||||
| |`cellFormula`| true    | Save formulae to the .f field                        | | ||||
| |`cellHTML`   | true    | Parse rich text and save HTML to the `.h` field      | | ||||
| |`cellNF`     | false   | Save number format string to the `.z` field          | | ||||
| @ -2027,6 +2027,11 @@ Excel HTML worksheets include special metadata encoded in styles.  For example, | ||||
| `mso-number-format` is a localized string containing the number format.  Despite | ||||
| the metadata the output is valid HTML, although it does accept bare `&` symbols. | ||||
| 
 | ||||
| The writer adds type metadata to the TD elements via the `t` tag.  The parser | ||||
| looks for those tags and overrides the default interpretation. For example, text | ||||
| like `<td>12345</td>` will be parsed as numbers but `<td t="s">12345</td>` will | ||||
| be parsed as text. | ||||
| 
 | ||||
| 
 | ||||
| #### Rich Text Format (RTF) | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										14
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										14
									
								
								test.js
									
									
									
									
									
								
							| @ -1881,6 +1881,20 @@ describe('HTML', function() { | ||||
| 		assert.equal(get_cell(ws, "A1").v, "A&B"); | ||||
| 		assert.equal(get_cell(ws, "B1").v, "A·B"); | ||||
| 	}); | ||||
| 	describe('type override', function() { | ||||
| 		function chk(ws) { | ||||
| 			assert.equal(get_cell(ws, "A1").t, "s"); | ||||
| 			assert.equal(get_cell(ws, "A1").v, "1234567890"); | ||||
| 			assert.equal(get_cell(ws, "B1").t, "n"); | ||||
| 			assert.equal(get_cell(ws, "B1").v, 1234567890); | ||||
| 		} | ||||
| 		var html = "<table><tr><td t=\"s\">1234567890</td><td>1234567890</td></tr></table>"; | ||||
| 		it('HTML string', function() { | ||||
| 			var ws = X.read(html, {type:'string'}).Sheets.Sheet1; chk(ws); | ||||
| 			chk(X.read(X.utils.sheet_to_html(ws), {type:'string'}).Sheets.Sheet1); | ||||
| 		}); | ||||
| 		if(domtest) it('DOM', function() { chk(X.utils.table_to_sheet(get_dom_element(html))); }); | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| describe('js -> file -> js', function() { | ||||
|  | ||||
| @ -1881,6 +1881,20 @@ describe('HTML', function() { | ||||
| 		assert.equal(get_cell(ws, "A1").v, "A&B"); | ||||
| 		assert.equal(get_cell(ws, "B1").v, "A·B"); | ||||
| 	}); | ||||
| 	describe('type override', function() { | ||||
| 		function chk(ws) { | ||||
| 			assert.equal(get_cell(ws, "A1").t, "s"); | ||||
| 			assert.equal(get_cell(ws, "A1").v, "1234567890"); | ||||
| 			assert.equal(get_cell(ws, "B1").t, "n"); | ||||
| 			assert.equal(get_cell(ws, "B1").v, 1234567890); | ||||
| 		} | ||||
| 		var html = "<table><tr><td t=\"s\">1234567890</td><td>1234567890</td></tr></table>"; | ||||
| 		it('HTML string', function() { | ||||
| 			var ws = X.read(html, {type:'string'}).Sheets.Sheet1; chk(ws); | ||||
| 			chk(X.read(X.utils.sheet_to_html(ws), {type:'string'}).Sheets.Sheet1); | ||||
| 		}); | ||||
| 		if(domtest) it('DOM', function() { chk(X.utils.table_to_sheet(get_dom_element(html))); }); | ||||
| 	}); | ||||
| }); | ||||
| 
 | ||||
| describe('js -> file -> js', function() { | ||||
|  | ||||
							
								
								
									
										44
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										44
									
								
								xlsx.flow.js
									
									
									
									
									
								
							| @ -17358,32 +17358,25 @@ var HTML_ = (function() { | ||||
| 				var tag = parsexmltag(cell.slice(0, cell.indexOf(">"))); | ||||
| 				CS = tag.colspan ? +tag.colspan : 1; | ||||
| 				if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); | ||||
| 				var _t/*:string*/ = tag.t || ""; | ||||
| 				/* TODO: generate stub cells */ | ||||
| 				if(!m.length) { C += CS; continue; } | ||||
| 				m = htmldecode(unescapexml(m)); | ||||
| 				if(range.s.r > R) range.s.r = R; | ||||
| 				if(range.e.r < R) range.e.r = R; | ||||
| 				if(range.s.c > C) range.s.c = C; | ||||
| 				if(range.e.c < C) range.e.c = C; | ||||
| 				if(opts.dense) { | ||||
| 					if(!ws[R]) ws[R] = []; | ||||
| 					if(!m.length){} | ||||
| 					else if(opts.raw || !m.trim().length) ws[R][C] = {t:'s', v:m}; | ||||
| 					else if(m === 'TRUE') ws[R][C] = {t:'b', v:true}; | ||||
| 					else if(m === 'FALSE') ws[R][C] = {t:'b', v:false}; | ||||
| 					else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)}; | ||||
| 					else ws[R][C] = {t:'s', v:m}; | ||||
| 				} else { | ||||
| 					var coord/*:string*/ = encode_cell({r:R, c:C}); | ||||
| 					/* TODO: value parsing */ | ||||
| 					if(!m.length){} | ||||
| 					else if(opts.raw) ws[coord] = {t:'s', v:m}; | ||||
| 					else if(opts.raw || !m.trim().length) ws[coord] = {t:'s', v:m}; | ||||
| 					else if(m === 'TRUE') ws[coord] = {t:'b', v:true}; | ||||
| 					else if(m === 'FALSE') ws[coord] = {t:'b', v:false}; | ||||
| 					else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)}; | ||||
| 					else ws[coord] = {t:'s', v:m}; | ||||
| 				if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R; | ||||
| 				if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C; | ||||
| 				if(!m.length) continue; | ||||
| 				var o/*:Cell*/ = {t:'s', v:m}; | ||||
| 				if(opts.raw || !m.trim().length || _t == 's'){} | ||||
| 				else if(m === 'TRUE') o = {t:'b', v:true}; | ||||
| 				else if(m === 'FALSE') o = {t:'b', v:false}; | ||||
| 				else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)}; | ||||
| 				else if(!isNaN(fuzzydate(m).getDate())) { | ||||
| 					o = ({t:'d', v:parseDate(m)}/*:any*/); | ||||
| 					if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/); | ||||
| 					o.z = opts.dateNF || SSF._table[14]; | ||||
| 				} | ||||
| 				if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; } | ||||
| 				else ws[encode_cell({r:R, c:C})] = o; | ||||
| 				C += CS; | ||||
| 			} | ||||
| 		} | ||||
| @ -17414,6 +17407,7 @@ var HTML_ = (function() { | ||||
| 			var sp = {}; | ||||
| 			if(RS > 1) sp.rowspan = RS; | ||||
| 			if(CS > 1) sp.colspan = CS; | ||||
| 			sp.t = cell.t; | ||||
| 			if(o.editable) w = '<span contenteditable="true">' + w + '</span>'; | ||||
| 			sp.id = "sjs-" + coord; | ||||
| 			oo.push(writextag('td', w, sp)); | ||||
| @ -17472,10 +17466,10 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ { | ||||
| 			CS = +elt.getAttribute("colspan") || 1; | ||||
| 			if((RS = +elt.getAttribute("rowspan"))>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); | ||||
| 			var o/*:Cell*/ = {t:'s', v:v}; | ||||
| 			var _t/*:string*/ = elt.getAttribute("t") || ""; | ||||
| 			if(v != null) { | ||||
| 				if(v.length == 0) o.t = 'z'; | ||||
| 				else if(opts.raw){} | ||||
| 				else if(v.trim().length == 0) o.t = 's'; | ||||
| 				if(v.length == 0) o.t = _t || 'z'; | ||||
| 				else if(opts.raw || v.trim().length == 0 || _t == "s"){} | ||||
| 				else if(v === 'TRUE') o = {t:'b', v:true}; | ||||
| 				else if(v === 'FALSE') o = {t:'b', v:false}; | ||||
| 				else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)}; | ||||
|  | ||||
							
								
								
									
										44
									
								
								xlsx.js
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										44
									
								
								xlsx.js
									
									
									
										generated
									
									
									
								
							| @ -17257,32 +17257,25 @@ var HTML_ = (function() { | ||||
| 				var tag = parsexmltag(cell.slice(0, cell.indexOf(">"))); | ||||
| 				CS = tag.colspan ? +tag.colspan : 1; | ||||
| 				if((RS = +tag.rowspan)>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); | ||||
| 				var _t = tag.t || ""; | ||||
| 				/* TODO: generate stub cells */ | ||||
| 				if(!m.length) { C += CS; continue; } | ||||
| 				m = htmldecode(unescapexml(m)); | ||||
| 				if(range.s.r > R) range.s.r = R; | ||||
| 				if(range.e.r < R) range.e.r = R; | ||||
| 				if(range.s.c > C) range.s.c = C; | ||||
| 				if(range.e.c < C) range.e.c = C; | ||||
| 				if(opts.dense) { | ||||
| 					if(!ws[R]) ws[R] = []; | ||||
| 					if(!m.length){} | ||||
| 					else if(opts.raw || !m.trim().length) ws[R][C] = {t:'s', v:m}; | ||||
| 					else if(m === 'TRUE') ws[R][C] = {t:'b', v:true}; | ||||
| 					else if(m === 'FALSE') ws[R][C] = {t:'b', v:false}; | ||||
| 					else if(!isNaN(fuzzynum(m))) ws[R][C] = {t:'n', v:fuzzynum(m)}; | ||||
| 					else ws[R][C] = {t:'s', v:m}; | ||||
| 				} else { | ||||
| 					var coord = encode_cell({r:R, c:C}); | ||||
| 					/* TODO: value parsing */ | ||||
| 					if(!m.length){} | ||||
| 					else if(opts.raw) ws[coord] = {t:'s', v:m}; | ||||
| 					else if(opts.raw || !m.trim().length) ws[coord] = {t:'s', v:m}; | ||||
| 					else if(m === 'TRUE') ws[coord] = {t:'b', v:true}; | ||||
| 					else if(m === 'FALSE') ws[coord] = {t:'b', v:false}; | ||||
| 					else if(!isNaN(fuzzynum(m))) ws[coord] = {t:'n', v:fuzzynum(m)}; | ||||
| 					else ws[coord] = {t:'s', v:m}; | ||||
| 				if(range.s.r > R) range.s.r = R; if(range.e.r < R) range.e.r = R; | ||||
| 				if(range.s.c > C) range.s.c = C; if(range.e.c < C) range.e.c = C; | ||||
| 				if(!m.length) continue; | ||||
| 				var o = {t:'s', v:m}; | ||||
| 				if(opts.raw || !m.trim().length || _t == 's'){} | ||||
| 				else if(m === 'TRUE') o = {t:'b', v:true}; | ||||
| 				else if(m === 'FALSE') o = {t:'b', v:false}; | ||||
| 				else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)}; | ||||
| 				else if(!isNaN(fuzzydate(m).getDate())) { | ||||
| 					o = ({t:'d', v:parseDate(m)}); | ||||
| 					if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}); | ||||
| 					o.z = opts.dateNF || SSF._table[14]; | ||||
| 				} | ||||
| 				if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o; } | ||||
| 				else ws[encode_cell({r:R, c:C})] = o; | ||||
| 				C += CS; | ||||
| 			} | ||||
| 		} | ||||
| @ -17313,6 +17306,7 @@ var HTML_ = (function() { | ||||
| 			var sp = {}; | ||||
| 			if(RS > 1) sp.rowspan = RS; | ||||
| 			if(CS > 1) sp.colspan = CS; | ||||
| 			sp.t = cell.t; | ||||
| 			if(o.editable) w = '<span contenteditable="true">' + w + '</span>'; | ||||
| 			sp.id = "sjs-" + coord; | ||||
| 			oo.push(writextag('td', w, sp)); | ||||
| @ -17371,10 +17365,10 @@ function parse_dom_table(table, _opts) { | ||||
| 			CS = +elt.getAttribute("colspan") || 1; | ||||
| 			if((RS = +elt.getAttribute("rowspan"))>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}}); | ||||
| 			var o = {t:'s', v:v}; | ||||
| 			var _t = elt.getAttribute("t") || ""; | ||||
| 			if(v != null) { | ||||
| 				if(v.length == 0) o.t = 'z'; | ||||
| 				else if(opts.raw){} | ||||
| 				else if(v.trim().length == 0) o.t = 's'; | ||||
| 				if(v.length == 0) o.t = _t || 'z'; | ||||
| 				else if(opts.raw || v.trim().length == 0 || _t == "s"){} | ||||
| 				else if(v === 'TRUE') o = {t:'b', v:true}; | ||||
| 				else if(v === 'FALSE') o = {t:'b', v:false}; | ||||
| 				else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)}; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user