/*
* This file is part of TREB.
*
* TREB is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with TREB. If not, see .
*
* Copyright 2022-2026 trebco, llc.
* info@treb.app
*
*/
import * as OOXML from 'ooxml-types';
import { EnsureArray, IterateTags } from './ooxml';
export class SharedStrings {
public strings: string[] = [];
public reverse: Record = {};
/** read strings table from (pre-parsed) xml; removes any existing strings */
public FromXML(sst: OOXML.SharedStringTable) {
// clear
this.strings = [];
this.reverse = {};
let index = 0;
IterateTags(sst.si, si => {
// simple string looks like
//
//
// text here!
//
if (si.t !== undefined) {
// seen recently in the wild, text with leading (or trailing) spaces
// has an attribute xml:space=preserve (which makes sense, but was not
// expecting it)
//
//
// (Target portfolio lease rate based on internal estimate of average Canadian farmland rates)
//
//
let base = '';
if (typeof si.t === 'string') { base = si.t; }
else if (si.t.$text) {
base = si.t.$text;
}
this.strings[index] = base;
this.reverse[base] = index;
}
// complex string looks like
//
//
//
// (...style data...)
// text part
//
//
//
// where there can be multiple r tags with different styling.
// since we don't support that atm, let's drop style and just
// collect text.
else if (si.r) {
// not sure what happens if there are multiple tags
const r = EnsureArray(si.r)[0];
if (r) {
const parts = EnsureArray(r.t);
const composite = parts.map(part => part.$text || '').join('');
this.strings[index] = composite;
this.reverse[composite] = index;
}
}
else {
console.warn(` ** unexpected shared string @ ${index}`);
console.info(si);
}
index++;
});
}
/** return a string by index */
public Get(index: number): string|undefined {
return this.strings[index];
}
/** find existing string or insert, and return index */
public Ensure(text: string): number {
if (text[0] === '\'') {
text = text.substring(1);
}
let index = this.reverse[text];
if (typeof index === 'number') {
return index;
}
index = this.strings.length;
this.strings.push(text);
this.reverse[text] = index;
return index;
}
}