Skip to content

Commit 4059e7a

Browse files
Add ConfigLoader with deduplicated logging and try_examples config caching (#249)
1 parent 7702294 commit 4059e7a

File tree

1 file changed

+73
-41
lines changed

1 file changed

+73
-41
lines changed

jupyterlite_sphinx/jupyterlite_sphinx.js

Lines changed: 73 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -149,55 +149,87 @@ var tryExamplesGlobalMinHeight = 0;
149149
*/
150150
var tryExamplesConfigLoaded = false;
151151

152-
window.loadTryExamplesConfig = async (configFilePath) => {
153-
if (tryExamplesConfigLoaded) {
154-
return;
155-
}
156-
try {
157-
// Add a timestamp as query parameter to ensure a cached version of the
158-
// file is not used.
159-
const timestamp = new Date().getTime();
160-
const configFileUrl = `${configFilePath}?cb=${timestamp}`;
161-
const currentPageUrl = window.location.pathname;
162-
163-
const response = await fetch(configFileUrl);
164-
if (!response.ok) {
165-
if (response.status === 404) {
166-
// Try examples ignore file is not present.
167-
console.log("Optional try_examples config file not found.");
168-
return;
169-
}
170-
throw new Error(`Error fetching ${configFilePath}`);
171-
}
152+
// A config loader with request deduplication + permanent caching
153+
const ConfigLoader = (() => {
154+
let configLoadPromise = null;
172155

173-
const data = await response.json();
174-
if (!data) {
156+
const loadConfig = async (configFilePath) => {
157+
if (tryExamplesConfigLoaded) {
175158
return;
176159
}
177160

178-
// Set minimum iframe height based on value in config file
179-
if (data.global_min_height) {
180-
tryExamplesGlobalMinHeight = parseInt(data.global_min_height);
161+
// Return the existing promise if the request is in progress, as we
162+
// don't want to make multiple requests for the same file. This
163+
// can happen if there are several try_examples directives on the
164+
// same page.
165+
if (configLoadPromise) {
166+
return configLoadPromise;
181167
}
182168

183-
// Disable interactive examples if file matches one of the ignore patterns
184-
// by hiding try_examples_buttons.
185-
Patterns = data.ignore_patterns;
186-
for (let pattern of Patterns) {
187-
let regex = new RegExp(pattern);
188-
if (regex.test(currentPageUrl)) {
189-
var buttons = document.getElementsByClassName("try_examples_button");
190-
for (var i = 0; i < buttons.length; i++) {
191-
buttons[i].classList.add("hidden");
169+
// Create and cache the promise for the config request
170+
configLoadPromise = (async () => {
171+
try {
172+
// Add a timestamp as query parameter to ensure a cached version of the
173+
// file is not used.
174+
const timestamp = new Date().getTime();
175+
const configFileUrl = `${configFilePath}?cb=${timestamp}`;
176+
const currentPageUrl = window.location.pathname;
177+
178+
const response = await fetch(configFileUrl);
179+
if (!response.ok) {
180+
if (response.status === 404) {
181+
console.log("Optional try_examples config file not found.");
182+
return;
183+
}
184+
throw new Error(`Error fetching ${configFilePath}`);
185+
}
186+
187+
const data = await response.json();
188+
if (!data) {
189+
return;
190+
}
191+
192+
// Set minimum iframe height based on value in config file
193+
if (data.global_min_height) {
194+
tryExamplesGlobalMinHeight = parseInt(data.global_min_height);
195+
}
196+
197+
// Disable interactive examples if file matches one of the ignore patterns
198+
// by hiding try_examples_buttons.
199+
Patterns = data.ignore_patterns;
200+
for (let pattern of Patterns) {
201+
let regex = new RegExp(pattern);
202+
if (regex.test(currentPageUrl)) {
203+
var buttons = document.getElementsByClassName(
204+
"try_examples_button",
205+
);
206+
for (var i = 0; i < buttons.length; i++) {
207+
buttons[i].classList.add("hidden");
208+
}
209+
break;
210+
}
192211
}
193-
break;
212+
} catch (error) {
213+
console.error(error);
214+
} finally {
215+
tryExamplesConfigLoaded = true;
194216
}
195-
}
196-
} catch (error) {
197-
console.error(error);
198-
}
199-
tryExamplesConfigLoaded = true;
200-
};
217+
})();
218+
219+
return configLoadPromise;
220+
};
221+
222+
return {
223+
loadConfig,
224+
// for testing/debugging only, could be removed
225+
resetState: () => {
226+
tryExamplesConfigLoaded = false;
227+
configLoadPromise = null;
228+
},
229+
};
230+
})();
231+
232+
window.loadTryExamplesConfig = ConfigLoader.loadConfig;
201233

202234
window.toggleTryExamplesButtons = () => {
203235
/* Toggle visibility of TryExamples buttons. For use in console for debug

0 commit comments

Comments
 (0)