diff --git a/static/js/TextRangeV3.jsx b/static/js/TextRangeV3.jsx index 7b03d47b8f..53e356345e 100644 --- a/static/js/TextRangeV3.jsx +++ b/static/js/TextRangeV3.jsx @@ -8,7 +8,7 @@ import Component from 'react-class'; import {EnglishText, HebrewText} from "./Misc"; import {VersionContent} from "./ContentText"; import {ContentText} from "./ContentText"; -import {getVersionsByRef} from "./sefaria/textManager"; +import {getVersions} from "./sefaria/textManager"; class TextRange extends Component { // A Range or text defined a by a single Ref. Specially treated when set as 'basetext'. @@ -125,7 +125,7 @@ class TextRange extends Component { versionPref: Sefaria.versionPreferences.getVersionPref(this.props.sref), }; // let data = Sefaria.getTextFromCache(this.props.sref, settings); - let data = await getVersionsByRef(this.props.sref, settings); + let data = await getVersions(this.props.sref, {language: 'he', versionTitle: 'base'}, {language: 'en', versionTitle: 'base'}, null); if ((!data || "updateFromAPI" in data) && !this.textLoading) { // If we don't have data yet, call trigger an API call this.textLoading = true; @@ -134,16 +134,7 @@ class TextRange extends Component { } else if (!!data && this.props.isCurrentlyVisible) { this._updateCurrVersions(data.versionTitle, data.heVersionTitle); } - - const {source, translation} = data.reduce((acc, item) => item.versions.some(v => v.isBaseText) ? { ...acc, source: item } : { ...acc, translation: item }, {}); - // this is a hack that takes the first version of the source and translation and puts it in the source object - // this is done so that the source object can be passed to the ContentText component. In the past the endpoint returned - // the the full version info at the top level of the object, but now it is nested in the versions array - const textData = source; - textData.he = source?.versions ? source.versions[0].text : null; - textData.text = translation?.versions ? translation.versions[0]?.text : null; - textData.en = translation?.versions ? translation.versions[0]?.text : null; - return textData; + return data; } async onTextLoad(data) { // Initiate additional API calls when text data first loads @@ -226,9 +217,11 @@ class TextRange extends Component { translationLanguagePreference: this.props.translationLanguagePreference, versionPref: Sefaria.versionPreferences.getVersionPref(data.next), }; - const nextTextPromise = getVersionsByRef(data.next, nextSettings); + const nextTextPromise = getVersions(data.next, {language: 'he', versionTitle: 'base'}, {language: 'en', versionTitle: 'base'}, null); // const nextTextPromise = Sefaria.getText(data.next, nextSettings); - nextTextPromise.then(ds => Array.isArray(ds) ? ds.map(d => this._prefetchLinksAndNotes(d)) : this._prefetchLinksAndNotes(ds)); + nextTextPromise.then(data => { + this._prefetchLinksAndNotes(data); + }); } if (data.prev) { const prevSettings = { @@ -239,9 +232,11 @@ class TextRange extends Component { translationLanguagePreference: this.props.translationLanguagePreference, versionPref: Sefaria.versionPreferences.getVersionPref(data.prev), }; - const prevTextPromise = getVersionsByRef(data.prev, prevSettings); + const prevTextPromise = getVersions(data.prev, {language: 'he', versionTitle: 'base'}, {language: 'en', versionTitle: 'base'}, null); // const prevTextPromise = Sefaria.getText(data.prev, prevSettings); - prevTextPromise.then(ds => Array.isArray(ds) ? ds.map(d => this._prefetchLinksAndNotes(d)) : this._prefetchLinksAndNotes(ds)); + prevTextPromise.then(data => { + this._prefetchLinksAndNotes(data); + }); } if (data.indexTitle) { // Preload data that is used on Text TOC page @@ -355,7 +350,7 @@ class TextRange extends Component { strip_vowels_re = (this.props.settings.vowels == "partial") ? nre : cnre; } - let segments = Sefaria.makeSegments(data, this.props.withContext); + let segments = Sefaria.makeSegmentsV3(data, this.props.withContext); if(segments.length > 0 && strip_vowels_re && !strip_vowels_re.test(segments[0].he)){ strip_vowels_re = null; //if the first segment doesnt even match as containing vowels or cantillation- stop } @@ -380,8 +375,8 @@ class TextRange extends Component { ); } } - segment.he = strip_vowels_re ? segment.he.replace(strip_vowels_re, "") : segment.he; - segment.he = strip_punctuation_re ? segment.he.replace(strip_punctuation_re, "") : segment.he; + segment.source = strip_vowels_re ? segment.source.replace(strip_vowels_re, "") : segment.source; + segment.source = strip_punctuation_re ? segment.source.replace(strip_punctuation_re, "") : segment.source; return ( @@ -390,8 +385,8 @@ class TextRange extends Component { sref={segment.ref} enLangCode={this.props.currVersions.en && /\[([a-z][a-z][a-z]?)\]$/.test(this.props.currVersions.en) ? /\[([a-z][a-z][a-z]?)\]$/.exec(this.props.currVersions.en)[1] : 'en'} heLangCode={this.props.currVersions.he && /\[([a-z][a-z][a-z]?)\]$/.test(this.props.currVersions.he) ? /\[([a-z][a-z][a-z]?)\]$/.exec(this.props.currVersions.he)[1] : 'he'} - en={!this.props.useVersionLanguage || this.props.currVersions.en ? segment.en : null} - he={!this.props.useVersionLanguage || this.props.currVersions.he ? segment.he : null} + en={!this.props.useVersionLanguage || this.props.currVersions.en ? segment.translation : null} + he={!this.props.useVersionLanguage || this.props.currVersions.he ? segment.source : null} highlight={highlight} showHighlight={this.props.showHighlight} textHighlights={textHighlights} diff --git a/static/js/sefaria/sefaria.js b/static/js/sefaria/sefaria.js index 89a3376053..db3fb642fc 100644 --- a/static/js/sefaria/sefaria.js +++ b/static/js/sefaria/sefaria.js @@ -2000,6 +2000,73 @@ _media: {}, } return segments; }, + makeSegmentsV3: function(data, withContext, sheets=false) { + // Returns a flat list of annotated segment objects, + // derived from the walking the text in data + if (!data || "error" in data) { return []; } + var segments = []; + var highlight = data.sections.length === data.textDepth; + var wrapTranslation = (typeof data.translation.text == "string"); + var wrapSource = (typeof data.source.text == "string"); + var translation = wrapTranslation ? [data.translation.text] : data.translation.text; + var source = wrapSource ? [data.source.text] : data.source.text; + var topLength = Math.max(translation.length, source.length); + translation = translation.pad(topLength, ""); + source = source.pad(topLength, ""); + + const index_offsets_by_depth = this._get_offsets(data, topLength); + var start = (data.textDepth == data.sections.length && !withContext ? + data.sections.slice(-1)[0] : 1+index_offsets_by_depth[0]); + if (!data.isSpanning) { + for (var i = 0; i < topLength; i++) { + var number = i+start; + var delim = data.textDepth == 1 ? " " : ":"; + var ref = data.sectionRef + delim + number; + segments.push({ + ref: ref, + translation: translation[i], + source: source[i], + number: number, + highlight: highlight && number >= data.sections.slice(-1)[0] && number <= data.toSections.slice(-1)[0], + alt: ("alts" in data && i < data.alts.length) ? data.alts[i] : null + }); + } + } else { + for (var n = 0; n < topLength; n++) { + var translation2 = typeof translation[n] == "string" ? [translation[n]] : translation[n]; + var source2 = typeof source[n] == "string" ? [source[n]] : source[n]; + var length = Math.max(translation2.length, source2.length); + translation2 = translation2.pad(length, ""); + source2 = source2.pad(length, ""); + var baseRef = data.book; + var baseSection = data.sections.slice(0,-2).join(":"); + var delim = baseSection ? ":" : " "; + var baseRef = baseSection ? baseRef + " " + baseSection : baseRef; + + start = (n == 0 ? start : 1+index_offsets_by_depth[n]); + for (var i = 0; i < length; i++) { + var startSection = data.sections.slice(-2)[0]; + var section = typeof startSection == "string" ? + Sefaria.hebrew.intToDaf(n+Sefaria.hebrew.dafToInt(startSection)) + : n + startSection; + var number = i + start; + var ref = baseRef + delim + section + ":" + number; + segments.push({ + ref: ref, + translation: translation2[i], + source: source2[i], + number: number, + highlight: highlight && + ((n == 0 && number >= data.sections.slice(-1)[0]) || + (n == topLength-1 && number <= data.toSections.slice(-1)[0]) || + (n > 0 && n < topLength -1)), + alt: ("alts" in data && n < data.alts.length && i < data.alts[n].length) ? data.alts[n][i] : null + }); + } + } + } + return segments; + }, stripImagesFromSegments: function(segments) { // Used by sheets editors. Sefaria.makeSegments creates a list of segments and this function handles the images. return segments.map(x => {