Skip to content

Commit

Permalink
Fix defaultLocale ignored in dependent styles zotero#272
Browse files Browse the repository at this point in the history
  • Loading branch information
tnajdek committed Aug 16, 2021
1 parent 4b809d2 commit 46b992c
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 44 deletions.
25 changes: 15 additions & 10 deletions src/js/citeproc-wrapper.js
Expand Up @@ -77,16 +77,16 @@ const syncRequestAsText = url => {
class CiteprocWrapper {
constructor(isLegacy, engine, opts) {
this.isLegacy = isLegacy;
this.opts = opts;
if(isLegacy) {
this.CSL = engine;
this.opts = opts;
this.itemsStore = {};
this.clustersStore = [];
this.driver = new this.CSL.Engine({
retrieveLocale: retrieveLocaleSync,
retrieveItem: itemId => this.itemsStore[itemId],
uppercase_subtitles: getStyleProperties(opts.style)?.isUppercaseSubtitlesStyle,
}, opts.style, opts.lang);
}, opts.style, opts.localeOverride || opts.lang, !!opts.localeOverride);
this.driver.setOutputFormat(opts.format);
this.driver.opt.development_extensions.wrap_url_and_doi = opts.wrap_url_and_doi;
} else {
Expand Down Expand Up @@ -300,12 +300,17 @@ class CiteprocWrapper {
}
}

setStyle(style_text) {
setStyle(newStyleXml, newLocaleOverride = null) {
if(this.isLegacy) {
// citeprocJS doesn't seem to be able to set style so we recreate the driver
this.recreateEngine({ style: style_text });
this.recreateEngine({ style: newStyleXml, localeOverride: newLocaleOverride });
} else {
return this.driver.setStyle(style_text).unwrap();
if(newLocaleOverride !== this.opts.localeOverride) {
// TODO
throw new Error("CiteprocRS does not support changing locale override.")
} else {
return this.driver.setStyle(newStyleXml).unwrap();
}
}
}

Expand All @@ -317,7 +322,7 @@ class CiteprocWrapper {
retrieveLocale: retrieveLocaleSync,
retrieveItem: itemId => this.itemsStore[itemId],
uppercase_subtitles: getStyleProperties(this.opts.style)?.isUppercaseSubtitlesStyle
}, this.opts.style, this.opts.lang);
}, this.opts.style, this.opts.localeOverride || this.opts.lang, !!this.opts.localeOverride);
this.driver.setOutputFormat(this.opts.format);
this.driver.opt.development_extensions.wrap_url_and_doi = this.opts.wrap_url_and_doi;
}
Expand Down Expand Up @@ -360,7 +365,7 @@ const getCiteprocRSLoader = async () => {
});
}

CiteprocWrapper.new = async ({ style, format = 'html', lang = null, wrap_url_and_doi = false }, useLegacy = null, DriverORCSL = null) => {
CiteprocWrapper.new = async ({ style, format = 'html', lang = null, localeOverride = null, wrap_url_and_doi = false }, useLegacy = null, DriverORCSL = null) => {
const userLocales = lang ? lang : window ? (window.navigator.languages || window.navigator.userLanguage || window.navigator.language) : null;
lang = pickBestLocale(userLocales, supportedLocales);
useLegacy = useLegacy === null ? !isWasmSupported : useLegacy;
Expand All @@ -371,7 +376,7 @@ CiteprocWrapper.new = async ({ style, format = 'html', lang = null, wrap_url_and
if(format === 'plain') {
format = 'text';
}
return new CiteprocWrapper(true, CSL, { style, format, lang, wrap_url_and_doi });
return new CiteprocWrapper(true, CSL, { style, format, lang, localeOverride, wrap_url_and_doi });
} else {
if(!Driver) {
if(DriverORCSL) {
Expand All @@ -385,10 +390,10 @@ CiteprocWrapper.new = async ({ style, format = 'html', lang = null, wrap_url_and
}
const fetcher = new Fetcher();
// NOTE: wrap_url_and_doi is not supported in citeproc rs (yet?)
const driverResult = Driver.new({ localeOverride: lang, format, style, fetcher });
const driverResult = Driver.new({ localeOverride, format, style, fetcher });
const driver = driverResult.unwrap();
await driver.fetchLocales();
return new CiteprocWrapper(false, driver);
return new CiteprocWrapper(false, driver, { style, format, lang, localeOverride, wrap_url_and_doi, Driver });
}
} catch(err) {
console.error(err);
Expand Down
50 changes: 29 additions & 21 deletions src/js/common/citation-style.js
@@ -1,4 +1,5 @@
import { fetchWithCachedFallback } from '../utils'
import { omit } from '../immutable';

const stylePropertiesCache = new Map();
const stylesCache = new Map();
Expand Down Expand Up @@ -35,35 +36,42 @@ const getStyleProperties = citationStyleXml => {
const isNoteStyle = xmlDoc.querySelector('info > category[citation-format^="note"]') !== null;
const isUppercaseSubtitlesStyle = checkUppercase(citationStyleName) || checkUppercase(parentStyleName);
const isSentenceCaseStyle = checkSentenceCase(citationStyleName) || checkSentenceCase(parentStyleName);
const defaultLocale = xmlDoc.querySelector('style')?.getAttribute('default-locale');

stylePropertiesCache.set(citationStyleXml, { citationStyleName, parentStyleName, styleHasBibliography,
isNumericStyle, isNoteStyle, isUppercaseSubtitlesStyle, isSentenceCaseStyle, });
stylePropertiesCache.set(citationStyleXml, { citationStyleName, defaultLocale,
parentStyleName, styleHasBibliography, isNumericStyle, isNoteStyle,
isUppercaseSubtitlesStyle, isSentenceCaseStyle, });
}

return stylePropertiesCache.get(citationStyleXml);
}

const fetchAndParseIndependentStyle = async styleName => {
let nextStyleName = styleName, styleXml, styleProps;

do {
if(stylesCache.has(nextStyleName)) {
styleXml = stylesCache.get(nextStyleName);
} else {
const url = `https://www.zotero.org/styles/${nextStyleName}`;
const response = await fetchWithCachedFallback(url);
if(!response.ok) {
throw new Error(`Failed to fetch ${nextStyleName} from ${url}`);
}
styleXml = await response.text();
stylesCache.set(nextStyleName, styleXml);
const fetchAndParseStyle = async styleName => {
let styleXml, styleProps;
if(stylesCache.has(styleName)) {
styleXml = stylesCache.get(styleName);
} else {
const url = `https://www.zotero.org/styles/${styleName}`;
const response = await fetchWithCachedFallback(url);
if(!response.ok) {
throw new Error(`Failed to fetch ${styleName} from ${url}`);
}
styleProps = getStyleProperties(styleXml);
const { parentStyleName } = styleProps
nextStyleName = parentStyleName;
} while(nextStyleName);
styleXml = await response.text();
stylesCache.set(styleName, styleXml);
}
styleProps = getStyleProperties(styleXml);
return { styleName, styleXml, styleProps }
}

const fetchAndParseIndependentStyle = async styleName => {
const { styleXml, styleProps } = await fetchAndParseStyle(styleName);
const { styleXml: parentStyleXml, styleProps: parentStyleProps } = (styleProps.parentStyleName ?
await fetchAndParseStyle(styleProps.parentStyleName) : {});

return { styleName, styleXml, styleProps };
return { styleName, styleXml, parentStyleXml, styleProps: {
...styleProps,
...omit((parentStyleProps || {}), ['parentStyleName', 'defaultLocale']),
}};
}

export { fetchAndParseIndependentStyle, getStyleProperties };
28 changes: 15 additions & 13 deletions src/js/components/container.jsx
Expand Up @@ -47,9 +47,9 @@ const CLEAR_ALL_MESSAGES = 'CLEAR_ALL_MESSAGES';
const fetchAndSelectStyle = async (dispatch, styleName, opts = {}) => {
dispatch({ type: REQUEST_FETCH_STYLE, styleName });
try {
const { styleName: independentStyleName, styleXml, styleProps } = await fetchAndParseIndependentStyle(styleName);
const styleData = await fetchAndParseIndependentStyle(styleName);
dispatch({
type: RECEIVE_FETCH_STYLE, styleName: independentStyleName, styleXml, styleProps, ...opts
type: RECEIVE_FETCH_STYLE, ...styleData, ...opts
});
} catch (error) {
dispatch({ type: ERROR_FETCH_STYLE, styleName, error });
Expand All @@ -69,9 +69,11 @@ const reducer = (state, action) => {
...state,
isFetching: false,
bibliographyNeedsRebuild: true,
selected: action.styleName,
xml: action.styleXml,
selected: action.styleName, // in case of dependant style, this is the name of the parent style
xml: action.parentStyleXml ?? action.styleXml,
isDependent: !!action.styleProps.parentStyleName,
isConfirmed: typeof(action.isConfirmed) === 'boolean' ? action.isConfirmed : !action.styleProps.isSentenceCaseStyle,
localeOverride: action.styleProps.parentStyleName ? action.styleProps.defaultLocale : null,
...pick(
action.styleProps,
['styleHasBibliography', 'isNumericStyle', 'isNoteStyle', 'isUppercaseSubtitlesStyle', 'isSentenceCaseStyle']
Expand Down Expand Up @@ -159,6 +161,8 @@ const BibWebContainer = props => {
selected: undefined,
xml: undefined,
isFetching: false,
isDependent: false,
localeOverride: null,
styleHasBibliography: undefined,
isNumericStyle: undefined,
isNoteStyle: undefined,
Expand Down Expand Up @@ -226,15 +230,13 @@ const BibWebContainer = props => {
const buildBibliography = useCallback(async () => {
dispatch({ type: BEGIN_BUILD_BIBLIOGRAPHY });

if(citeproc.current) {
citeproc.current.setStyle(state.xml);
} else {
citeproc.current = await CiteprocWrapper.new({
style: state.xml,
format: 'html',
wrap_url_and_doi: isReadOnly
}, useLegacy.current);
}
//TODO: if citeproc.current use setStyle on CiteprocWrapper, once it supports localeOverride
citeproc.current = await CiteprocWrapper.new({
style: state.xml,
format: 'html',
localeOverride: state.localeOverride,
wrap_url_and_doi: isReadOnly
}, useLegacy.current);

const t0 = performance.now();
citeproc.current.includeUncited("All");
Expand Down

0 comments on commit 46b992c

Please sign in to comment.