diff --git a/htdocs/css/rtl.css b/htdocs/css/rtl.css
index 95691f2401..8a2379a99c 100644
--- a/htdocs/css/rtl.css
+++ b/htdocs/css/rtl.css
@@ -17,4 +17,3 @@
/* The changes which were needed here in WeBWorK 2.16 are no
* longer needed in WeBWorK 2.17. The file is being retained
* for potential future use. */
-
diff --git a/htdocs/generate-assets.js b/htdocs/generate-assets.js
index 5f275e266f..81ee6c7b10 100755
--- a/htdocs/generate-assets.js
+++ b/htdocs/generate-assets.js
@@ -15,7 +15,10 @@ const rtlcss = require('rtlcss');
const cssMinify = require('cssnano');
const argv = yargs
- .usage('$0 Options').version(false).alias('help', 'h').wrap(100)
+ .usage('$0 Options')
+ .version(false)
+ .alias('help', 'h')
+ .wrap(100)
.option('enable-sourcemaps', {
alias: 's',
description: 'Generate source maps. (Not for use in production!)',
@@ -30,8 +33,7 @@ const argv = yargs
alias: 'd',
description: 'Delete all generated files.',
type: 'boolean'
- })
- .argv;
+ }).argv;
const assetFile = path.resolve(__dirname, 'static-assets.json');
const assets = {};
@@ -48,7 +50,7 @@ const cleanDir = (dir) => {
}
}
}
-}
+};
// The is set to true after all files are processed for the first time.
let ready = false;
@@ -75,12 +77,13 @@ const processFile = async (file, _details) => {
return;
}
- const minJS = result.code + (
- argv.enableSourcemaps && result.map
- ? `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${
- Buffer.from(result.map).toString('base64')}`
- : ''
- );
+ const minJS =
+ result.code +
+ (argv.enableSourcemaps && result.map
+ ? `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${Buffer.from(
+ result.map
+ ).toString('base64')}`
+ : '');
const contentHash = crypto.createHash('sha256');
contentHash.update(minJS);
@@ -114,18 +117,19 @@ const processFile = async (file, _details) => {
return;
}
- if (result.sourceMap) result.sourceMap.sources = [ baseName ];
+ if (result.sourceMap) result.sourceMap.sources = [baseName];
// Pass the compiled css through the autoprefixer.
// This is really only needed for the bootstrap.css files, but doesn't hurt for the rest.
let prefixedResult = await postcss([autoprefixer, cssMinify]).process(result.css, { from: baseName });
- const minCSS = prefixedResult.css + (
- argv.enableSourcemaps && result.sourceMap
- ? `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${
- Buffer.from(JSON.stringify(result.sourceMap)).toString('base64')}*/`
- : ''
- );
+ const minCSS =
+ prefixedResult.css +
+ (argv.enableSourcemaps && result.sourceMap
+ ? `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${Buffer.from(
+ JSON.stringify(result.sourceMap)
+ ).toString('base64')}*/`
+ : '');
const contentHash = crypto.createHash('sha256');
contentHash.update(minCSS);
@@ -149,18 +153,21 @@ const processFile = async (file, _details) => {
// Pass the compiled css through rtlcss and autoprefixer to generate css for right-to-left languages.
let rtlResult = await postcss([rtlcss, autoprefixer, cssMinify]).process(result.css, { from: baseName });
- const rtlCSS = rtlResult.css + (
- argv.enableSourcemaps && result.sourceMap
- ? `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${
- Buffer.from(JSON.stringify(result.sourceMap)).toString('base64')}*/`
- : ''
- );
+ const rtlCSS =
+ rtlResult.css +
+ (argv.enableSourcemaps && result.sourceMap
+ ? `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${Buffer.from(
+ JSON.stringify(result.sourceMap)
+ ).toString('base64')}*/`
+ : '');
const rtlContentHash = crypto.createHash('sha256');
rtlContentHash.update(rtlCSS);
- const newRTLVersion = file.replace(/\.s?css$/,
- `.rtl.${rtlContentHash.digest('hex').substring(0, 8)}.min.css`);
+ const newRTLVersion = file.replace(
+ /\.s?css$/,
+ `.rtl.${rtlContentHash.digest('hex').substring(0, 8)}.min.css`
+ );
fs.writeFileSync(path.resolve(__dirname, newRTLVersion), rtlCSS);
const rtlAssetName = file.replace(/\.s?css$/, '.rtl.css');
@@ -180,8 +187,9 @@ const processFile = async (file, _details) => {
}
} else {
if (argv.watchFiles)
- console.log('\x1b[33mWatches established, and initial build complete.\n'
- + 'Press Control-C to stop.\x1b[0m');
+ console.log(
+ '\x1b[33mWatches established, and initial build complete.\n' + 'Press Control-C to stop.\x1b[0m'
+ );
ready = true;
}
@@ -202,20 +210,25 @@ for (const file of fs.readdirSync(themesDir, { withFileTypes: true })) {
if (!file.isDirectory()) continue;
if (!fs.existsSync(path.resolve(themesDir, file.name, 'math4-overrides.js')))
fs.closeSync(fs.openSync(path.resolve(themesDir, file.name, 'math4-overrides.js'), 'w'));
- if (!fs.existsSync(path.resolve(themesDir, file.name, 'math4-overrides.css'))
- && !fs.existsSync(path.resolve(themesDir, file.name, 'math4-overrides.scss')))
+ if (
+ !fs.existsSync(path.resolve(themesDir, file.name, 'math4-overrides.css')) &&
+ !fs.existsSync(path.resolve(themesDir, file.name, 'math4-overrides.scss'))
+ )
fs.closeSync(fs.openSync(path.resolve(themesDir, file.name, 'math4-overrides.css'), 'w'));
}
// Set up the watcher.
if (argv.watchFiles) console.log('\x1b[32mEstablishing watches and performing initial build.\x1b[0m');
-chokidar.watch(['js', 'themes'], {
- ignored: /layouts|\.min\.(js|css)$/,
- cwd: __dirname, // Make sure all paths are given relative to the htdocs directory.
- awaitWriteFinish: { stabilityThreshold: 500 },
- persistent: argv.watchFiles ? true : false
-})
- .on('add', processFile).on('change', processFile).on('ready', processFile)
+chokidar
+ .watch(['js', 'themes'], {
+ ignored: /layouts|\.min\.(js|css)$/,
+ cwd: __dirname, // Make sure all paths are given relative to the htdocs directory.
+ awaitWriteFinish: { stabilityThreshold: 500 },
+ persistent: argv.watchFiles ? true : false
+ })
+ .on('add', processFile)
+ .on('change', processFile)
+ .on('ready', processFile)
.on('unlink', (file) => {
// If a file is deleted, then also delete the corresponding generated file.
if (assets[file]) {
diff --git a/htdocs/index.dist.html b/htdocs/index.dist.html
index 532c6f4032..a82efd7355 100644
--- a/htdocs/index.dist.html
+++ b/htdocs/index.dist.html
@@ -1,4 +1,4 @@
-
+
This is the default page for the root url of this site.
If you want to see something better here, then copy webwork2/htdocs/index.dist.html (this file) to
- webwork/htdocs/index.html, and modify it to show what you want to show. Then that file will be displayed
+ webwork/htdocs/index.html, and modify it to show what you want to show. Then that file will be displayed
instead.
diff --git a/htdocs/js/DatePicker/datepicker.js b/htdocs/js/DatePicker/datepicker.js
index bdaef40623..3cbe63dfc6 100644
--- a/htdocs/js/DatePicker/datepicker.js
+++ b/htdocs/js/DatePicker/datepicker.js
@@ -50,11 +50,11 @@
// Compute the time difference between the current browser timezone and the course timezone.
// flatpickr gives the time in the browser's timezone, and this is used to adjust to the course timezone.
// Note that this is in seconds.
- const timezoneAdjustment = (
- (new Date((new Date).toLocaleString('en-US'))).getTime() -
- (new Date((new Date).toLocaleString('en-US',
- { timeZone: rule.dataset.timezone ?? 'America/New_York' }))).getTime()
- );
+ const timezoneAdjustment =
+ new Date(new Date().toLocaleString('en-US')).getTime() -
+ new Date(
+ new Date().toLocaleString('en-US', { timeZone: rule.dataset.timezone ?? 'America/New_York' })
+ ).getTime();
const fp = flatpickr(rule.parentNode, {
allowInput: true,
diff --git a/htdocs/js/GatewayQuiz/gateway.js b/htdocs/js/GatewayQuiz/gateway.js
index 09f97d2c63..26ddd35fc1 100644
--- a/htdocs/js/GatewayQuiz/gateway.js
+++ b/htdocs/js/GatewayQuiz/gateway.js
@@ -12,9 +12,10 @@
const timerDiv = document.getElementById('gwTimer'); // The timer div element
let actuallySubmit = false; // This needs to be set to true to allow an actual submission.
// The 'Grade Test' submit button.
- const submitAnswers = document.gwquiz.elements.submitAnswers instanceof NodeList
- ? document.gwquiz.elements.submitAnswers[document.gwquiz.elements.submitAnswers.length - 1]
- : document.gwquiz.elements.submitAnswers;
+ const submitAnswers =
+ document.gwquiz.elements.submitAnswers instanceof NodeList
+ ? document.gwquiz.elements.submitAnswers[document.gwquiz.elements.submitAnswers.length - 1]
+ : document.gwquiz.elements.submitAnswers;
let timeDelta; // The difference between the browser time and the server time
let serverDueTime; // The time the test is due
let gracePeriod; // The grace period
@@ -32,7 +33,14 @@
const alertToast = (message, delay = 5000) => {
const toastContainer = document.createElement('div');
toastContainer.classList.add(
- 'gwAlert', 'toast-container', 'position-fixed', 'top-0', 'start-50', 'translate-middle-x', 'p-3');
+ 'gwAlert',
+ 'toast-container',
+ 'position-fixed',
+ 'top-0',
+ 'start-50',
+ 'translate-middle-x',
+ 'p-3'
+ );
toastContainer.innerHTML =
'
' +
'';
document.body.prepend(toastContainer);
const bsToast = new bootstrap.Toast(toastContainer.firstElementChild, { delay });
- toastContainer.addEventListener('hidden.bs.toast', () => { bsToast.dispose(); toastContainer.remove(); })
+ toastContainer.addEventListener('hidden.bs.toast', () => {
+ bsToast.dispose();
+ toastContainer.remove();
+ });
bsToast.show();
};
@@ -72,23 +83,29 @@
submitAnswers.click();
} else if (remainingTime > 10 - gracePeriod && remainingTime <= 0) {
if (alertStatus !== '1') {
- alertToast(timerDiv.dataset.alertOne ??
- '
You are out of time!
Press "Grade Test" now!
',
- (remainingTime + gracePeriod) * 1000);
+ alertToast(
+ timerDiv.dataset.alertOne ??
+ '
You are out of time!
Press "Grade Test" now!
',
+ (remainingTime + gracePeriod) * 1000
+ );
sessionStorage.setItem('gatewayAlertStatus', '1');
}
} else if (remainingTime > 0 && remainingTime <= 45) {
if (alertStatus !== '2') {
- alertToast(timerDiv.dataset.alertTwo ??
- '
You have less than 45 seconds left!
Press "Grade Test" soon!
',
- remainingTime * 1000);
+ alertToast(
+ timerDiv.dataset.alertTwo ??
+ '
You have less than 45 seconds left!
Press "Grade Test" soon!
',
+ remainingTime * 1000
+ );
sessionStorage.setItem('gatewayAlertStatus', '2');
}
} else if (remainingTime > 45 && remainingTime <= 90) {
if (alertStatus !== '3') {
- alertToast(timerDiv.dataset.alertThree ??
- 'You have less than 90 seconds left to complete this assignment. You should finish it soon!',
- (remainingTime - 45) * 1000);
+ alertToast(
+ timerDiv.dataset.alertThree ??
+ 'You have less than 90 seconds left to complete this assignment. You should finish it soon!',
+ (remainingTime - 45) * 1000
+ );
sessionStorage.setItem('gatewayAlertStatus', '3');
}
}
@@ -122,15 +139,17 @@
setInterval(updateTimer, 1000);
}
}
- };
+ }
// Show a confirmation dialog when a student clicks 'Grade Test'.
if (typeof submitAnswers?.dataset?.confirmDialogMessage !== 'undefined') {
submitAnswers.addEventListener('click', (evt) => {
// Don't show the dialog if the test is timed and in the last 90 seconds.
// The alerts above are now being shown telling the student to submit the test.
- if (typeof serverDueTime !== 'undefined' &&
- serverDueTime - Math.round(new Date().getTime() / 1000) + timeDelta < 90)
+ if (
+ typeof serverDueTime !== 'undefined' &&
+ serverDueTime - Math.round(new Date().getTime() / 1000) + timeDelta < 90
+ )
return;
if (actuallySubmit) return;
@@ -196,7 +215,10 @@
const bsModal = new bootstrap.Modal(modal);
bsModal.show();
- modal.addEventListener('hidden.bs.modal', () => { bsModal.dispose(); modal.remove(); });
+ modal.addEventListener('hidden.bs.modal', () => {
+ bsModal.dispose();
+ modal.remove();
+ });
});
}
@@ -214,7 +236,7 @@
document.querySelectorAll('.problem-jump-link').forEach((jumpLink) => {
jumpLink.addEventListener('click', (evt) => {
// Prevent the link from being followed.
- evt.preventDefault()
+ evt.preventDefault();
if (jumpLink.dataset.problemNumber) {
// Note that the anchor indexing starts at 0, not 1.
const problem = document.getElementById(`prob${parseInt(jumpLink.dataset.problemNumber) - 1}`);
diff --git a/htdocs/js/InstructorTools/instructortools.js b/htdocs/js/InstructorTools/instructortools.js
index 6b41ded95c..6c09bc852a 100644
--- a/htdocs/js/InstructorTools/instructortools.js
+++ b/htdocs/js/InstructorTools/instructortools.js
@@ -2,21 +2,27 @@
const form = document.forms['instructor-tools-form'];
form?.addEventListener('submit', (e) => {
- const selectedUsers = Array.from(document.querySelector('select[name=selected_users]')?.options ?? [])
- .filter((option) => option.selected);
- const selectedSets = Array.from(document.querySelector('select[name=selected_sets]')?.options ?? [])
- .filter((option) => option.selected);
+ const selectedUsers = Array.from(document.querySelector('select[name=selected_users]')?.options ?? []).filter(
+ (option) => option.selected
+ );
+ const selectedSets = Array.from(document.querySelector('select[name=selected_sets]')?.options ?? []).filter(
+ (option) => option.selected
+ );
// Check for the neccessary data for the requested module.
// Show a message and prevent submission if it is missing.
const messages = [];
- if ((e.submitter.dataset.usersNeeded === 'at least one' && !selectedUsers.length) ||
- (e.submitter.dataset.usersNeeded === 'exactly one' && selectedUsers.length !== 1))
+ if (
+ (e.submitter.dataset.usersNeeded === 'at least one' && !selectedUsers.length) ||
+ (e.submitter.dataset.usersNeeded === 'exactly one' && selectedUsers.length !== 1)
+ )
messages.push(e.submitter.dataset.errorUsers);
- if ((e.submitter.dataset.setsNeeded === 'at least one' && !selectedSets.length) ||
+ if (
+ (e.submitter.dataset.setsNeeded === 'at least one' && !selectedSets.length) ||
(e.submitter.dataset.setsNeeded === 'exactly one' && selectedSets.length !== 1) ||
- (e.submitter.dataset.setsNeeded === 'at most one' && selectedSets.length > 1))
+ (e.submitter.dataset.setsNeeded === 'at most one' && selectedSets.length > 1)
+ )
messages.push(e.submitter.dataset.errorSets);
if (e.submitter.dataset.setNameNeeded) {
const newSetName = form.querySelector('input[name="new_set_name"]')?.value ?? '';
diff --git a/htdocs/js/LocalStorage/localstorage.js b/htdocs/js/LocalStorage/localstorage.js
index b20022af33..32d4c148e1 100644
--- a/htdocs/js/LocalStorage/localstorage.js
+++ b/htdocs/js/LocalStorage/localstorage.js
@@ -2,7 +2,8 @@
const container = document.getElementById('problemMainForm');
const storeId = 'wwStickyAnswers';
- const identifier = (document.querySelector("input[name='problemUUID']")?.value ?? '') +
+ const identifier =
+ (document.querySelector("input[name='problemUUID']")?.value ?? '') +
(document.querySelector("input[name='sourceFilePath']")?.value ?? '') +
(document.querySelector("input[name='problemSource']")?.value ?? '') +
(document.querySelector("input[name='problemSeed']")?.value ?? '');
@@ -26,7 +27,7 @@
store[identifier] = problemData;
localStorage.setItem(storeId, JSON.stringify(store));
- }
+ };
container.addEventListener('submit', storeData);
diff --git a/htdocs/js/MathJaxConfig/mathjax-config.js b/htdocs/js/MathJaxConfig/mathjax-config.js
index 033aa0e198..c998d67ce5 100644
--- a/htdocs/js/MathJaxConfig/mathjax-config.js
+++ b/htdocs/js/MathJaxConfig/mathjax-config.js
@@ -1,64 +1,128 @@
if (!window.MathJax) {
window.MathJax = {
- tex: {
- packages: {'[+]': ['noerrors']}
- },
+ tex: { packages: { '[+]': ['noerrors'] } },
loader: { load: ['input/asciimath', '[tex]/noerrors'] },
startup: {
- ready: function() {
+ ready() {
const AM = MathJax.InputJax.AsciiMath.AM;
- // modify existing AsciiMath triggers
- let i = AM.names.indexOf('**');
- AM.symbols[i] = { input: "**", tag: "msup", output: "^", tex: null, ttype: AM.TOKEN.INFIX };
- i = AM.names.indexOf('infty');
+ // Modify existing AsciiMath triggers.
+ AM.symbols[AM.names.indexOf('**')] = {
+ input: '**',
+ tag: 'msup',
+ output: '^',
+ tex: null,
+ ttype: AM.TOKEN.INFIX
+ };
+
+ const i = AM.names.indexOf('infty');
AM.names[i] = 'infinity';
- AM.symbols[i] = { input:"infinity", tag:"mo", output:"\u221E", tex:"infty", ttype:AM.TOKEN.CONST };
+ AM.symbols[i] = { input: 'infinity', tag: 'mo', output: '\u221E', tex: 'infty', ttype: AM.TOKEN.CONST };
- // add AsciiMath triggers for consistency with MathObjects
+ // Add AsciiMath triggers for consistency with MathObjects.
const newTriggers = {
- inf: {precedes:'infinity', symbols:{tag:"mo", output:"\u221E", tex:"infty", ttype:AM.TOKEN.CONST}},
- Infinity:{precedes:'Lambda', symbols:{tag:"mo", output:"\u221E", tex:"infty", ttype:AM.TOKEN.CONST}},
- Inf: {precedes:'Infinity', symbols:{tag:"mo", output:"\u221E", tex:"infty", ttype:AM.TOKEN.CONST}},
- INFINITY:{precedes:'Inf', symbols:{tag:"mo", output:"\u221E", tex:"infty", ttype:AM.TOKEN.CONST}},
- INF: {precedes:'INFINITY', symbols:{tag:"mo", output:"\u221E", tex:"infty", ttype:AM.TOKEN.CONST}},
- none: {precedes:'norm', symbols:{tag:"mtext", output:"NONE", tex:null, ttype:AM.TOKEN.CONST}},
- None: {precedes:'O/', symbols:{tag:"mtext", output:"NONE", tex:null, ttype:AM.TOKEN.CONST}},
- NONE: {precedes:'None', symbols:{tag:"mtext", output:"NONE", tex:null, ttype:AM.TOKEN.CONST}},
- dne: {precedes:'dot', symbols:{tag:"mtext", output:"DNE", tex:null, ttype:AM.TOKEN.CONST}},
- Dne: {precedes:'EE', symbols:{tag:"mtext", output:"DNE", tex:null, ttype:AM.TOKEN.CONST}},
- DNE: {precedes:'Delta', symbols:{tag:"mtext", output:"DNE", tex:null, ttype:AM.TOKEN.CONST}},
- Re: {precedes:'Rightarrow', symbols:{tag:"mi", output:"Re", tex:null, ttype:AM.TOKEN.UNARY, func:true}},
- Im: {precedes:'Inf', symbols:{tag:"mi", output:"Im", tex:null, ttype:AM.TOKEN.UNARY, func:true}},
- log10: {precedes:'lt', symbols:{tag:"mi", output:"log\u2081\u2080", tex:"log_{10}", ttype:AM.TOKEN.UNARY, func:true}},
- U: {precedes:'Xi', symbols:{tag:"mo", output:"\u222A", tex:"cup", ttype:AM.TOKEN.CONST}},
- '><': {precedes:'><|', symbols:{tag:"mo", output:"\u00D7", tex:"times", ttype:AM.TOKEN.CONST}},
+ inf: {
+ precedes: 'infinity',
+ symbols: { tag: 'mo', output: '\u221E', tex: 'infty', ttype: AM.TOKEN.CONST }
+ },
+ Infinity: {
+ precedes: 'Lambda',
+ symbols: { tag: 'mo', output: '\u221E', tex: 'infty', ttype: AM.TOKEN.CONST }
+ },
+ Inf: {
+ precedes: 'Infinity',
+ symbols: { tag: 'mo', output: '\u221E', tex: 'infty', ttype: AM.TOKEN.CONST }
+ },
+ INFINITY: {
+ precedes: 'Inf',
+ symbols: { tag: 'mo', output: '\u221E', tex: 'infty', ttype: AM.TOKEN.CONST }
+ },
+ INF: {
+ precedes: 'INFINITY',
+ symbols: { tag: 'mo', output: '\u221E', tex: 'infty', ttype: AM.TOKEN.CONST }
+ },
+ none: {
+ precedes: 'norm',
+ symbols: { tag: 'mtext', output: 'NONE', tex: null, ttype: AM.TOKEN.CONST }
+ },
+ None: {
+ precedes: 'O/',
+ symbols: { tag: 'mtext', output: 'NONE', tex: null, ttype: AM.TOKEN.CONST }
+ },
+ NONE: {
+ precedes: 'None',
+ symbols: { tag: 'mtext', output: 'NONE', tex: null, ttype: AM.TOKEN.CONST }
+ },
+ dne: {
+ precedes: 'dot',
+ symbols: { tag: 'mtext', output: 'DNE', tex: null, ttype: AM.TOKEN.CONST }
+ },
+ Dne: {
+ precedes: 'EE',
+ symbols: { tag: 'mtext', output: 'DNE', tex: null, ttype: AM.TOKEN.CONST }
+ },
+ DNE: {
+ precedes: 'Delta',
+ symbols: { tag: 'mtext', output: 'DNE', tex: null, ttype: AM.TOKEN.CONST }
+ },
+ Re: {
+ precedes: 'Rightarrow',
+ symbols: { tag: 'mi', output: 'Re', tex: null, ttype: AM.TOKEN.UNARY, func: true }
+ },
+ Im: {
+ precedes: 'Inf',
+ symbols: { tag: 'mi', output: 'Im', tex: null, ttype: AM.TOKEN.UNARY, func: true }
+ },
+ log10: {
+ precedes: 'lt',
+ symbols: {
+ tag: 'mi',
+ output: 'log\u2081\u2080',
+ tex: 'log_{10}',
+ ttype: AM.TOKEN.UNARY,
+ func: true
+ }
+ },
+ U: {
+ precedes: 'Xi',
+ symbols: { tag: 'mo', output: '\u222A', tex: 'cup', ttype: AM.TOKEN.CONST }
+ },
+ '><': {
+ precedes: '><|',
+ symbols: { tag: 'mo', output: '\u00D7', tex: 'times', ttype: AM.TOKEN.CONST }
+ }
};
for (const trigger in newTriggers) {
const i = AM.names.indexOf(newTriggers[trigger].precedes);
AM.names.splice(i, 0, trigger);
- AM.symbols.splice(i, 0, {input:trigger, ...newTriggers[trigger].symbols});
+ AM.symbols.splice(i, 0, { input: trigger, ...newTriggers[trigger].symbols });
}
- return MathJax.startup.defaultReady()
+ return MathJax.startup.defaultReady();
}
},
options: {
renderActions: {
- findScript: [10, function (doc) {
- document.querySelectorAll('script[type^="math/tex"]').forEach(function(node) {
- var display = !!node.type.match(/; *mode=display/);
- var math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
- var text = document.createTextNode('');
- node.parentNode.replaceChild(text, node);
- math.start = {node: text, delim: '', n: 0};
- math.end = {node: text, delim: '', n: 0};
- doc.math.push(math);
- });
- }, '']
+ findScript: [
+ 10,
+ (doc) => {
+ for (const node of document.querySelectorAll('script[type^="math/tex"]')) {
+ const math = new doc.options.MathItem(
+ node.textContent,
+ doc.inputJax[0],
+ !!node.type.match(/; *mode=display/)
+ );
+ const text = document.createTextNode('');
+ node.parentNode.replaceChild(text, node);
+ math.start = { node: text, delim: '', n: 0 };
+ math.end = { node: text, delim: '', n: 0 };
+ doc.math.push(math);
+ }
+ },
+ ''
+ ]
},
ignoreHtmlClass: 'tex2jax_ignore'
}
-
};
}
diff --git a/htdocs/js/PGCodeMirror/PG.js b/htdocs/js/PGCodeMirror/PG.js
index debcc25100..e003158379 100644
--- a/htdocs/js/PGCodeMirror/PG.js
+++ b/htdocs/js/PGCodeMirror/PG.js
@@ -4,469 +4,470 @@
'use strict';
(() => {
- CodeMirror.defineMode("PG",function(){
+ CodeMirror.defineMode('PG', function () {
// http://perldoc.perl.org
- const PERL={ // null - magic touch
- // 1 - keyword
- // 2 - def
- // 3 - atom
- // 4 - operator
- // 5 - variable-2 (predefined)
- // [x,y] - x=1,2,3; y=must be defined if x{...}
- // PERL operators
- '->' : 4,
- '++' : 4,
- '--' : 4,
- '**' : 4,
- // ! ~ \ and unary + and -
- '=~' : 4,
- '!~' : 4,
- '*' : 4,
- '/' : 4,
- '%' : 4,
- 'x' : 4,
- '+' : 4,
- '-' : 4,
- '.' : 4,
- '<<' : 4,
- '>>' : 4,
- // named unary operators
- '<' : 4,
- '>' : 4,
- '<=' : 4,
- '>=' : 4,
- 'lt' : 4,
- 'gt' : 4,
- 'le' : 4,
- 'ge' : 4,
- '==' : 4,
- '!=' : 4,
- '<=>' : 4,
- 'eq' : 4,
- 'ne' : 4,
- 'cmp' : 4,
- '~~' : 4,
- '&' : 4,
- '|' : 4,
- '^' : 4,
- '&&' : 4,
- '||' : 4,
- '//' : 4,
- '..' : 4,
- '...' : 4,
- '?' : 4,
- ':' : 4,
- '=' : 4,
- '+=' : 4,
- '-=' : 4,
- '*=' : 4, // etc. ???
- ',' : 4,
- '=>' : 4,
- '::' : 4,
- // list operators (rightward)
- 'not' : 4,
- 'and' : 4,
- 'or' : 4,
- 'xor' : 4,
- // PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;)
- 'BEGIN' : [5,1],
- 'END' : [5,1],
- 'PRINT' : [5,1],
- 'PRINTF' : [5,1],
- 'GETC' : [5,1],
- 'READ' : [5,1],
- 'READLINE' : [5,1],
- 'DESTROY' : [5,1],
- 'TIE' : [5,1],
- 'TIEHANDLE' : [5,1],
- 'UNTIE' : [5,1],
- 'STDIN' : 5,
- 'STDIN_TOP' : 5,
- 'STDOUT' : 5,
- 'STDOUT_TOP' : 5,
- 'STDERR' : 5,
- 'STDERR_TOP' : 5,
- '$ARG' : 5,
- '$_' : 5,
- '@ARG' : 5,
- '@_' : 5,
- '$LIST_SEPARATOR' : 5,
- '$"' : 5,
- '$PROCESS_ID' : 5,
- '$PID' : 5,
- '$$' : 5,
- '$REAL_GROUP_ID' : 5,
- '$GID' : 5,
- '$(' : 5,
- '$EFFECTIVE_GROUP_ID' : 5,
- '$EGID' : 5,
- '$)' : 5,
- '$PROGRAM_NAME' : 5,
- '$0' : 5,
- '$SUBSCRIPT_SEPARATOR' : 5,
- '$SUBSEP' : 5,
- '$;' : 5,
- '$REAL_USER_ID' : 5,
- '$UID' : 5,
- '$<' : 5,
- '$EFFECTIVE_USER_ID' : 5,
- '$EUID' : 5,
- '$>' : 5,
-// '$a' : 5,
-// '$b' : 5,
- '$COMPILING' : 5,
- '$^C' : 5,
- '$DEBUGGING' : 5,
- '$^D' : 5,
- '${^ENCODING}' : 5,
- '$ENV' : 5,
- '%ENV' : 5,
- '$SYSTEM_FD_MAX' : 5,
- '$^F' : 5,
- '@F' : 5,
- '${^GLOBAL_PHASE}' : 5,
- '$^H' : 5,
- '%^H' : 5,
- '@INC' : 5,
- '%INC' : 5,
- '$INPLACE_EDIT' : 5,
- '$^I' : 5,
- '$^M' : 5,
- '$OSNAME' : 5,
- '$^O' : 5,
- '${^OPEN}' : 5,
- '$PERLDB' : 5,
- '$^P' : 5,
- '$SIG' : 5,
- '%SIG' : 5,
- '$BASETIME' : 5,
- '$^T' : 5,
- '${^TAINT}' : 5,
- '${^UNICODE}' : 5,
- '${^UTF8CACHE}' : 5,
- '${^UTF8LOCALE}' : 5,
- '$PERL_VERSION' : 5,
- '$^V' : 5,
- '${^WIN32_SLOPPY_STAT}' : 5,
- '$EXECUTABLE_NAME' : 5,
- '$^X' : 5,
- '$1' : 5, // - regexp $1, $2...
- '$MATCH' : 5,
- '$&' : 5,
- '${^MATCH}' : 5,
- '$PREMATCH' : 5,
- '$`' : 5,
- '${^PREMATCH}' : 5,
- '$POSTMATCH' : 5,
- "$'" : 5,
- '${^POSTMATCH}' : 5,
- '$LAST_PAREN_MATCH' : 5,
- '$+' : 5,
- '$LAST_SUBMATCH_RESULT' : 5,
- '$^N' : 5,
- '@LAST_MATCH_END' : 5,
- '@+' : 5,
- '%LAST_PAREN_MATCH' : 5,
- '%+' : 5,
- '@LAST_MATCH_START' : 5,
- '@-' : 5,
- '%LAST_MATCH_START' : 5,
- '%-' : 5,
- '$LAST_REGEXP_CODE_RESULT' : 5,
- '$^R' : 5,
- '${^RE_DEBUG_FLAGS}' : 5,
- '${^RE_TRIE_MAXBUF}' : 5,
- '$ARGV' : 5,
- '@ARGV' : 5,
- 'ARGV' : 5,
- 'ARGVOUT' : 5,
- '$OUTPUT_FIELD_SEPARATOR' : 5,
- '$OFS' : 5,
- '$,' : 5,
- '$INPUT_LINE_NUMBER' : 5,
- '$NR' : 5,
- '$.' : 5,
- '$INPUT_RECORD_SEPARATOR' : 5,
- '$RS' : 5,
- '$/' : 5,
- '$OUTPUT_RECORD_SEPARATOR' : 5,
- '$ORS' : 5,
- '$\\' : 5,
- '$OUTPUT_AUTOFLUSH' : 5,
- '$|' : 5,
- '$ACCUMULATOR' : 5,
- '$^A' : 5,
- '$FORMAT_FORMFEED' : 5,
- '$^L' : 5,
- '$FORMAT_PAGE_NUMBER' : 5,
- '$%' : 5,
- '$FORMAT_LINES_LEFT' : 5,
- '$-' : 5,
- '$FORMAT_LINE_BREAK_CHARACTERS' : 5,
- '$:' : 5,
- '$FORMAT_LINES_PER_PAGE' : 5,
- '$=' : 5,
- '$FORMAT_TOP_NAME' : 5,
- '$^' : 5,
- '$FORMAT_NAME' : 5,
- '$~' : 5,
- '${^CHILD_ERROR_NATIVE}' : 5,
- '$EXTENDED_OS_ERROR' : 5,
- '$^E' : 5,
- '$EXCEPTIONS_BEING_CAUGHT' : 5,
- '$^S' : 5,
- '$WARNING' : 5,
- '$^W' : 5,
- '${^WARNING_BITS}' : 5,
- '$OS_ERROR' : 5,
- '$ERRNO' : 5,
- '$!' : 5,
- '%OS_ERROR' : 5,
- '%ERRNO' : 5,
- '%!' : 5,
- '$CHILD_ERROR' : 5,
- '$?' : 5,
- '$EVAL_ERROR' : 5,
- '$@' : 5,
- '$OFMT' : 5,
- '$#' : 5,
- '$*' : 5,
- '$ARRAY_BASE' : 5,
- '$[' : 5,
- '$OLD_PERL_VERSION' : 5,
- '$]' : 5,
- // PERL blocks
- 'if' :[1,1],
- elsif :[1,1],
- 'else' :[1,1],
- 'while' :[1,1],
- unless :[1,1],
- until :[1,1],
- 'for' :[1,1],
- foreach :[1,1],
- // PERL functions
- 'abs' :1, // - absolute value function
- accept :1, // - accept an incoming socket connect
- alarm :1, // - schedule a SIGALRM
- 'atan2' :1, // - arctangent of Y/X in the range -PI to PI
- bind :1, // - binds an address to a socket
- binmode :1, // - prepare binary files for I/O
- bless :1, // - create an object
- bootstrap :1, //
- 'break' :1, // - break out of a "given" block
- caller :1, // - get context of the current subroutine call
- chdir :1, // - change your current working directory
- chmod :1, // - changes the permissions on a list of files
- chomp :1, // - remove a trailing record separator from a string
- chop :1, // - remove the last character from a string
- chown :1, // - change the ownership on a list of files
- chr :1, // - get character this number represents
- chroot :1, // - make directory new root for path lookups
- close :1, // - close file (or pipe or socket) handle
- closedir :1, // - close directory handle
- connect :1, // - connect to a remote socket
- 'continue' :[1,1], // - optional trailing block in a while or foreach
- 'cos' :1, // - cosine function
- crypt :1, // - one-way passwd-style encryption
- dbmclose :1, // - breaks binding on a tied dbm file
- dbmopen :1, // - create binding on a tied dbm file
- 'default' :1, //
- defined :1, // - test whether a value, variable, or function is defined
- 'delete' :1, // - deletes a value from a hash
- die :1, // - raise an exception or bail out
- 'do' :1, // - turn a BLOCK into a TERM
- dump :1, // - create an immediate core dump
- each :1, // - retrieve the next key/value pair from a hash
- endgrent :1, // - be done using group file
- endhostent :1, // - be done using hosts file
- endnetent :1, // - be done using networks file
- endprotoent :1, // - be done using protocols file
- endpwent :1, // - be done using passwd file
- endservent :1, // - be done using services file
- eof :1, // - test a filehandle for its end
- 'eval' :1, // - catch exceptions or compile and run code
- 'exec' :1, // - abandon this program to run another
- exists :1, // - test whether a hash key is present
- exit :1, // - terminate this program
- 'exp' :1, // - raise I to a power
- fcntl :1, // - file control system call
- fileno :1, // - return file descriptor from filehandle
- flock :1, // - lock an entire file with an advisory lock
- fork :1, // - create a new process just like this one
- format :1, // - declare a picture format with use by the write() function
- formline :1, // - internal function used for formats
- getc :1, // - get the next character from the filehandle
- getgrent :1, // - get next group record
- getgrgid :1, // - get group record given group user ID
- getgrnam :1, // - get group record given group name
- gethostbyaddr :1, // - get host record given its address
- gethostbyname :1, // - get host record given name
- gethostent :1, // - get next hosts record
- getlogin :1, // - return who logged in at this tty
- getnetbyaddr :1, // - get network record given its address
- getnetbyname :1, // - get networks record given name
- getnetent :1, // - get next networks record
- getpeername :1, // - find the other end of a socket connection
- getpgrp :1, // - get process group
- getppid :1, // - get parent process ID
- getpriority :1, // - get current nice value
- getprotobyname :1, // - get protocol record given name
- getprotobynumber :1, // - get protocol record numeric protocol
- getprotoent :1, // - get next protocols record
- getpwent :1, // - get next passwd record
- getpwnam :1, // - get passwd record given user login name
- getpwuid :1, // - get passwd record given user ID
- getservbyname :1, // - get services record given its name
- getservbyport :1, // - get services record given numeric port
- getservent :1, // - get next services record
- getsockname :1, // - retrieve the sockaddr for a given socket
- getsockopt :1, // - get socket options on a given socket
- given :1, //
- glob :1, // - expand filenames using wildcards
- gmtime :1, // - convert UNIX time into record or string using Greenwich time
- 'goto' :1, // - create spaghetti code
- grep :1, // - locate elements in a list test true against a given criterion
- hex :1, // - convert a string to a hexadecimal number
- 'import' :1, // - patch a module's namespace into your own
- index :1, // - find a substring within a string
- 'int' :1, // - get the integer portion of a number
- ioctl :1, // - system-dependent device control system call
- 'join' :1, // - join a list into a string using a separator
- keys :1, // - retrieve list of indices from a hash
- kill :1, // - send a signal to a process or process group
- last :1, // - exit a block prematurely
- lc :1, // - return lower-case version of a string
- lcfirst :1, // - return a string with just the next letter in lower case
- length :1, // - return the number of bytes in a string
- 'link' :1, // - create a hard link in the filesystem
- listen :1, // - register your socket as a server
- local : 2, // - create a temporary value for a global variable (dynamic scoping)
- localtime :1, // - convert UNIX time into record or string using local time
- lock :1, // - get a thread lock on a variable, subroutine, or method
- 'log' :1, // - retrieve the natural logarithm for a number
- lstat :1, // - stat a symbolic link
- m :null, // - match a string with a regular expression pattern
- map :1, // - apply a change to a list to get back a new list with the changes
- mkdir :1, // - create a directory
- msgctl :1, // - SysV IPC message control operations
- msgget :1, // - get SysV IPC message queue
- msgrcv :1, // - receive a SysV IPC message from a message queue
- msgsnd :1, // - send a SysV IPC message to a message queue
- my : 2, // - declare and assign a local variable (lexical scoping)
- 'new' :1, //
- next :1, // - iterate a block prematurely
- no :1, // - unimport some module symbols or semantics at compile time
- oct :1, // - convert a string to an octal number
- open :1, // - open a file, pipe, or descriptor
- opendir :1, // - open a directory
- ord :1, // - find a character's numeric representation
- our : 2, // - declare and assign a package variable (lexical scoping)
- pack :1, // - convert a list into a binary representation
- 'package' :1, // - declare a separate global namespace
- pipe :1, // - open a pair of connected filehandles
- pop :1, // - remove the last element from an array and return it
- pos :1, // - find or set the offset for the last/next m//g search
- print :1, // - output a list to a filehandle
- printf :1, // - output a formatted list to a filehandle
- prototype :1, // - get the prototype (if any) of a subroutine
- push :1, // - append one or more elements to an array
- q :null, // - singly quote a string
- qq :null, // - doubly quote a string
- qr :null, // - Compile pattern
- quotemeta :null, // - quote regular expression magic characters
- qw :null, // - quote a list of words
- qx :null, // - backquote quote a string
- rand :1, // - retrieve the next pseudorandom number
- read :1, // - fixed-length buffered input from a filehandle
- readdir :1, // - get a directory from a directory handle
- readline :1, // - fetch a record from a file
- readlink :1, // - determine where a symbolic link is pointing
- readpipe :1, // - execute a system command and collect standard output
- recv :1, // - receive a message over a Socket
- redo :1, // - start this loop iteration over again
- ref :1, // - find out the type of thing being referenced
- rename :1, // - change a filename
- require :1, // - load in external functions from a library at runtime
- reset :1, // - clear all variables of a given name
- 'return' :1, // - get out of a function early
- reverse :1, // - flip a string or a list
- rewinddir :1, // - reset directory handle
- rindex :1, // - right-to-left substring search
- rmdir :1, // - remove a directory
- s :null, // - replace a pattern with a string
- say :1, // - print with newline
- scalar :1, // - force a scalar context
- seek :1, // - reposition file pointer for random-access I/O
- seekdir :1, // - reposition directory pointer
- select :1, // - reset default output or do I/O multiplexing
- semctl :1, // - SysV semaphore control operations
- semget :1, // - get set of SysV semaphores
- semop :1, // - SysV semaphore operations
- send :1, // - send a message over a socket
- setgrent :1, // - prepare group file for use
- sethostent :1, // - prepare hosts file for use
- setnetent :1, // - prepare networks file for use
- setpgrp :1, // - set the process group of a process
- setpriority :1, // - set a process's nice value
- setprotoent :1, // - prepare protocols file for use
- setpwent :1, // - prepare passwd file for use
- setservent :1, // - prepare services file for use
- setsockopt :1, // - set some socket options
- shift :1, // - remove the first element of an array, and return it
- shmctl :1, // - SysV shared memory operations
- shmget :1, // - get SysV shared memory segment identifier
- shmread :1, // - read SysV shared memory
- shmwrite :1, // - write SysV shared memory
- shutdown :1, // - close down just half of a socket connection
- 'sin' :1, // - return the sine of a number
- sleep :1, // - block for some number of seconds
- socket :1, // - create a socket
- socketpair :1, // - create a pair of sockets
- 'sort' :1, // - sort a list of values
- splice :1, // - add or remove elements anywhere in an array
- 'split' :1, // - split up a string using a regexp delimiter
- sprintf :1, // - formatted print into a string
- 'sqrt' :1, // - square root function
- srand :1, // - seed the random number generator
- stat :1, // - get a file's status information
- state :1, // - declare and assign a state variable (persistent lexical scoping)
- study :1, // - optimize input data for repeated searches
- 'sub' :1, // - declare a subroutine, possibly anonymously
- 'substr' :1, // - get or alter a portion of a string
- symlink :1, // - create a symbolic link to a file
- syscall :1, // - execute an arbitrary system call
- sysopen :1, // - open a file, pipe, or descriptor
- sysread :1, // - fixed-length unbuffered input from a filehandle
- sysseek :1, // - position I/O pointer on handle used with sysread and syswrite
- system :1, // - run a separate program
- syswrite :1, // - fixed-length unbuffered output to a filehandle
- tell :1, // - get current seekpointer on a filehandle
- telldir :1, // - get current seekpointer on a directory handle
- tie :1, // - bind a variable to an object class
- tied :1, // - get a reference to the object underlying a tied variable
- time :1, // - return number of seconds since 1970
- times :1, // - return elapsed time for self and child processes
- tr :null, // - transliterate a string
- truncate :1, // - shorten a file
- uc :1, // - return upper-case version of a string
- ucfirst :1, // - return a string with just the next letter in upper case
- umask :1, // - set file creation mode mask
- undef :1, // - remove a variable or function definition
- unlink :1, // - remove one link to a file
- unpack :1, // - convert binary structure into normal perl variables
- unshift :1, // - prepend more elements to the beginning of a list
- untie :1, // - break a tie binding to a variable
- use :1, // - load in a module at compile time
- utime :1, // - set a file's last access and modify times
- values :1, // - return a list of the values in a hash
- vec :1, // - test or set particular bits in a string
- wait :1, // - wait for any child process to die
- waitpid :1, // - wait for a particular child process to die
- wantarray :1, // - get void vs scalar vs list context of current subroutine call
- warn :1, // - print debugging info
- when :1, //
- write :1, // - print a picture record
- y :null, // - transliterate a string
+ const PERL = {
+ // null - magic touch
+ // 1 - keyword
+ // 2 - def
+ // 3 - atom
+ // 4 - operator
+ // 5 - variable-2 (predefined)
+ // [x,y] - x=1,2,3; y=must be defined if x{...}
+ // PERL operators
+ '->': 4,
+ '++': 4,
+ '--': 4,
+ '**': 4,
+ // ! ~ \ and unary + and -
+ '=~': 4,
+ '!~': 4,
+ '*': 4,
+ '/': 4,
+ '%': 4,
+ x: 4,
+ '+': 4,
+ '-': 4,
+ '.': 4,
+ '<<': 4,
+ '>>': 4,
+ // named unary operators
+ '<': 4,
+ '>': 4,
+ '<=': 4,
+ '>=': 4,
+ lt: 4,
+ gt: 4,
+ le: 4,
+ ge: 4,
+ '==': 4,
+ '!=': 4,
+ '<=>': 4,
+ eq: 4,
+ ne: 4,
+ cmp: 4,
+ '~~': 4,
+ '&': 4,
+ '|': 4,
+ '^': 4,
+ '&&': 4,
+ '||': 4,
+ '//': 4,
+ '..': 4,
+ '...': 4,
+ '?': 4,
+ ':': 4,
+ '=': 4,
+ '+=': 4,
+ '-=': 4,
+ '*=': 4, // etc. ???
+ ',': 4,
+ '=>': 4,
+ '::': 4,
+ // list operators (rightward)
+ not: 4,
+ and: 4,
+ or: 4,
+ xor: 4,
+ // PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;)
+ BEGIN: [5, 1],
+ END: [5, 1],
+ PRINT: [5, 1],
+ PRINTF: [5, 1],
+ GETC: [5, 1],
+ READ: [5, 1],
+ READLINE: [5, 1],
+ DESTROY: [5, 1],
+ TIE: [5, 1],
+ TIEHANDLE: [5, 1],
+ UNTIE: [5, 1],
+ STDIN: 5,
+ STDIN_TOP: 5,
+ STDOUT: 5,
+ STDOUT_TOP: 5,
+ STDERR: 5,
+ STDERR_TOP: 5,
+ $ARG: 5,
+ $_: 5,
+ '@ARG': 5,
+ '@_': 5,
+ $LIST_SEPARATOR: 5,
+ '$"': 5,
+ $PROCESS_ID: 5,
+ $PID: 5,
+ $$: 5,
+ $REAL_GROUP_ID: 5,
+ $GID: 5,
+ '$(': 5,
+ $EFFECTIVE_GROUP_ID: 5,
+ $EGID: 5,
+ '$)': 5,
+ $PROGRAM_NAME: 5,
+ $0: 5,
+ $SUBSCRIPT_SEPARATOR: 5,
+ $SUBSEP: 5,
+ '$;': 5,
+ $REAL_USER_ID: 5,
+ $UID: 5,
+ '$<': 5,
+ $EFFECTIVE_USER_ID: 5,
+ $EUID: 5,
+ '$>': 5,
+ // '$a' : 5,
+ // '$b' : 5,
+ $COMPILING: 5,
+ '$^C': 5,
+ $DEBUGGING: 5,
+ '$^D': 5,
+ '${^ENCODING}': 5,
+ $ENV: 5,
+ '%ENV': 5,
+ $SYSTEM_FD_MAX: 5,
+ '$^F': 5,
+ '@F': 5,
+ '${^GLOBAL_PHASE}': 5,
+ '$^H': 5,
+ '%^H': 5,
+ '@INC': 5,
+ '%INC': 5,
+ $INPLACE_EDIT: 5,
+ '$^I': 5,
+ '$^M': 5,
+ $OSNAME: 5,
+ '$^O': 5,
+ '${^OPEN}': 5,
+ $PERLDB: 5,
+ '$^P': 5,
+ $SIG: 5,
+ '%SIG': 5,
+ $BASETIME: 5,
+ '$^T': 5,
+ '${^TAINT}': 5,
+ '${^UNICODE}': 5,
+ '${^UTF8CACHE}': 5,
+ '${^UTF8LOCALE}': 5,
+ $PERL_VERSION: 5,
+ '$^V': 5,
+ '${^WIN32_SLOPPY_STAT}': 5,
+ $EXECUTABLE_NAME: 5,
+ '$^X': 5,
+ $1: 5, // - regexp $1, $2...
+ $MATCH: 5,
+ '$&': 5,
+ '${^MATCH}': 5,
+ $PREMATCH: 5,
+ '$`': 5,
+ '${^PREMATCH}': 5,
+ $POSTMATCH: 5,
+ "$'": 5,
+ '${^POSTMATCH}': 5,
+ $LAST_PAREN_MATCH: 5,
+ '$+': 5,
+ $LAST_SUBMATCH_RESULT: 5,
+ '$^N': 5,
+ '@LAST_MATCH_END': 5,
+ '@+': 5,
+ '%LAST_PAREN_MATCH': 5,
+ '%+': 5,
+ '@LAST_MATCH_START': 5,
+ '@-': 5,
+ '%LAST_MATCH_START': 5,
+ '%-': 5,
+ $LAST_REGEXP_CODE_RESULT: 5,
+ '$^R': 5,
+ '${^RE_DEBUG_FLAGS}': 5,
+ '${^RE_TRIE_MAXBUF}': 5,
+ $ARGV: 5,
+ '@ARGV': 5,
+ ARGV: 5,
+ ARGVOUT: 5,
+ $OUTPUT_FIELD_SEPARATOR: 5,
+ $OFS: 5,
+ '$,': 5,
+ $INPUT_LINE_NUMBER: 5,
+ $NR: 5,
+ '$.': 5,
+ $INPUT_RECORD_SEPARATOR: 5,
+ $RS: 5,
+ '$/': 5,
+ $OUTPUT_RECORD_SEPARATOR: 5,
+ $ORS: 5,
+ '$\\': 5,
+ $OUTPUT_AUTOFLUSH: 5,
+ '$|': 5,
+ $ACCUMULATOR: 5,
+ '$^A': 5,
+ $FORMAT_FORMFEED: 5,
+ '$^L': 5,
+ $FORMAT_PAGE_NUMBER: 5,
+ '$%': 5,
+ $FORMAT_LINES_LEFT: 5,
+ '$-': 5,
+ $FORMAT_LINE_BREAK_CHARACTERS: 5,
+ '$:': 5,
+ $FORMAT_LINES_PER_PAGE: 5,
+ '$=': 5,
+ $FORMAT_TOP_NAME: 5,
+ '$^': 5,
+ $FORMAT_NAME: 5,
+ '$~': 5,
+ '${^CHILD_ERROR_NATIVE}': 5,
+ $EXTENDED_OS_ERROR: 5,
+ '$^E': 5,
+ $EXCEPTIONS_BEING_CAUGHT: 5,
+ '$^S': 5,
+ $WARNING: 5,
+ '$^W': 5,
+ '${^WARNING_BITS}': 5,
+ $OS_ERROR: 5,
+ $ERRNO: 5,
+ '$!': 5,
+ '%OS_ERROR': 5,
+ '%ERRNO': 5,
+ '%!': 5,
+ $CHILD_ERROR: 5,
+ '$?': 5,
+ $EVAL_ERROR: 5,
+ '$@': 5,
+ $OFMT: 5,
+ '$#': 5,
+ '$*': 5,
+ $ARRAY_BASE: 5,
+ '$[': 5,
+ $OLD_PERL_VERSION: 5,
+ '$]': 5,
+ // PERL blocks
+ if: [1, 1],
+ elsif: [1, 1],
+ else: [1, 1],
+ while: [1, 1],
+ unless: [1, 1],
+ until: [1, 1],
+ for: [1, 1],
+ foreach: [1, 1],
+ // PERL functions
+ abs: 1, // - absolute value function
+ accept: 1, // - accept an incoming socket connect
+ alarm: 1, // - schedule a SIGALRM
+ atan2: 1, // - arctangent of Y/X in the range -PI to PI
+ bind: 1, // - binds an address to a socket
+ binmode: 1, // - prepare binary files for I/O
+ bless: 1, // - create an object
+ bootstrap: 1, //
+ break: 1, // - break out of a "given" block
+ caller: 1, // - get context of the current subroutine call
+ chdir: 1, // - change your current working directory
+ chmod: 1, // - changes the permissions on a list of files
+ chomp: 1, // - remove a trailing record separator from a string
+ chop: 1, // - remove the last character from a string
+ chown: 1, // - change the ownership on a list of files
+ chr: 1, // - get character this number represents
+ chroot: 1, // - make directory new root for path lookups
+ close: 1, // - close file (or pipe or socket) handle
+ closedir: 1, // - close directory handle
+ connect: 1, // - connect to a remote socket
+ continue: [1, 1], // - optional trailing block in a while or foreach
+ cos: 1, // - cosine function
+ crypt: 1, // - one-way passwd-style encryption
+ dbmclose: 1, // - breaks binding on a tied dbm file
+ dbmopen: 1, // - create binding on a tied dbm file
+ default: 1, //
+ defined: 1, // - test whether a value, variable, or function is defined
+ delete: 1, // - deletes a value from a hash
+ die: 1, // - raise an exception or bail out
+ do: 1, // - turn a BLOCK into a TERM
+ dump: 1, // - create an immediate core dump
+ each: 1, // - retrieve the next key/value pair from a hash
+ endgrent: 1, // - be done using group file
+ endhostent: 1, // - be done using hosts file
+ endnetent: 1, // - be done using networks file
+ endprotoent: 1, // - be done using protocols file
+ endpwent: 1, // - be done using passwd file
+ endservent: 1, // - be done using services file
+ eof: 1, // - test a filehandle for its end
+ eval: 1, // - catch exceptions or compile and run code
+ exec: 1, // - abandon this program to run another
+ exists: 1, // - test whether a hash key is present
+ exit: 1, // - terminate this program
+ exp: 1, // - raise I to a power
+ fcntl: 1, // - file control system call
+ fileno: 1, // - return file descriptor from filehandle
+ flock: 1, // - lock an entire file with an advisory lock
+ fork: 1, // - create a new process just like this one
+ format: 1, // - declare a picture format with use by the write() function
+ formline: 1, // - internal function used for formats
+ getc: 1, // - get the next character from the filehandle
+ getgrent: 1, // - get next group record
+ getgrgid: 1, // - get group record given group user ID
+ getgrnam: 1, // - get group record given group name
+ gethostbyaddr: 1, // - get host record given its address
+ gethostbyname: 1, // - get host record given name
+ gethostent: 1, // - get next hosts record
+ getlogin: 1, // - return who logged in at this tty
+ getnetbyaddr: 1, // - get network record given its address
+ getnetbyname: 1, // - get networks record given name
+ getnetent: 1, // - get next networks record
+ getpeername: 1, // - find the other end of a socket connection
+ getpgrp: 1, // - get process group
+ getppid: 1, // - get parent process ID
+ getpriority: 1, // - get current nice value
+ getprotobyname: 1, // - get protocol record given name
+ getprotobynumber: 1, // - get protocol record numeric protocol
+ getprotoent: 1, // - get next protocols record
+ getpwent: 1, // - get next passwd record
+ getpwnam: 1, // - get passwd record given user login name
+ getpwuid: 1, // - get passwd record given user ID
+ getservbyname: 1, // - get services record given its name
+ getservbyport: 1, // - get services record given numeric port
+ getservent: 1, // - get next services record
+ getsockname: 1, // - retrieve the sockaddr for a given socket
+ getsockopt: 1, // - get socket options on a given socket
+ given: 1, //
+ glob: 1, // - expand filenames using wildcards
+ gmtime: 1, // - convert UNIX time into record or string using Greenwich time
+ goto: 1, // - create spaghetti code
+ grep: 1, // - locate elements in a list test true against a given criterion
+ hex: 1, // - convert a string to a hexadecimal number
+ import: 1, // - patch a module's namespace into your own
+ index: 1, // - find a substring within a string
+ int: 1, // - get the integer portion of a number
+ ioctl: 1, // - system-dependent device control system call
+ join: 1, // - join a list into a string using a separator
+ keys: 1, // - retrieve list of indices from a hash
+ kill: 1, // - send a signal to a process or process group
+ last: 1, // - exit a block prematurely
+ lc: 1, // - return lower-case version of a string
+ lcfirst: 1, // - return a string with just the next letter in lower case
+ length: 1, // - return the number of bytes in a string
+ link: 1, // - create a hard link in the filesystem
+ listen: 1, // - register your socket as a server
+ local: 2, // - create a temporary value for a global variable (dynamic scoping)
+ localtime: 1, // - convert UNIX time into record or string using local time
+ lock: 1, // - get a thread lock on a variable, subroutine, or method
+ log: 1, // - retrieve the natural logarithm for a number
+ lstat: 1, // - stat a symbolic link
+ m: null, // - match a string with a regular expression pattern
+ map: 1, // - apply a change to a list to get back a new list with the changes
+ mkdir: 1, // - create a directory
+ msgctl: 1, // - SysV IPC message control operations
+ msgget: 1, // - get SysV IPC message queue
+ msgrcv: 1, // - receive a SysV IPC message from a message queue
+ msgsnd: 1, // - send a SysV IPC message to a message queue
+ my: 2, // - declare and assign a local variable (lexical scoping)
+ new: 1, //
+ next: 1, // - iterate a block prematurely
+ no: 1, // - unimport some module symbols or semantics at compile time
+ oct: 1, // - convert a string to an octal number
+ open: 1, // - open a file, pipe, or descriptor
+ opendir: 1, // - open a directory
+ ord: 1, // - find a character's numeric representation
+ our: 2, // - declare and assign a package variable (lexical scoping)
+ pack: 1, // - convert a list into a binary representation
+ package: 1, // - declare a separate global namespace
+ pipe: 1, // - open a pair of connected filehandles
+ pop: 1, // - remove the last element from an array and return it
+ pos: 1, // - find or set the offset for the last/next m//g search
+ print: 1, // - output a list to a filehandle
+ printf: 1, // - output a formatted list to a filehandle
+ prototype: 1, // - get the prototype (if any) of a subroutine
+ push: 1, // - append one or more elements to an array
+ q: null, // - singly quote a string
+ qq: null, // - doubly quote a string
+ qr: null, // - Compile pattern
+ quotemeta: null, // - quote regular expression magic characters
+ qw: null, // - quote a list of words
+ qx: null, // - backquote quote a string
+ rand: 1, // - retrieve the next pseudorandom number
+ read: 1, // - fixed-length buffered input from a filehandle
+ readdir: 1, // - get a directory from a directory handle
+ readline: 1, // - fetch a record from a file
+ readlink: 1, // - determine where a symbolic link is pointing
+ readpipe: 1, // - execute a system command and collect standard output
+ recv: 1, // - receive a message over a Socket
+ redo: 1, // - start this loop iteration over again
+ ref: 1, // - find out the type of thing being referenced
+ rename: 1, // - change a filename
+ require: 1, // - load in external functions from a library at runtime
+ reset: 1, // - clear all variables of a given name
+ return: 1, // - get out of a function early
+ reverse: 1, // - flip a string or a list
+ rewinddir: 1, // - reset directory handle
+ rindex: 1, // - right-to-left substring search
+ rmdir: 1, // - remove a directory
+ s: null, // - replace a pattern with a string
+ say: 1, // - print with newline
+ scalar: 1, // - force a scalar context
+ seek: 1, // - reposition file pointer for random-access I/O
+ seekdir: 1, // - reposition directory pointer
+ select: 1, // - reset default output or do I/O multiplexing
+ semctl: 1, // - SysV semaphore control operations
+ semget: 1, // - get set of SysV semaphores
+ semop: 1, // - SysV semaphore operations
+ send: 1, // - send a message over a socket
+ setgrent: 1, // - prepare group file for use
+ sethostent: 1, // - prepare hosts file for use
+ setnetent: 1, // - prepare networks file for use
+ setpgrp: 1, // - set the process group of a process
+ setpriority: 1, // - set a process's nice value
+ setprotoent: 1, // - prepare protocols file for use
+ setpwent: 1, // - prepare passwd file for use
+ setservent: 1, // - prepare services file for use
+ setsockopt: 1, // - set some socket options
+ shift: 1, // - remove the first element of an array, and return it
+ shmctl: 1, // - SysV shared memory operations
+ shmget: 1, // - get SysV shared memory segment identifier
+ shmread: 1, // - read SysV shared memory
+ shmwrite: 1, // - write SysV shared memory
+ shutdown: 1, // - close down just half of a socket connection
+ sin: 1, // - return the sine of a number
+ sleep: 1, // - block for some number of seconds
+ socket: 1, // - create a socket
+ socketpair: 1, // - create a pair of sockets
+ sort: 1, // - sort a list of values
+ splice: 1, // - add or remove elements anywhere in an array
+ split: 1, // - split up a string using a regexp delimiter
+ sprintf: 1, // - formatted print into a string
+ sqrt: 1, // - square root function
+ srand: 1, // - seed the random number generator
+ stat: 1, // - get a file's status information
+ state: 1, // - declare and assign a state variable (persistent lexical scoping)
+ study: 1, // - optimize input data for repeated searches
+ sub: 1, // - declare a subroutine, possibly anonymously
+ substr: 1, // - get or alter a portion of a string
+ symlink: 1, // - create a symbolic link to a file
+ syscall: 1, // - execute an arbitrary system call
+ sysopen: 1, // - open a file, pipe, or descriptor
+ sysread: 1, // - fixed-length unbuffered input from a filehandle
+ sysseek: 1, // - position I/O pointer on handle used with sysread and syswrite
+ system: 1, // - run a separate program
+ syswrite: 1, // - fixed-length unbuffered output to a filehandle
+ tell: 1, // - get current seekpointer on a filehandle
+ telldir: 1, // - get current seekpointer on a directory handle
+ tie: 1, // - bind a variable to an object class
+ tied: 1, // - get a reference to the object underlying a tied variable
+ time: 1, // - return number of seconds since 1970
+ times: 1, // - return elapsed time for self and child processes
+ tr: null, // - transliterate a string
+ truncate: 1, // - shorten a file
+ uc: 1, // - return upper-case version of a string
+ ucfirst: 1, // - return a string with just the next letter in upper case
+ umask: 1, // - set file creation mode mask
+ undef: 1, // - remove a variable or function definition
+ unlink: 1, // - remove one link to a file
+ unpack: 1, // - convert binary structure into normal perl variables
+ unshift: 1, // - prepend more elements to the beginning of a list
+ untie: 1, // - break a tie binding to a variable
+ use: 1, // - load in a module at compile time
+ utime: 1, // - set a file's last access and modify times
+ values: 1, // - return a list of the values in a hash
+ vec: 1, // - test or set particular bits in a string
+ wait: 1, // - wait for any child process to die
+ waitpid: 1, // - wait for a particular child process to die
+ wantarray: 1, // - get void vs scalar vs list context of current subroutine call
+ warn: 1, // - print debugging info
+ when: 1, //
+ write: 1, // - print a picture record
+ y: null // - transliterate a string
};
// PG Keywords and Variables
const PGstyle = 'atom';
@@ -506,7 +507,7 @@
'random',
'list_random',
'non_zero_random',
- 'NchooseK',
+ 'NchooseK'
]);
const PGvars = new Set([
'BR',
@@ -566,66 +567,69 @@
'ITEMSEP'
]);
- const RXstyle="string-2";
- const RXmodifiers=/[goseximacplud]/; // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type
+ const RXstyle = 'string-2';
+ const RXmodifiers = /[goseximacplud]/; // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type
- function tokenChain(stream,state,chain,style,tail,tokener){ // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)
- state.chain=null; // 12 3tail
- state.style=null;
- state.tail=null;
- state.tokenize=function(stream,state){
- var e=false,c,i=0;
- while(c=stream.next()){
- if(c===chain[i]&&!e){
- if(chain[++i]!==undefined){
- state.chain=chain[i];
- state.style=style;
- state.tail=tail;}
- else if(tail)
- stream.eatWhile(tail);
- state.tokenize=tokener || tokenPerl;
- return style;}
- e=!e&&c=="\\";}
- return style;};
- return state.tokenize(stream,state);}
+ function tokenChain(stream, state, chain, style, tail, tokener) {
+ // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;)
+ state.chain = null; // 12 3tail
+ state.style = null;
+ state.tail = null;
+ state.tokenize = function (stream, state) {
+ var e = false,
+ c,
+ i = 0;
+ while ((c = stream.next())) {
+ if (c === chain[i] && !e) {
+ if (chain[++i] !== undefined) {
+ state.chain = chain[i];
+ state.style = style;
+ state.tail = tail;
+ } else if (tail) stream.eatWhile(tail);
+ state.tokenize = tokener || tokenPerl;
+ return style;
+ }
+ e = !e && c == '\\';
+ }
+ return style;
+ };
+ return state.tokenize(stream, state);
+ }
- function tokenSOMETHING(stream,state,string){
- state.tokenize=function(stream,state){
- if(stream.string==string)
- state.tokenize=tokenPerl;
+ function tokenSOMETHING(stream, state, string) {
+ state.tokenize = function (stream, state) {
+ if (stream.string == string) state.tokenize = tokenPerl;
stream.skipToEnd();
- return "string";};
- return state.tokenize(stream,state);}
+ return 'string';
+ };
+ return state.tokenize(stream, state);
+ }
// EV3 block formatting
- function tokenEV3(stream,state,string,style,prevState){
- state.tokenize = function(stream,state) {
- if (prevState && prevState.mode == "math") {
- var reg = new RegExp("^\\\\"+string);
+ function tokenEV3(stream, state, string, style, prevState) {
+ state.tokenize = function (stream, state) {
+ if (prevState && prevState.mode == 'math') {
+ var reg = new RegExp('^\\\\' + string);
} else {
- var reg = new RegExp("^"+string);
+ var reg = new RegExp('^' + string);
}
if (stream.match(reg)) {
if (!prevState) {
state.tokenize = tokenPerl;
return PGstyle;
} else {
- state.tokenize = function(stream,state) {
- return tokenEV3(stream,state,prevState.string,
- prevState.style,prevState.prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenEV3(stream, state, prevState.string, prevState.style, prevState.prevState);
+ };
}
- if (string.includes("BOLD"))
- return PGstyle + " strong";
- if (string.includes("ITALIC"))
- return PGstyle + " em";
- if (prevState.endstyle)
- return prevState.endstyle;
+ if (string.includes('BOLD')) return PGstyle + ' strong';
+ if (string.includes('ITALIC')) return PGstyle + ' em';
+ if (prevState.endstyle) return prevState.endstyle;
return style;
} else {
- state.tokenize = function(stream,state) {
- return tokenEV3(stream,state,string,style,prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenEV3(stream, state, string, style, prevState);
+ };
}
const newPrevState = {};
@@ -637,204 +641,229 @@
newPrevState.style = style;
newPrevState.string = string;
- if (prevState && prevState.mode == "cmd") { // Some additional formatting for perl code blocks
- newPrevState.mode = "cmd";
- if (stream.match(/^[$@%]{/)) { // ${, @{, %{ nested blocks
- style = "variable";
- state.tokenize = function(stream,state) {
- return tokenEV3(stream,state,"\\}",style,newPrevState);
- }
+ if (prevState && prevState.mode == 'cmd') {
+ // Some additional formatting for perl code blocks
+ newPrevState.mode = 'cmd';
+ if (stream.match(/^[$@%]{/)) {
+ // ${, @{, %{ nested blocks
+ style = 'variable';
+ state.tokenize = function (stream, state) {
+ return tokenEV3(stream, state, '\\}', style, newPrevState);
+ };
return style;
}
- if (stream.match(/^\(/)) { // Nested ( ) blocks
- newPrevState.endstyle = "variable";
- state.tokenize = function(stream,state) {
- return tokenEV3(stream,state,"\\)",style,newPrevState);
- }
- return "variable";
+ if (stream.match(/^\(/)) {
+ // Nested ( ) blocks
+ newPrevState.endstyle = 'variable';
+ state.tokenize = function (stream, state) {
+ return tokenEV3(stream, state, '\\)', style, newPrevState);
+ };
+ return 'variable';
}
- if (stream.match(/^\[/)) { // Nested [ ] blocks
- newPrevState.endstyle = "variable";
- state.tokenize = function(stream,state) {
- return tokenEV3(stream,state,"\\]",style,newPrevState);
- }
- return "variable";
+ if (stream.match(/^\[/)) {
+ // Nested [ ] blocks
+ newPrevState.endstyle = 'variable';
+ state.tokenize = function (stream, state) {
+ return tokenEV3(stream, state, '\\]', style, newPrevState);
+ };
+ return 'variable';
}
- if (stream.match(/^\{/)) { // Nested { } blocks
- newPrevState.endstyle = "variable";
- state.tokenize = function(stream,state) {
- return tokenEV3(stream,state,"\\}",style,newPrevState);
- }
- return "variable";
+ if (stream.match(/^\{/)) {
+ // Nested { } blocks
+ newPrevState.endstyle = 'variable';
+ state.tokenize = function (stream, state) {
+ return tokenEV3(stream, state, '\\}', style, newPrevState);
+ };
+ return 'variable';
}
- if (stream.match(/^\w+/)) { // Check for PG keywords
- if (PGcmds.has(stream.current()))
- return PGkeyword;
- else
- return style;
+ if (stream.match(/^\w+/)) {
+ // Check for PG keywords
+ if (PGcmds.has(stream.current())) return PGkeyword;
+ else return style;
}
- if (stream.match(/^['"]/)) { // Quotes
- return tokenChain(stream,state,[stream.current()],"string",null,function(stream,state) {
- tokenEV3(stream,state,string,style,prevState) });
+ if (stream.match(/^['"]/)) {
+ // Quotes
+ return tokenChain(stream, state, [stream.current()], 'string', null, function (stream, state) {
+ tokenEV3(stream, state, string, style, prevState);
+ });
}
- if (stream.match(/^[=,;/\*><%&|.~?:+/-]/)) { // Catch some perl operators
- return "variable";
+ if (stream.match(/^[=,;/\*><%&|.~?:+/-]/)) {
+ // Catch some perl operators
+ return 'variable';
}
}
- if (stream.match(/^\\\(/)) { // \(...\) TeX block
+ if (stream.match(/^\\\(/)) {
+ // \(...\) TeX block
if (prevState) {
- style = "error";
+ style = 'error';
} else {
- style = "comment";
- }
- state.tokenize = function(stream,state) {
- newPrevState.mode = "math";
- return tokenEV3(stream,state,"\\)",style,newPrevState);
+ style = 'comment';
}
- } else if (stream.match(/^\\\[/)) { // \[...\] TeX block
+ state.tokenize = function (stream, state) {
+ newPrevState.mode = 'math';
+ return tokenEV3(stream, state, '\\)', style, newPrevState);
+ };
+ } else if (stream.match(/^\\\[/)) {
+ // \[...\] TeX block
if (prevState) {
- style = "error";
+ style = 'error';
} else {
- style = "comment";
- }
- state.tokenize = function(stream,state) {
- newPrevState.mode = "math";
- return tokenEV3(stream,state,"\\]",style,newPrevState);
+ style = 'comment';
}
- } else if (stream.match(/^\\{/)) { // \{...\} Perl code block
+ state.tokenize = function (stream, state) {
+ newPrevState.mode = 'math';
+ return tokenEV3(stream, state, '\\]', style, newPrevState);
+ };
+ } else if (stream.match(/^\\{/)) {
+ // \{...\} Perl code block
if (prevState) {
- style = "error";
+ style = 'error';
} else {
- style = "variable-2";
+ style = 'variable-2';
}
- state.tokenize = function(stream,state) {
- newPrevState.mode = "cmd";
- return tokenEV3(stream,state,"\\\\}",style,newPrevState);
- }
- } else if (stream.match(/^``/)) { // ``...`` math object math
- if (prevState && prevState.mode != "math") {
- style = "error";
+ state.tokenize = function (stream, state) {
+ newPrevState.mode = 'cmd';
+ return tokenEV3(stream, state, '\\\\}', style, newPrevState);
+ };
+ } else if (stream.match(/^``/)) {
+ // ``...`` math object math
+ if (prevState && prevState.mode != 'math') {
+ style = 'error';
} else {
- style = "variable-3";
+ style = 'variable-3';
}
- state.tokenize = function(stream,state) {
- return tokenEV3(stream,state,"``",style,newPrevState);
- }
- } else if (stream.match(/^`/)) { // `...` math object math
- if (prevState && prevState.mode != "math") {
- style = "error";
+ state.tokenize = function (stream, state) {
+ return tokenEV3(stream, state, '``', style, newPrevState);
+ };
+ } else if (stream.match(/^`/)) {
+ // `...` math object math
+ if (prevState && prevState.mode != 'math') {
+ style = 'error';
} else {
- style = "variable-3";
- }
- state.tokenize = function(stream,state) {
- return tokenEV3(stream,state,"`([^`]|$)",style,newPrevState,"tick");
+ style = 'variable-3';
}
- } else if (stream.match(/^(\$BBOLD|\${BBOLD})/)) { // Bold
- style = style = " strong";
- state.tokenize = function(stream,state) {
- return tokenEV3(stream,state,"(\\$EBOLD|\\${EBOLD})",style,newPrevState);
- }
- return PGstyle + " strong";
- } else if (stream.match(/^(\$BITALIC|\${BITALIC})/)) { // Italic
- style = style + " em";
- state.tokenize = function(stream,state) {
- return tokenEV3(stream,state,"(\\$EITALIC|\\${EITALIC})",style,newPrevState);
- }
- return PGstyle + " em";
- } else if (stream.match(/^[$@%]\w+/)) { // PG Variables
- if (PGvars.has(stream.current().substring(1)))
- return PGstyle;
- return "variable";
- } else if (stream.match(/^[$@%]{\w+}/)) { // ${foo} PG variables
- if (PGvars.has(stream.current().slice(2,-1)))
- return PGstyle;
- return "variable";
- } else if (stream.match(/^ +$/)) { // Trailing white space
- return "trailingspace";
- } else if (stream.match(/^[\[\]\\ (){}$@%`]/)) { // Advance a single character if special
+ state.tokenize = function (stream, state) {
+ return tokenEV3(stream, state, '`([^`]|$)', style, newPrevState, 'tick');
+ };
+ } else if (stream.match(/^(\$BBOLD|\${BBOLD})/)) {
+ // Bold
+ style = style = ' strong';
+ state.tokenize = function (stream, state) {
+ return tokenEV3(stream, state, '(\\$EBOLD|\\${EBOLD})', style, newPrevState);
+ };
+ return PGstyle + ' strong';
+ } else if (stream.match(/^(\$BITALIC|\${BITALIC})/)) {
+ // Italic
+ style = style + ' em';
+ state.tokenize = function (stream, state) {
+ return tokenEV3(stream, state, '(\\$EITALIC|\\${EITALIC})', style, newPrevState);
+ };
+ return PGstyle + ' em';
+ } else if (stream.match(/^[$@%]\w+/)) {
+ // PG Variables
+ if (PGvars.has(stream.current().substring(1))) return PGstyle;
+ return 'variable';
+ } else if (stream.match(/^[$@%]{\w+}/)) {
+ // ${foo} PG variables
+ if (PGvars.has(stream.current().slice(2, -1))) return PGstyle;
+ return 'variable';
+ } else if (stream.match(/^ +$/)) {
+ // Trailing white space
+ return 'trailingspace';
+ } else if (stream.match(/^[\[\]\\ (){}$@%`]/)) {
+ // Advance a single character if special
return style;
- } else { // Otherwise advance through all non special characters
- if (prevState && prevState.mode == "cmd") { // Only eat through words in perl code mode
- if (stream.match(/\w+/))
- return style;
- else
- stream.next();
+ } else {
+ // Otherwise advance through all non special characters
+ if (prevState && prevState.mode == 'cmd') {
+ // Only eat through words in perl code mode
+ if (stream.match(/\w+/)) return style;
+ else stream.next();
} else {
stream.eatWhile(/[^\[\]\\ (){}$@%`]/);
}
}
return style;
- }
- return state.tokenize(stream,state);
+ };
+ return state.tokenize(stream, state);
}
// No additional formatting inside comment block, only looks for end string.
// Currently only used for comments and ``` code blocks.
// The final stream.match and stream.eatWhile may need updated if used for other blocks.
- function tokenPGMLComment(stream,state,string,style,prevState){
- state.tokenize = function(stream,state) {
- var reg = new RegExp("^"+string);
+ function tokenPGMLComment(stream, state, string, style, prevState) {
+ state.tokenize = function (stream, state) {
+ var reg = new RegExp('^' + string);
if (stream.match(reg)) {
- state.tokenize = function(stream,state) {
- return tokenPGML(stream,state,prevState.string,
- prevState.style,prevState.prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenPGML(stream, state, prevState.string, prevState.style, prevState.prevState);
+ };
return style;
} else {
- state.tokenize = function(stream,state) {
- return tokenPGMLComment(stream,state,string,style,prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenPGMLComment(stream, state, string, style, prevState);
+ };
}
- if (stream.match(/^[\]%`]/))
- return style;
+ if (stream.match(/^[\]%`]/)) return style;
stream.eatWhile(/[^\]%`]/);
return style;
- }
- return state.tokenize(stream,state);
+ };
+ return state.tokenize(stream, state);
}
// PGML subblock which has limited formatting options compared to main block.
// This block nests {} and [] blocks, for correct pairing in variables and commands.
- function tokenPGMLSubBlock(stream,state,string,style,prevState){
- state.tokenize = function(stream,state) {
- var reg = new RegExp("^"+string);
+ function tokenPGMLSubBlock(stream, state, string, style, prevState) {
+ state.tokenize = function (stream, state) {
+ var reg = new RegExp('^' + string);
if (stream.match(reg)) {
// Needed to ensure ': ' verbatim lines exit out if ended with a secondary subblock.
if (stream.eol() && prevState.subblock && prevState.prevState && prevState.prevState.stopeol) {
- state.tokenize = function(stream,state) {
- return tokenPGMLSubBlock(stream,state,prevState.prevState.string,
- prevState.prevState.style,prevState.prevState.prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenPGMLSubBlock(
+ stream,
+ state,
+ prevState.prevState.string,
+ prevState.prevState.style,
+ prevState.prevState.prevState
+ );
+ };
} else if (stream.eol() && prevState.prevState && prevState.prevState.stopeol) {
- state.tokenize = function(stream,state) {
- return tokenPGML(stream,state,prevState.prevState.string,
- prevState.prevState.style,prevState.prevState.prevState);
- }
- } else if (prevState.subblock){
- state.tokenize = function(stream,state) {
- return tokenPGMLSubBlock(stream,state,prevState.string,
- prevState.style,prevState.prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenPGML(
+ stream,
+ state,
+ prevState.prevState.string,
+ prevState.prevState.style,
+ prevState.prevState.prevState
+ );
+ };
+ } else if (prevState.subblock) {
+ state.tokenize = function (stream, state) {
+ return tokenPGMLSubBlock(
+ stream,
+ state,
+ prevState.string,
+ prevState.style,
+ prevState.prevState
+ );
+ };
} else {
- state.tokenize = function(stream,state) {
- return tokenPGML(stream,state,prevState.string,
- prevState.style,prevState.prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenPGML(stream, state, prevState.string, prevState.style, prevState.prevState);
+ };
}
- if (prevState.mode == "var" || prevState.mode == "cmd")
- stream.match(/^\*{1,3}([^\*]|$)/);
- if (prevState.mode == "calc") {
- if (!stream.match(/^\*(\s|$)/))
- stream.match(/^\{.+\}/);
+ if (prevState.mode == 'var' || prevState.mode == 'cmd') stream.match(/^\*{1,3}([^\*]|$)/);
+ if (prevState.mode == 'calc') {
+ if (!stream.match(/^\*(\s|$)/)) stream.match(/^\{.+\}/);
}
- if (prevState.endstyle)
- return prevState.endstyle;
+ if (prevState.endstyle) return prevState.endstyle;
return style;
} else {
- state.tokenize = function(stream,state) {
- return tokenPGMLSubBlock(stream,state,string,style,prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenPGMLSubBlock(stream, state, string, style, prevState);
+ };
}
var newPrevState = {};
@@ -846,51 +875,54 @@
newPrevState.style = style;
newPrevState.string = string;
newPrevState.subblock = true;
- if (prevState.mode)
- newPrevState.mode = prevState.mode;
+ if (prevState.mode) newPrevState.mode = prevState.mode;
- if (prevState.mode == "cmd") { // Some formatting for [@ ... @] blocks
- if (stream.match(/^[$@%]\w+/)) { // $, @, % variables
- if (PGvars.has(stream.current().substring(1)))
- return PGstyle;
- else
- return "variable";
+ if (prevState.mode == 'cmd') {
+ // Some formatting for [@ ... @] blocks
+ if (stream.match(/^[$@%]\w+/)) {
+ // $, @, % variables
+ if (PGvars.has(stream.current().substring(1))) return PGstyle;
+ else return 'variable';
}
- if (stream.match(/^[$@%]{\w+}/)) { // ${foo}, @{foo}, %{foo} variables
- if (PGvars.has(stream.current().slice(2,-1)))
- return PGstyle;
- else
- return "variable";
+ if (stream.match(/^[$@%]{\w+}/)) {
+ // ${foo}, @{foo}, %{foo} variables
+ if (PGvars.has(stream.current().slice(2, -1))) return PGstyle;
+ else return 'variable';
}
- if (stream.match(/^[$@%]{/)) { // ${, @{, %{ nested blocks
- style = "variable";
- state.tokenize = function(stream,state) {
- return tokenPGMLSubBlock(stream,state,"\\}",style,newPrevState);
- }
+ if (stream.match(/^[$@%]{/)) {
+ // ${, @{, %{ nested blocks
+ style = 'variable';
+ state.tokenize = function (stream, state) {
+ return tokenPGMLSubBlock(stream, state, '\\}', style, newPrevState);
+ };
return style;
}
- if (stream.match(/^\(/)) { // Nested ( ) blocks
- newPrevState.endstyle = "variable";
- state.tokenize = function(stream,state) {
- return tokenPGMLSubBlock(stream,state,"\\)",style,newPrevState);
- }
- return "variable";
+ if (stream.match(/^\(/)) {
+ // Nested ( ) blocks
+ newPrevState.endstyle = 'variable';
+ state.tokenize = function (stream, state) {
+ return tokenPGMLSubBlock(stream, state, '\\)', style, newPrevState);
+ };
+ return 'variable';
}
- if (stream.match(/^\w+/)) { // Check for PG keywords
- if (PGcmds.has(stream.current()))
- return PGkeyword;
- else
- return style;
+ if (stream.match(/^\w+/)) {
+ // Check for PG keywords
+ if (PGcmds.has(stream.current())) return PGkeyword;
+ else return style;
}
- if (stream.match(/^['"]/)) { // Quotes
- return tokenChain(stream,state,[stream.current()],"string",null,function(stream,state) {
- tokenPGMLSubBlock(stream,state,string,style,prevState) });
+ if (stream.match(/^['"]/)) {
+ // Quotes
+ return tokenChain(stream, state, [stream.current()], 'string', null, function (stream, state) {
+ tokenPGMLSubBlock(stream, state, string, style, prevState);
+ });
}
- if (stream.match(/^[=,;/\*><%$&|.~?:]/)) // Catch some perl operators
- return "variable";
+ if (stream.match(/^[=,;/\*><%$&|.~?:]/))
+ // Catch some perl operators
+ return 'variable';
}
- if (stream.match(/^\[\$/)) { // Variable
+ if (stream.match(/^\[\$/)) {
+ // Variable
const p = stream.pos;
if (stream.match(/^\w+/) && PGvars.has(stream.current().substring(2)) && stream.eat(']')) {
stream.match(/^\*{1,3}/);
@@ -898,62 +930,66 @@
} else {
stream.pos = p;
}
- style = "variable";
- state.tokenize = function(stream,state) {
- newPrevState.mode = "var";
- return tokenPGMLSubBlock(stream,state,"\\]",style,newPrevState);
- }
- } else if (stream.match(/^\[/)) { // Nested [ ] blocks
- if (prevState.mode == "cmd")
- newPrevState.endstyle = "variable";
- state.tokenize = function(stream,state) {
- return tokenPGMLSubBlock(stream,state,"\\]",style,newPrevState);
- }
- if (prevState.mode == "cmd")
- return "variable";
- } else if (stream.match(/^\{/)) { // Nested { } blocks
- if (prevState.mode == "cmd")
- newPrevState.endstyle = "variable";
- state.tokenize = function(stream,state) {
- return tokenPGMLSubBlock(stream,state,"\\}",style,newPrevState);
- }
- if (prevState.mode == "cmd")
- return "variable";
- } else if (stream.match(/^\w+\s*/)) { // Grab next word before going forward
+ style = 'variable';
+ state.tokenize = function (stream, state) {
+ newPrevState.mode = 'var';
+ return tokenPGMLSubBlock(stream, state, '\\]', style, newPrevState);
+ };
+ } else if (stream.match(/^\[/)) {
+ // Nested [ ] blocks
+ if (prevState.mode == 'cmd') newPrevState.endstyle = 'variable';
+ state.tokenize = function (stream, state) {
+ return tokenPGMLSubBlock(stream, state, '\\]', style, newPrevState);
+ };
+ if (prevState.mode == 'cmd') return 'variable';
+ } else if (stream.match(/^\{/)) {
+ // Nested { } blocks
+ if (prevState.mode == 'cmd') newPrevState.endstyle = 'variable';
+ state.tokenize = function (stream, state) {
+ return tokenPGMLSubBlock(stream, state, '\\}', style, newPrevState);
+ };
+ if (prevState.mode == 'cmd') return 'variable';
+ } else if (stream.match(/^\w+\s*/)) {
+ // Grab next word before going forward
return style;
- } else { // Catchall to advanced one character if no match was found.
+ } else {
+ // Catchall to advanced one character if no match was found.
stream.eat(/./);
}
return style;
- }
- return state.tokenize(stream,state);
+ };
+ return state.tokenize(stream, state);
}
// Main PGML block. Can nest to allow subblocks with PGML formatting in them.
- function tokenPGML(stream,state,string,style,prevState){
- state.tokenize = function(stream,state) {
- var reg = new RegExp("^"+string);
+ function tokenPGML(stream, state, string, style, prevState) {
+ state.tokenize = function (stream, state) {
+ var reg = new RegExp('^' + string);
if (stream.match(reg)) {
if (!prevState) {
state.tokenize = tokenPerl;
return PGkeyword;
- // Needed to ensure ': ' verbatim lines exit out if ended with a secondary block.
+ // Needed to ensure ': ' verbatim lines exit out if ended with a secondary block.
} else if (stream.eol() && prevState.prevState && prevState.prevState.stopeol) {
- state.tokenize = function(stream,state) {
- return tokenPGML(stream,state,prevState.prevState.string,
- prevState.prevState.style,prevState.prevState.prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenPGML(
+ stream,
+ state,
+ prevState.prevState.string,
+ prevState.prevState.style,
+ prevState.prevState.prevState
+ );
+ };
} else {
- state.tokenize = function(stream,state) {
- return tokenPGML(stream,state,prevState.string,
- prevState.style,prevState.prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenPGML(stream, state, prevState.string, prevState.style, prevState.prevState);
+ };
}
return style;
} else {
- state.tokenize = function(stream,state) {
- return tokenPGML(stream,state,string,style,prevState);
- }
+ state.tokenize = function (stream, state) {
+ return tokenPGML(stream, state, string, style, prevState);
+ };
}
var newPrevState = {};
@@ -966,68 +1002,82 @@
newPrevState.string = string;
if (stream.sol()) {
- if (stream.match(/^ *(>> +)?[ivxlIVXL]+[.)] /) ||
- stream.match(/^ *(>> +)?\d+[.)] /) ||
- stream.match(/^ *(>> +)?\w[.)] /) ||
- stream.match(/^ *(>> +)?[*\-+o] /)) { // Lists
- return "atom strong";
+ if (
+ stream.match(/^ *(>> +)?[ivxlIVXL]+[.)] /) ||
+ stream.match(/^ *(>> +)?\d+[.)] /) ||
+ stream.match(/^ *(>> +)?\w[.)] /) ||
+ stream.match(/^ *(>> +)?[*\-+o] /)
+ ) {
+ // Lists
+ return 'atom strong';
}
- if (stream.match(/^ *[\-=]{3,}/)) { // Rules
+ if (stream.match(/^ *[\-=]{3,}/)) {
+ // Rules
stream.match(/^\{[^}]*\}/);
stream.match(/^\{[^}]*\}/);
- return "hr";
+ return 'hr';
}
- if (stream.match(/^ *(>> +)?#{1,}.*$/)) // Headers
- return "header";
- if (stream.match(/^ *>> /)) // Justification
- return "atom strong";
- if (stream.match(/^ *: /)) { // Single line verbatim
- style = "tag";
- state.tokenize = function(stream,state) {
+ if (stream.match(/^ *(>> +)?#{1,}.*$/))
+ // Headers
+ return 'header';
+ if (stream.match(/^ *>> /))
+ // Justification
+ return 'atom strong';
+ if (stream.match(/^ *: /)) {
+ // Single line verbatim
+ style = 'tag';
+ state.tokenize = function (stream, state) {
newPrevState.stopeol = true;
- return tokenPGML(stream,state,".$",style,newPrevState);
- }
+ return tokenPGML(stream, state, '.$', style, newPrevState);
+ };
return style;
}
}
- if (stream.match(/^\[:{1,3}/)) { // Algebra notation math
- style = "variable-3";
- const endstring = stream.current().substring(1) + "\\]";
- state.tokenize = function(stream,state) {
- newPrevState.mode = "calc";
- return tokenPGMLSubBlock(stream,state,endstring,style,newPrevState);
- }
- } else if (stream.match(/^\[`{1,3}/)) { // TeX notation math
- style = "comment";
- const endstring = stream.current().substring(1) + "\\]";
- state.tokenize = function(stream,state) {
- newPrevState.mode = "tex";
- return tokenPGMLSubBlock(stream,state,endstring,style,newPrevState);
- }
- } else if (stream.match(/^\[\|+/)) { // Verbatim
- style = "tag";
- const endstring = stream.current().substring(1) + "\\]";
- state.tokenize = function(stream,state) {
- return tokenPGML(stream,state,endstring,style,newPrevState);
- }
- } else if (!prevState && stream.match(/^```/)) { // Multiline verbatim / code
- style = "tag";
- state.tokenize = function(stream,state) {
- return tokenPGMLComment(stream,state,"```",style,newPrevState);
- }
- } else if (stream.match(/^\[%/)) { // Comment
- style = "comment";
- state.tokenize = function(stream,state) {
- return tokenPGMLComment(stream,state,"%\\]",style,newPrevState);
- }
- } else if (stream.match(/^\[@/)) { // Perl code
- style = "variable-2";
- state.tokenize = function(stream,state) {
- newPrevState.mode = "cmd";
- return tokenPGMLSubBlock(stream,state,"@\\]",style,newPrevState);
- }
- } else if (stream.match(/^\[\$/)) { // Variable
+ if (stream.match(/^\[:{1,3}/)) {
+ // Algebra notation math
+ style = 'variable-3';
+ const endstring = stream.current().substring(1) + '\\]';
+ state.tokenize = function (stream, state) {
+ newPrevState.mode = 'calc';
+ return tokenPGMLSubBlock(stream, state, endstring, style, newPrevState);
+ };
+ } else if (stream.match(/^\[`{1,3}/)) {
+ // TeX notation math
+ style = 'comment';
+ const endstring = stream.current().substring(1) + '\\]';
+ state.tokenize = function (stream, state) {
+ newPrevState.mode = 'tex';
+ return tokenPGMLSubBlock(stream, state, endstring, style, newPrevState);
+ };
+ } else if (stream.match(/^\[\|+/)) {
+ // Verbatim
+ style = 'tag';
+ const endstring = stream.current().substring(1) + '\\]';
+ state.tokenize = function (stream, state) {
+ return tokenPGML(stream, state, endstring, style, newPrevState);
+ };
+ } else if (!prevState && stream.match(/^```/)) {
+ // Multiline verbatim / code
+ style = 'tag';
+ state.tokenize = function (stream, state) {
+ return tokenPGMLComment(stream, state, '```', style, newPrevState);
+ };
+ } else if (stream.match(/^\[%/)) {
+ // Comment
+ style = 'comment';
+ state.tokenize = function (stream, state) {
+ return tokenPGMLComment(stream, state, '%\\]', style, newPrevState);
+ };
+ } else if (stream.match(/^\[@/)) {
+ // Perl code
+ style = 'variable-2';
+ state.tokenize = function (stream, state) {
+ newPrevState.mode = 'cmd';
+ return tokenPGMLSubBlock(stream, state, '@\\]', style, newPrevState);
+ };
+ } else if (stream.match(/^\[\$/)) {
+ // Variable
const p = stream.pos;
if (stream.match(/^[\w\d_]+/) && PGvars.has(stream.current().substring(2)) && stream.eat(']')) {
stream.match(/^\*{1,3}/);
@@ -1035,376 +1085,418 @@
} else {
stream.pos = p;
}
- style = "variable";
- state.tokenize = function(stream,state) {
- newPrevState.mode = "var";
- return tokenPGMLSubBlock(stream,state,"\\]",style,newPrevState);
- }
- } else if (stream.match(/^\[_+\]/)) { // Answer blank
+ style = 'variable';
+ state.tokenize = function (stream, state) {
+ newPrevState.mode = 'var';
+ return tokenPGMLSubBlock(stream, state, '\\]', style, newPrevState);
+ };
+ } else if (stream.match(/^\[_+\]/)) {
+ // Answer blank
if (stream.match(/^\*?\{/)) {
- state.tokenize = function(stream,state) {
- return tokenPGMLSubBlock(stream,state,"\\}","builtin",newPrevState);
- }
- }
- return "builtin";
- } else if (stream.match(/<< *$/)) { // Justification
- return "atom strong";
- } else if (stream.match(/^(\*_|_\*)\w/)) { // Bold and italic
- style = style + " strong em";
- const endstring = (stream.current().charAt(1) + stream.current().charAt(0)).replace(/\*/, "\\*");
- state.tokenize = function(stream,state) {
- return tokenPGML(stream,state,endstring,style,newPrevState);
+ state.tokenize = function (stream, state) {
+ return tokenPGMLSubBlock(stream, state, '\\}', 'builtin', newPrevState);
+ };
}
- } else if (stream.match(/^\*{1,3}\w/)) { // Bold
- style = style + " strong";
- const endstring = stream.current().slice(0,-1).replace(/\*/g, "\\*");
- state.tokenize = function(stream,state) {
- return tokenPGML(stream,state,endstring,style,newPrevState);
- }
- } else if (stream.match(/^_{1,3}\w/)) { // Italic
- style = style + " em";
- const endstring = stream.current().slice(0,-1);
- state.tokenize = function(stream,state) {
- return tokenPGML(stream,state,endstring,style,newPrevState);
- }
- } else if (stream.match(/^ +$/)) { // Trailing whitespace
- return "trailingspace";
- } else if (stream.match(/[A-Za-z0-9]+\s*/)) { // Grab next word before going forward
+ return 'builtin';
+ } else if (stream.match(/<< *$/)) {
+ // Justification
+ return 'atom strong';
+ } else if (stream.match(/^(\*_|_\*)\w/)) {
+ // Bold and italic
+ style = style + ' strong em';
+ const endstring = (stream.current().charAt(1) + stream.current().charAt(0)).replace(/\*/, '\\*');
+ state.tokenize = function (stream, state) {
+ return tokenPGML(stream, state, endstring, style, newPrevState);
+ };
+ } else if (stream.match(/^\*{1,3}\w/)) {
+ // Bold
+ style = style + ' strong';
+ const endstring = stream.current().slice(0, -1).replace(/\*/g, '\\*');
+ state.tokenize = function (stream, state) {
+ return tokenPGML(stream, state, endstring, style, newPrevState);
+ };
+ } else if (stream.match(/^_{1,3}\w/)) {
+ // Italic
+ style = style + ' em';
+ const endstring = stream.current().slice(0, -1);
+ state.tokenize = function (stream, state) {
+ return tokenPGML(stream, state, endstring, style, newPrevState);
+ };
+ } else if (stream.match(/^ +$/)) {
+ // Trailing whitespace
+ return 'trailingspace';
+ } else if (stream.match(/[A-Za-z0-9]+\s*/)) {
+ // Grab next word before going forward
return style;
- } else { // Catchall to advanced one character if no match was found.
+ } else {
+ // Catchall to advanced one character if no match was found.
stream.eat(/./);
}
return style;
};
- return state.tokenize(stream,state);
+ return state.tokenize(stream, state);
}
- function tokenPerl(stream,state){
- if(stream.eatSpace())
- return null;
- if(state.chain)
- return tokenChain(stream,state,state.chain,state.style,state.tail);
- if(stream.match(/^(\-?((\d[\d_]*)?\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F_]+|0b[01_]+|\d[\d_]*(e[+-]?\d+)?)/))
+ function tokenPerl(stream, state) {
+ if (stream.eatSpace()) return null;
+ if (state.chain) return tokenChain(stream, state, state.chain, state.style, state.tail);
+ if (
+ stream.match(
+ /^(\-?((\d[\d_]*)?\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F_]+|0b[01_]+|\d[\d_]*(e[+-]?\d+)?)/
+ )
+ )
return 'number';
- if(stream.match(/^<<(?=[_a-zA-Z])/)){ // NOTE: <
"],RXstyle,RXmodifiers);}
- if(/[\^'"!~\/]/.test(c)){
+ return tokenChain(stream, state, ['>'], RXstyle, RXmodifiers);
+ }
+ if (/[\^'"!~\/]/.test(c)) {
eatSuffix(stream, 1);
- return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}
- else if(c=="q"){
- c=look(stream, 1);
- if(c=="("){
+ return tokenChain(stream, state, [stream.eat(c)], RXstyle, RXmodifiers);
+ }
+ } else if (c == 'q') {
+ c = look(stream, 1);
+ if (c == '(') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,[")"],"string");}
- if(c=="["){
+ return tokenChain(stream, state, [')'], 'string');
+ }
+ if (c == '[') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,["]"],"string");}
- if(c=="{"){
+ return tokenChain(stream, state, [']'], 'string');
+ }
+ if (c == '{') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,["}"],"string");}
- if(c=="<"){
+ return tokenChain(stream, state, ['}'], 'string');
+ }
+ if (c == '<') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,[">"],"string");}
- if(/[\^'"!~\/]/.test(c)){
+ return tokenChain(stream, state, ['>'], 'string');
+ }
+ if (/[\^'"!~\/]/.test(c)) {
eatSuffix(stream, 1);
- return tokenChain(stream,state,[stream.eat(c)],"string");}}
- else if(c=="w"){
- c=look(stream, 1);
- if(c=="("){
+ return tokenChain(stream, state, [stream.eat(c)], 'string');
+ }
+ } else if (c == 'w') {
+ c = look(stream, 1);
+ if (c == '(') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,[")"],"bracket");}
- if(c=="["){
+ return tokenChain(stream, state, [')'], 'bracket');
+ }
+ if (c == '[') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,["]"],"bracket");}
- if(c=="{"){
+ return tokenChain(stream, state, [']'], 'bracket');
+ }
+ if (c == '{') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,["}"],"bracket");}
- if(c=="<"){
+ return tokenChain(stream, state, ['}'], 'bracket');
+ }
+ if (c == '<') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,[">"],"bracket");}
- if(/[\^'"!~\/]/.test(c)){
+ return tokenChain(stream, state, ['>'], 'bracket');
+ }
+ if (/[\^'"!~\/]/.test(c)) {
eatSuffix(stream, 1);
- return tokenChain(stream,state,[stream.eat(c)],"bracket");}}
- else if(c=="r"){
- c=look(stream, 1);
- if(c=="("){
+ return tokenChain(stream, state, [stream.eat(c)], 'bracket');
+ }
+ } else if (c == 'r') {
+ c = look(stream, 1);
+ if (c == '(') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
- if(c=="["){
+ return tokenChain(stream, state, [')'], RXstyle, RXmodifiers);
+ }
+ if (c == '[') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
- if(c=="{"){
+ return tokenChain(stream, state, [']'], RXstyle, RXmodifiers);
+ }
+ if (c == '{') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
- if(c=="<"){
+ return tokenChain(stream, state, ['}'], RXstyle, RXmodifiers);
+ }
+ if (c == '<') {
eatSuffix(stream, 2);
- return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}
- if(/[\^'"!~\/]/.test(c)){
+ return tokenChain(stream, state, ['>'], RXstyle, RXmodifiers);
+ }
+ if (/[\^'"!~\/]/.test(c)) {
eatSuffix(stream, 1);
- return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}}
- else if(/[\^'"!~\/(\[{<]/.test(c)){
- if(c=="("){
+ return tokenChain(stream, state, [stream.eat(c)], RXstyle, RXmodifiers);
+ }
+ } else if (/[\^'"!~\/(\[{<]/.test(c)) {
+ if (c == '(') {
eatSuffix(stream, 1);
- return tokenChain(stream,state,[")"],"string");}
- if(c=="["){
+ return tokenChain(stream, state, [')'], 'string');
+ }
+ if (c == '[') {
eatSuffix(stream, 1);
- return tokenChain(stream,state,["]"],"string");}
- if(c=="{"){
+ return tokenChain(stream, state, [']'], 'string');
+ }
+ if (c == '{') {
eatSuffix(stream, 1);
- return tokenChain(stream,state,["}"],"string");}
- if(c=="<"){
+ return tokenChain(stream, state, ['}'], 'string');
+ }
+ if (c == '<') {
eatSuffix(stream, 1);
- return tokenChain(stream,state,[">"],"string");}
- if(/[\^'"!~\/]/.test(c)){
- return tokenChain(stream,state,[stream.eat(c)],"string");}}}}
- if(ch=="m"){
- var c=look(stream, -2);
- if(!(c&&/\w/.test(c))){
- c=stream.eat(/[(\[{<\^'"!~\/]/);
- if(c){
- if(/[\^'"!~\/]/.test(c)){
- return tokenChain(stream,state,[c],RXstyle,RXmodifiers);}
- if(c=="("){
- return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);}
- if(c=="["){
- return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);}
- if(c=="{"){
- return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);}
- if(c=="<"){
- return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}}}}
- if(ch=="s"){
- var c=/[\/>\]})\w]/.test(look(stream, -2));
- if(!c){
- c=stream.eat(/[(\[{<\^'"!~\/]/);
- if(c){
- if(c=="[")
- return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
- if(c=="{")
- return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
- if(c=="<")
- return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
- if(c=="(")
- return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
- return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}
- if(ch=="y"){
- var c=/[\/>\]})\w]/.test(look(stream, -2));
- if(!c){
- c=stream.eat(/[(\[{<\^'"!~\/]/);
- if(c){
- if(c=="[")
- return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
- if(c=="{")
- return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
- if(c=="<")
- return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
- if(c=="(")
- return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
- return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}
- if(ch=="t"){
- var c=/[\/>\]})\w]/.test(look(stream, -2));
- if(!c){
- c=stream.eat("r");if(c){
- c=stream.eat(/[(\[{<\^'"!~\/]/);
- if(c){
- if(c=="[")
- return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers);
- if(c=="{")
- return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers);
- if(c=="<")
- return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers);
- if(c=="(")
- return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers);
- return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}}
- if(ch=="`"){
- return tokenChain(stream,state,[ch],"variable-2");}
- if(ch=="/"){
- if(!/~\s*$/.test(prefix(stream)))
- return "operator";
- else
- return tokenChain(stream,state,[ch],RXstyle,RXmodifiers);}
- if(ch=="$"){
- var p=stream.pos;
- if(stream.eatWhile(/\w/)&&PGvars.has(stream.current().substring(1)))
- return PGstyle;
- else
- stream.pos=p;
- if(stream.eatWhile(/\d/)||stream.eat("{")&&stream.eatWhile(/\d/)&&stream.eat("}"))
- return "variable-2";
- else
- stream.pos=p;}
- if(/[$@%]/.test(ch)){
- var p=stream.pos;
- if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(look(stream, -2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){
- var c=stream.current();
- if(PERL[c])
- return "variable-2";}
- stream.pos=p;}
- if(/[$@%&]/.test(ch)){
- if(stream.eatWhile(/[\w$]/)||stream.eat("{")&&stream.eatWhile(/[\w$]/)&&stream.eat("}")){
- var c=stream.current();
- if(PERL[c])
- return "variable-2";
- else
- return "variable";}}
- if(ch=="#"){
- if(look(stream, -2)!="$"){
+ return tokenChain(stream, state, ['>'], 'string');
+ }
+ if (/[\^'"!~\/]/.test(c)) {
+ return tokenChain(stream, state, [stream.eat(c)], 'string');
+ }
+ }
+ }
+ }
+ if (ch == 'm') {
+ var c = look(stream, -2);
+ if (!(c && /\w/.test(c))) {
+ c = stream.eat(/[(\[{<\^'"!~\/]/);
+ if (c) {
+ if (/[\^'"!~\/]/.test(c)) {
+ return tokenChain(stream, state, [c], RXstyle, RXmodifiers);
+ }
+ if (c == '(') {
+ return tokenChain(stream, state, [')'], RXstyle, RXmodifiers);
+ }
+ if (c == '[') {
+ return tokenChain(stream, state, [']'], RXstyle, RXmodifiers);
+ }
+ if (c == '{') {
+ return tokenChain(stream, state, ['}'], RXstyle, RXmodifiers);
+ }
+ if (c == '<') {
+ return tokenChain(stream, state, ['>'], RXstyle, RXmodifiers);
+ }
+ }
+ }
+ }
+ if (ch == 's') {
+ var c = /[\/>\]})\w]/.test(look(stream, -2));
+ if (!c) {
+ c = stream.eat(/[(\[{<\^'"!~\/]/);
+ if (c) {
+ if (c == '[') return tokenChain(stream, state, [']', ']'], RXstyle, RXmodifiers);
+ if (c == '{') return tokenChain(stream, state, ['}', '}'], RXstyle, RXmodifiers);
+ if (c == '<') return tokenChain(stream, state, ['>', '>'], RXstyle, RXmodifiers);
+ if (c == '(') return tokenChain(stream, state, [')', ')'], RXstyle, RXmodifiers);
+ return tokenChain(stream, state, [c, c], RXstyle, RXmodifiers);
+ }
+ }
+ }
+ if (ch == 'y') {
+ var c = /[\/>\]})\w]/.test(look(stream, -2));
+ if (!c) {
+ c = stream.eat(/[(\[{<\^'"!~\/]/);
+ if (c) {
+ if (c == '[') return tokenChain(stream, state, [']', ']'], RXstyle, RXmodifiers);
+ if (c == '{') return tokenChain(stream, state, ['}', '}'], RXstyle, RXmodifiers);
+ if (c == '<') return tokenChain(stream, state, ['>', '>'], RXstyle, RXmodifiers);
+ if (c == '(') return tokenChain(stream, state, [')', ')'], RXstyle, RXmodifiers);
+ return tokenChain(stream, state, [c, c], RXstyle, RXmodifiers);
+ }
+ }
+ }
+ if (ch == 't') {
+ var c = /[\/>\]})\w]/.test(look(stream, -2));
+ if (!c) {
+ c = stream.eat('r');
+ if (c) {
+ c = stream.eat(/[(\[{<\^'"!~\/]/);
+ if (c) {
+ if (c == '[') return tokenChain(stream, state, [']', ']'], RXstyle, RXmodifiers);
+ if (c == '{') return tokenChain(stream, state, ['}', '}'], RXstyle, RXmodifiers);
+ if (c == '<') return tokenChain(stream, state, ['>', '>'], RXstyle, RXmodifiers);
+ if (c == '(') return tokenChain(stream, state, [')', ')'], RXstyle, RXmodifiers);
+ return tokenChain(stream, state, [c, c], RXstyle, RXmodifiers);
+ }
+ }
+ }
+ }
+ if (ch == '`') {
+ return tokenChain(stream, state, [ch], 'variable-2');
+ }
+ if (ch == '/') {
+ if (!/~\s*$/.test(prefix(stream))) return 'operator';
+ else return tokenChain(stream, state, [ch], RXstyle, RXmodifiers);
+ }
+ if (ch == '$') {
+ var p = stream.pos;
+ if (stream.eatWhile(/\w/) && PGvars.has(stream.current().substring(1))) return PGstyle;
+ else stream.pos = p;
+ if (stream.eatWhile(/\d/) || (stream.eat('{') && stream.eatWhile(/\d/) && stream.eat('}')))
+ return 'variable-2';
+ else stream.pos = p;
+ }
+ if (/[$@%]/.test(ch)) {
+ var p = stream.pos;
+ if (
+ (stream.eat('^') && stream.eat(/[A-Z]/)) ||
+ (!/[@$%&]/.test(look(stream, -2)) && stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/))
+ ) {
+ var c = stream.current();
+ if (PERL[c]) return 'variable-2';
+ }
+ stream.pos = p;
+ }
+ if (/[$@%&]/.test(ch)) {
+ if (stream.eatWhile(/[\w$]/) || (stream.eat('{') && stream.eatWhile(/[\w$]/) && stream.eat('}'))) {
+ var c = stream.current();
+ if (PERL[c]) return 'variable-2';
+ else return 'variable';
+ }
+ }
+ if (ch == '#') {
+ if (look(stream, -2) != '$') {
stream.skipToEnd();
- return "comment";}}
- if(ch=="-"&&look(stream, -2)!=" "&&stream.match(/>\w+/))
- return "variable";
- if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){
- var p=stream.pos;
+ return 'comment';
+ }
+ }
+ if (ch == '-' && look(stream, -2) != ' ' && stream.match(/>\w+/)) return 'variable';
+ if (/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)) {
+ var p = stream.pos;
stream.eatWhile(/[:+\-\^*$&%@=<>!?|\/~\.]/);
- if(PERL[stream.current()])
- return "operator";
- else
- stream.pos=p;}
- if(ch=="_"){
- if(stream.pos==1){
- if(suffix(stream, 6)=="_END__"){
- return tokenChain(stream,state,['\0'],"comment");}
- else if(suffix(stream, 7)=="_DATA__"){
- return tokenChain(stream,state,['\0'],"variable-2");}
- else if(suffix(stream, 7)=="_C__"){
- return tokenChain(stream,state,['\0'],"string");}}}
- if(/\w/.test(ch)){
- var p=stream.pos;
- if(look(stream, -2)=="{"&&(look(stream, 0)=="}"||stream.eatWhile(/\w/)&&look(stream, 0)=="}"))
- return "string";
- else
- stream.pos=p;
- if(stream.match(/\w* *=>/))
- return "string";}
- if(/[A-Z]/.test(ch)){
- var l=look(stream, -2);
- var p=stream.pos;
+ if (PERL[stream.current()]) return 'operator';
+ else stream.pos = p;
+ }
+ if (ch == '_') {
+ if (stream.pos == 1) {
+ if (suffix(stream, 6) == '_END__') {
+ return tokenChain(stream, state, ['\0'], 'comment');
+ } else if (suffix(stream, 7) == '_DATA__') {
+ return tokenChain(stream, state, ['\0'], 'variable-2');
+ } else if (suffix(stream, 7) == '_C__') {
+ return tokenChain(stream, state, ['\0'], 'string');
+ }
+ }
+ }
+ if (/\w/.test(ch)) {
+ var p = stream.pos;
+ if (
+ look(stream, -2) == '{' &&
+ (look(stream, 0) == '}' || (stream.eatWhile(/\w/) && look(stream, 0) == '}'))
+ )
+ return 'string';
+ else stream.pos = p;
+ if (stream.match(/\w* *=>/)) return 'string';
+ }
+ if (/[A-Z]/.test(ch)) {
+ var l = look(stream, -2);
+ var p = stream.pos;
stream.eatWhile(/[A-Z_]/);
- if(/[\da-z]/.test(look(stream, 0))){
- stream.pos=p;}
- else{
- var c=PERL[stream.current()];
+ if (/[\da-z]/.test(look(stream, 0))) {
+ stream.pos = p;
+ } else {
+ var c = PERL[stream.current()];
var isPG = PGcmds.has(stream.current());
- if(!c && !isPG)
- return "meta";
- if(isPG)
- return PGkeyword;
- if(c[1])
- c=c[0];
- if(l!=":"){
- if(c==1)
- return "keyword";
- else if(c==2)
- return "def";
- else if(c==3)
- return "atom";
- else if(c==4)
- return "operator";
- else if(c==5)
- return "variable-2";
- else
- return "meta";}
- else
- return "meta";}}
- if(/[a-zA-Z_]/.test(ch)){
- var l=look(stream, -2);
+ if (!c && !isPG) return 'meta';
+ if (isPG) return PGkeyword;
+ if (c[1]) c = c[0];
+ if (l != ':') {
+ if (c == 1) return 'keyword';
+ else if (c == 2) return 'def';
+ else if (c == 3) return 'atom';
+ else if (c == 4) return 'operator';
+ else if (c == 5) return 'variable-2';
+ else return 'meta';
+ } else return 'meta';
+ }
+ }
+ if (/[a-zA-Z_]/.test(ch)) {
+ var l = look(stream, -2);
stream.eatWhile(/\w/);
- var c=PERL[stream.current()];
+ var c = PERL[stream.current()];
var isPG = PGcmds.has(stream.current());
- if(!c && !isPG)
- return "meta";
- if(isPG)
- return PGkeyword;
- if(c[1])
- c=c[0];
- if(l!=":"){
- if(c==1)
- return "keyword";
- else if(c==2)
- return "def";
- else if(c==3)
- return "atom";
- else if(c==4)
- return "operator";
- else if(c==5)
- return "variable-2";
- else
- return "meta";}
- else
- return "meta";}
- return null;}
+ if (!c && !isPG) return 'meta';
+ if (isPG) return PGkeyword;
+ if (c[1]) c = c[0];
+ if (l != ':') {
+ if (c == 1) return 'keyword';
+ else if (c == 2) return 'def';
+ else if (c == 3) return 'atom';
+ else if (c == 4) return 'operator';
+ else if (c == 5) return 'variable-2';
+ else return 'meta';
+ } else return 'meta';
+ }
+ return null;
+ }
return {
- startState: function() {
+ startState: function () {
return {
tokenize: tokenPerl,
chain: null,
@@ -1412,14 +1504,14 @@
tail: null
};
},
- token: function(stream, state) {
+ token: function (stream, state) {
return (state.tokenize || tokenPerl)(stream, state);
},
lineComment: '#'
};
});
- CodeMirror.registerHelper("wordChars", "perl", /[\w$]/);
+ CodeMirror.registerHelper('wordChars', 'perl', /[\w$]/);
CodeMirror.registerHelper('fold', 'PG', (cm, start) => {
const m1 =
@@ -1429,7 +1521,7 @@
if (m1 || m2) {
for (let current_line = start.line + 1; current_line <= cm.lineCount(); ++current_line) {
const end_re = m1 ? RegExp(`END_${m1[1]}`) : RegExp(`${m2[1]}::End`);
- if(end_re.test(cm.getLine(current_line))) {
+ if (end_re.test(cm.getLine(current_line))) {
return {
from: CodeMirror.Pos(start.line, cm.getLine(start.line).length),
to: CodeMirror.Pos(current_line, cm.getLine(current_line).length)
@@ -1440,40 +1532,36 @@
return;
});
- CodeMirror.defineMIME("text/x-perl", "perl");
+ CodeMirror.defineMIME('text/x-perl', 'perl');
// it's like "peek", but need for look-ahead or look-behind if index < 0
- function look(stream, c){
- return stream.string.charAt(stream.pos+(c||0));
+ function look(stream, c) {
+ return stream.string.charAt(stream.pos + (c || 0));
}
// return a part of prefix of current stream from current position
- function prefix(stream, c){
- if(c){
- var x=stream.pos-c;
- return stream.string.substr((x>=0?x:0),c);}
- else{
- return stream.string.substr(0,stream.pos-1);
+ function prefix(stream, c) {
+ if (c) {
+ var x = stream.pos - c;
+ return stream.string.substr(x >= 0 ? x : 0, c);
+ } else {
+ return stream.string.substr(0, stream.pos - 1);
}
}
// return a part of suffix of current stream from current position
- function suffix(stream, c){
- var y=stream.string.length;
- var x=y-stream.pos+1;
- return stream.string.substr(stream.pos,(c&&c=(y=stream.string.length-1))
- stream.pos=y;
- else
- stream.pos=x;
+ if (x <= 0) stream.pos = 0;
+ else if (x >= (y = stream.string.length - 1)) stream.pos = y;
+ else stream.pos = x;
}
-
})();
diff --git a/htdocs/js/PGCodeMirror/comment.js b/htdocs/js/PGCodeMirror/comment.js
index 0735a801e1..356b9ce146 100644
--- a/htdocs/js/PGCodeMirror/comment.js
+++ b/htdocs/js/PGCodeMirror/comment.js
@@ -1,42 +1,51 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/5/LICENSE
-(function(mod) {
- if (typeof exports == "object" && typeof module == "object") // CommonJS
- mod(require("../../lib/codemirror"));
- else if (typeof define == "function" && define.amd) // AMD
- define(["../../lib/codemirror"], mod);
- else // Plain browser env
- mod(CodeMirror);
-})(function(CodeMirror) {
- "use strict";
+(function (mod) {
+ if (typeof exports == 'object' && typeof module == 'object')
+ // CommonJS
+ mod(require('../../lib/codemirror'));
+ else if (typeof define == 'function' && define.amd)
+ // AMD
+ define(['../../lib/codemirror'], mod);
+ // Plain browser env
+ else mod(CodeMirror);
+})(function (CodeMirror) {
+ 'use strict';
var noOptions = {};
var nonWS = /[^\s\u00a0]/;
- var Pos = CodeMirror.Pos, cmp = CodeMirror.cmpPos;
+ var Pos = CodeMirror.Pos,
+ cmp = CodeMirror.cmpPos;
function firstNonWS(str) {
var found = str.search(nonWS);
return found == -1 ? 0 : found;
}
- CodeMirror.commands.toggleComment = function(cm) {
+ CodeMirror.commands.toggleComment = function (cm) {
cm.toggleComment();
};
- CodeMirror.defineExtension("toggleComment", function(options) {
+ CodeMirror.defineExtension('toggleComment', function (options) {
if (!options) options = noOptions;
var cm = this;
- var minLine = Infinity, ranges = this.listSelections(), mode = null;
+ var minLine = Infinity,
+ ranges = this.listSelections(),
+ mode = null;
for (var i = ranges.length - 1; i >= 0; i--) {
- var from = ranges[i].from(), to = ranges[i].to();
+ var from = ranges[i].from(),
+ to = ranges[i].to();
if (from.line >= minLine) continue;
if (to.line >= minLine) to = Pos(minLine, 0);
minLine = from.line;
if (mode == null) {
- if (cm.uncomment(from, to, options)) mode = "un";
- else { cm.lineComment(from, to, options); mode = "line"; }
- } else if (mode == "un") {
+ if (cm.uncomment(from, to, options)) mode = 'un';
+ else {
+ cm.lineComment(from, to, options);
+ mode = 'line';
+ }
+ } else if (mode == 'un') {
cm.uncomment(from, to, options);
} else {
cm.lineComment(from, to, options);
@@ -46,11 +55,13 @@
// Rough heuristic to try and detect lines that are part of multi-line string
function probablyInsideString(cm, pos, line) {
- return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"\`]/.test(line)
+ return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"\`]/.test(line);
}
- const md_section = RegExp('DESCRIPTION|KEYWORDS|DBsubject|DBchapter|DBsection|Date|Author|Institution ' +
- '|MO|Static|TitleText|EditionText|AuthorText|Section|Problem|Language|Level');
+ const md_section = RegExp(
+ 'DESCRIPTION|KEYWORDS|DBsubject|DBchapter|DBsection|Date|Author|Institution ' +
+ '|MO|Static|TitleText|EditionText|AuthorText|Section|Problem|Language|Level'
+ );
// Custom version of getMode for PG files.
function getMode(cm, pos) {
@@ -60,7 +71,7 @@
delete mode.blockCommentStart;
delete mode.blockCommentEnd;
- if(md_section.test(cm.getLine(pos.line)) || insideDescriptionBlock(cm, pos)) {
+ if (md_section.test(cm.getLine(pos.line)) || insideDescriptionBlock(cm, pos)) {
mode.lineComment = '##';
mode.name = 'PG_meta';
} else if (inPGMLBlock(cm, pos)) {
@@ -78,7 +89,7 @@
}
function insideDescriptionBlock(cm, pos) {
- for(let line = pos.line; line >= 0; --line) {
+ for (let line = pos.line; line >= 0; --line) {
if (/ENDDESCRIPTION/.test(cm.getLine(line))) return false;
if (/DESCRIPTION/.test(cm.getLine(line))) return true;
}
@@ -86,7 +97,7 @@
}
function inTikzBlock(cm, pos) {
- for(let line = pos.line; line >= 0; --line){
+ for (let line = pos.line; line >= 0; --line) {
if (/BEGIN_TIKZ|BEGIN_LATEX_IMAGE/.test(cm.getLine(line))) return true;
if (/END_PGML|END_TIKZ|END_LATEX_IMAGE/.test(cm.getLine(line))) return false;
}
@@ -94,17 +105,17 @@
}
function inPGMLBlock(cm, pos) {
- for(let line = pos.line; line >= 0; --line){
+ for (let line = pos.line; line >= 0; --line) {
if (/BEGIN_PGML/.test(cm.getLine(line))) return true;
if (/END_PGML/.test(cm.getLine(line))) return false;
}
return false;
}
-
- CodeMirror.defineExtension("lineComment", function(from, to, options) {
+ CodeMirror.defineExtension('lineComment', function (from, to, options) {
if (!options) options = noOptions;
- var self = this, mode = getMode(self, from);
+ var self = this,
+ mode = getMode(self, from);
var firstLine = self.getLine(from.line);
if (firstLine == null || probablyInsideString(self, from, firstLine)) return;
@@ -118,10 +129,10 @@
}
var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
- var pad = options.padding == null ? " " : options.padding;
+ var pad = options.padding == null ? ' ' : options.padding;
var blankLines = options.commentBlankLines || from.line == to.line;
- self.operation(function() {
+ self.operation(function () {
if (options.indent) {
var baseString = null;
for (var i = from.line; i < end; ++i) {
@@ -132,23 +143,24 @@
}
}
for (var i = from.line; i < end; ++i) {
- var line = self.getLine(i), cut = baseString.length;
+ var line = self.getLine(i),
+ cut = baseString.length;
if (!blankLines && !nonWS.test(line)) continue;
if (line.slice(0, cut) != baseString) cut = firstNonWS(line);
self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut));
}
} else {
for (var i = from.line; i < end; ++i) {
- if (blankLines || nonWS.test(self.getLine(i)))
- self.replaceRange(commentString + pad, Pos(i, 0));
+ if (blankLines || nonWS.test(self.getLine(i))) self.replaceRange(commentString + pad, Pos(i, 0));
}
}
});
});
- CodeMirror.defineExtension("blockComment", function(from, to, options) {
+ CodeMirror.defineExtension('blockComment', function (from, to, options) {
if (!options) options = noOptions;
- var self = this, mode = getMode(self, from);
+ var self = this,
+ mode = getMode(self, from);
var startString = options.blockCommentStart || mode.blockCommentStart;
var endString = options.blockCommentEnd || mode.blockCommentEnd;
if (!startString || !endString) {
@@ -156,40 +168,45 @@
self.lineComment(from, to, options);
return;
}
- if (/\bcomment\b/.test(self.getTokenTypeAt(Pos(from.line, 0)))) return
+ if (/\bcomment\b/.test(self.getTokenTypeAt(Pos(from.line, 0)))) return;
var end = Math.min(to.line, self.lastLine());
if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end;
- var pad = options.padding == null ? " " : options.padding;
+ var pad = options.padding == null ? ' ' : options.padding;
if (from.line > end) return;
- self.operation(function() {
+ self.operation(function () {
if (options.fullLines != false) {
var lastLineHasText = nonWS.test(self.getLine(end));
self.replaceRange(pad + endString, Pos(end));
self.replaceRange(startString + pad, Pos(from.line, 0));
var lead = options.blockCommentLead || mode.blockCommentLead;
- if (lead != null) for (var i = from.line + 1; i <= end; ++i)
- if (i != end || lastLineHasText)
- self.replaceRange(lead + pad, Pos(i, 0));
+ if (lead != null)
+ for (var i = from.line + 1; i <= end; ++i)
+ if (i != end || lastLineHasText) self.replaceRange(lead + pad, Pos(i, 0));
} else {
- var atCursor = cmp(self.getCursor("to"), to) == 0, empty = !self.somethingSelected()
+ var atCursor = cmp(self.getCursor('to'), to) == 0,
+ empty = !self.somethingSelected();
self.replaceRange(endString, to);
- if (atCursor) self.setSelection(empty ? to : self.getCursor("from"), to)
+ if (atCursor) self.setSelection(empty ? to : self.getCursor('from'), to);
self.replaceRange(startString, from);
}
});
});
- CodeMirror.defineExtension("uncomment", function(from, to, options) {
+ CodeMirror.defineExtension('uncomment', function (from, to, options) {
if (!options) options = noOptions;
- var self = this, mode = getMode(self, from);
- var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
+ var self = this,
+ mode = getMode(self, from);
+ var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()),
+ start = Math.min(from.line, end);
// Try finding line comments
- var lineString = options.lineComment || mode.lineComment, lines = [];
- var pad = options.padding == null ? " " : options.padding, didSomething;
+ var lineString = options.lineComment || mode.lineComment,
+ lines = [];
+ var pad = options.padding == null ? ' ' : options.padding,
+ didSomething;
lineComment: {
if (!lineString) break lineComment;
for (var i = start; i <= end; ++i) {
@@ -200,14 +217,15 @@
if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment;
lines.push(line);
}
- self.operation(function() {
+ self.operation(function () {
for (var i = start; i <= end; ++i) {
var line = lines[i - start];
- var pos = line.indexOf(lineString), endPos = pos + lineString.length;
+ var pos = line.indexOf(lineString),
+ endPos = pos + lineString.length;
if (pos < 0) continue;
if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length;
didSomething = true;
- self.replaceRange("", Pos(i, pos), Pos(i, endPos));
+ self.replaceRange('', Pos(i, pos), Pos(i, endPos));
}
});
if (didSomething) return true;
@@ -218,42 +236,52 @@
var endString = options.blockCommentEnd || mode.blockCommentEnd;
if (!startString || !endString) return false;
var lead = options.blockCommentLead || mode.blockCommentLead;
- var startLine = self.getLine(start), open = startLine.indexOf(startString)
- if (open == -1) return false
- var endLine = end == start ? startLine : self.getLine(end)
+ var startLine = self.getLine(start),
+ open = startLine.indexOf(startString);
+ if (open == -1) return false;
+ var endLine = end == start ? startLine : self.getLine(end);
var close = endLine.indexOf(endString, end == start ? open + startString.length : 0);
- var insideStart = Pos(start, open + 1), insideEnd = Pos(end, close + 1);
- if (close == -1 ||
- !/comment/.test(self.getTokenTypeAt(insideStart)) ||
- !/comment/.test(self.getTokenTypeAt(insideEnd)) ||
- self.getRange(insideStart, insideEnd, "\n").indexOf(endString) > -1)
+ var insideStart = Pos(start, open + 1),
+ insideEnd = Pos(end, close + 1);
+ if (
+ close == -1 ||
+ !/comment/.test(self.getTokenTypeAt(insideStart)) ||
+ !/comment/.test(self.getTokenTypeAt(insideEnd)) ||
+ self.getRange(insideStart, insideEnd, '\n').indexOf(endString) > -1
+ )
return false;
// Avoid killing block comments completely outside the selection.
// Positions of the last startString before the start of the selection, and the first endString after it.
var lastStart = startLine.lastIndexOf(startString, from.ch);
- var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
+ var firstEnd =
+ lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length);
if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false;
// Positions of the first endString after the end of the selection, and the last startString before it.
firstEnd = endLine.indexOf(endString, to.ch);
var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch);
- lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart;
+ lastStart = firstEnd == -1 || almostLastStart == -1 ? -1 : to.ch + almostLastStart;
if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false;
- self.operation(function() {
- self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
- Pos(end, close + endString.length));
+ self.operation(function () {
+ self.replaceRange(
+ '',
+ Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)),
+ Pos(end, close + endString.length)
+ );
var openEnd = open + startString.length;
if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length;
- self.replaceRange("", Pos(start, open), Pos(start, openEnd));
- if (lead) for (var i = start + 1; i <= end; ++i) {
- var line = self.getLine(i), found = line.indexOf(lead);
- if (found == -1 || nonWS.test(line.slice(0, found))) continue;
- var foundEnd = found + lead.length;
- if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length;
- self.replaceRange("", Pos(i, found), Pos(i, foundEnd));
- }
+ self.replaceRange('', Pos(start, open), Pos(start, openEnd));
+ if (lead)
+ for (var i = start + 1; i <= end; ++i) {
+ var line = self.getLine(i),
+ found = line.indexOf(lead);
+ if (found == -1 || nonWS.test(line.slice(0, found))) continue;
+ var foundEnd = found + lead.length;
+ if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length;
+ self.replaceRange('', Pos(i, found), Pos(i, foundEnd));
+ }
});
return true;
});
-});
\ No newline at end of file
+});
diff --git a/htdocs/js/PGCodeMirror/pgeditor.js b/htdocs/js/PGCodeMirror/pgeditor.js
index d00c18d6d5..cb3483b056 100644
--- a/htdocs/js/PGCodeMirror/pgeditor.js
+++ b/htdocs/js/PGCodeMirror/pgeditor.js
@@ -57,8 +57,8 @@
};
const loadConfig = async (file) => {
- const configName = [...file.matchAll(/.*\/([^.]*?)(?:\.min)?\.(?:js|css)(?:\?[0-9a-zA-Z=^.]*)?$/g)][0]?.[1]
- ?? 'default';
+ const configName =
+ [...file.matchAll(/.*\/([^.]*?)(?:\.min)?\.(?:js|css)(?:\?[0-9a-zA-Z=^.]*)?$/g)][0]?.[1] ?? 'default';
if (configName !== 'default') {
try {
await loadResource(file);
@@ -77,13 +77,13 @@
lineNumbers: true,
lineWrapping: true,
extraKeys: {
- Tab: (cm) => cm.execCommand('insertSoftTab'),
- 'Shift-Ctrl-F': (cm) => cm.foldCode(cm.getCursor(), { scanUp : true }),
- 'Shift-Cmd-F': (cm) => cm.foldCode(cm.getCursor(), { scanUp : true }),
+ Tab: (cm) => cm.execCommand('insertSoftTab'),
+ 'Shift-Ctrl-F': (cm) => cm.foldCode(cm.getCursor(), { scanUp: true }),
+ 'Shift-Cmd-F': (cm) => cm.foldCode(cm.getCursor(), { scanUp: true }),
'Shift-Ctrl-A': (cm) => CodeMirror.commands.foldAll(cm),
- 'Shift-Cmd-A': (cm) => CodeMirror.commands.foldAll(cm),
+ 'Shift-Cmd-A': (cm) => CodeMirror.commands.foldAll(cm),
'Shift-Ctrl-G': (cm) => CodeMirror.commands.unfoldAll(cm),
- 'Shift-Cmd-G': (cm) => CodeMirror.commands.unfoldAll(cm),
+ 'Shift-Cmd-G': (cm) => CodeMirror.commands.unfoldAll(cm)
},
highlightSelectionMatches: { annotateScrollbar: true },
matchBrackets: true,
@@ -95,14 +95,16 @@
if (mode === 'PG') {
options.extraKeys['Ctrl-/'] = (cm) => cm.execCommand('toggleComment');
options.extraKeys['Cmd-/'] = (cm) => cm.execCommand('toggleComment');
- options.foldGutter = { rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.PG) }
- options.fold = 'PG'
+ options.foldGutter = { rangeFinder: new CodeMirror.fold.combine(CodeMirror.fold.PG) };
+ options.fold = 'PG';
} else {
options.foldGutter = true;
}
- const cm = webworkConfig.pgCodeMirror
- = CodeMirror.fromTextArea(document.querySelector('.codeMirrorEditor'), options);
+ const cm = (webworkConfig.pgCodeMirror = CodeMirror.fromTextArea(
+ document.querySelector('.codeMirrorEditor'),
+ options
+ ));
cm.setSize('100%', '550px');
// Refresh the CodeMirror instance anytime the containing div resizes so that if line wrapping changes,
@@ -130,8 +132,7 @@
selectKeymap.addEventListener('change', async () => {
const keymapName = await loadConfig(selectKeymap.value);
cm.setOption('keyMap', keymapName);
- localStorage.setItem('WW_PGEditor_selected_keymap',
- keymapName === 'default' ? 'default' : selectKeymap.value);
+ localStorage.setItem('WW_PGEditor_selected_keymap', keymapName === 'default' ? 'default' : selectKeymap.value);
});
const enableSpell = document.getElementById('enableSpell');
@@ -146,5 +147,4 @@
forceRTL.addEventListener('change', () => {
cm.setOption('direction', forceRTL.checked ? 'rtl' : 'ltr');
});
-
})();
diff --git a/htdocs/js/PGProblemEditor/pgproblemeditor.js b/htdocs/js/PGProblemEditor/pgproblemeditor.js
index 144d149e59..80dd2c138f 100644
--- a/htdocs/js/PGProblemEditor/pgproblemeditor.js
+++ b/htdocs/js/PGProblemEditor/pgproblemeditor.js
@@ -14,7 +14,8 @@
toast.setAttribute('role', 'alert');
toast.setAttribute('aria-live', success ? 'polite' : 'assertive');
toast.setAttribute('aria-atomic', 'true');
- toast.innerHTML = `` +
+ toast.innerHTML =
+ `
';
@@ -22,7 +23,10 @@
toastContainer.append(toast);
const bsToast = new bootstrap.Toast(toast, { delay: success ? 2000 : 6000 });
- toast.addEventListener('hidden.bs.toast', () => { bsToast.dispose(); toast.remove(); })
+ toast.addEventListener('hidden.bs.toast', () => {
+ bsToast.dispose();
+ toast.remove();
+ });
bsToast.show();
};
@@ -39,8 +43,8 @@
request_object.rpc_command = 'saveFile';
request_object.outputFilePath = document.getElementsByName('temp_file_path')[0]?.value ?? '';
- request_object.fileContents = webworkConfig?.pgCodeMirror?.getValue()
- ?? document.getElementById('problemContents')?.value ?? '';
+ request_object.fileContents =
+ webworkConfig?.pgCodeMirror?.getValue() ?? document.getElementById('problemContents')?.value ?? '';
if (!request_object.outputFilePath) return;
@@ -89,13 +93,15 @@
const revertBackupCheck = document.getElementById('action_revert_type_backup_id');
if (revertBackupCheck) {
- document.getElementById('action_revert_backup_time_id')
- ?.addEventListener('change', () => revertBackupCheck.checked = true);
+ document
+ .getElementById('action_revert_backup_time_id')
+ ?.addEventListener('change', () => (revertBackupCheck.checked = true));
}
const deleteBackupCheck = document.getElementById('action_revert_type_delete_id');
if (deleteBackupCheck) {
- document.getElementById('action_revert_delete_number_id')
- ?.addEventListener('change', () => deleteBackupCheck.checked = true);
+ document
+ .getElementById('action_revert_delete_number_id')
+ ?.addEventListener('change', () => (deleteBackupCheck.checked = true));
}
// Send a request to the server to perltidy the current PG code in the CodeMirror editor.
@@ -107,20 +113,21 @@
};
request_object.rpc_command = 'tidyPGCode';
- request_object.pgCode = webworkConfig?.pgCodeMirror?.getValue()
- ?? document.getElementById('problemContents')?.value ?? '';
+ request_object.pgCode =
+ webworkConfig?.pgCodeMirror?.getValue() ?? document.getElementById('problemContents')?.value ?? '';
fetch(webserviceURL, { method: 'post', mode: 'same-origin', body: new URLSearchParams(request_object) })
.then((response) => response.json())
.then((data) => {
if (data.result_data.status) {
if (data.result_data.errors) {
- renderArea.innerHTML = '
' +
+ renderArea.innerHTML =
+ '
' +
'
PG perltidy errors:
' +
'
' +
data.result_data.errors
- .replace(/^[\s\S]*Begin Error Output Stream\n\n/, '')
- .replace(/\n\d*: To save a full \.LOG file rerun with -g/, '') +
+ .replace(/^[\s\S]*Begin Error Output Stream\n\n/, '')
+ .replace(/\n\d*: To save a full \.LOG file rerun with -g/, '') +
'
';
}
showMessage('Errors occurred perltidying code.', false);
@@ -177,11 +184,12 @@
}
const actionSave = document.getElementById('save');
- if (actionSave
- && actionSave.classList.contains('active')
- && document.getElementById('newWindowSave')?.checked
- && editorForm)
- {
+ if (
+ actionSave &&
+ actionSave.classList.contains('active') &&
+ document.getElementById('newWindowSave')?.checked &&
+ editorForm
+ ) {
if (document.getElementById('backupFile')?.checked) {
document.getElementById('show-backups-comment')?.classList.remove('d-none');
const deleteBackupCheck = document.getElementById('deleteBackup');
@@ -192,7 +200,6 @@
editorForm.target = 'WW_View';
}
-
const actionHardcopy = document.getElementById('hardcopy');
if (actionHardcopy && actionHardcopy.classList.contains('active')) {
e.preventDefault();
@@ -273,8 +280,10 @@
// So extract the problem form data using the FormData object and construct the URLSearchParams object
// with that.
const requestData = new URLSearchParams(new FormData(problemForm));
- requestData.set('rawProblemSource', webworkConfig?.pgCodeMirror?.getValue()
- ?? document.getElementById('problemContents')?.value ?? '');
+ requestData.set(
+ 'rawProblemSource',
+ webworkConfig?.pgCodeMirror?.getValue() ?? document.getElementById('problemContents')?.value ?? ''
+ );
requestData.set('send_pg_flags', 1);
requestData.set(button.name, button.value);
requestData.set('set_id', document.getElementsByName('hidden_set_id')[0]?.value ?? 'Unknown Set');
@@ -293,119 +302,139 @@
if (renderAreaRect.top < topBarHeight) window.scrollBy(0, renderAreaRect.top - topBarHeight);
});
- const render = () => new Promise((resolve) => {
- if (fileType === 'hardcopy_header') {
- renderArea.innerHTML = '
' +
- 'Hardcopy header contents can only be viewed in a new window.
';
- resolve();
- return;
- }
+ const render = () =>
+ new Promise((resolve) => {
+ if (fileType === 'hardcopy_header') {
+ renderArea.innerHTML =
+ '
' +
+ 'Hardcopy header contents can only be viewed in a new window.
';
+ resolve();
+ return;
+ }
- if (fileType === 'course_info') {
- const contents = webworkConfig?.pgCodeMirror?.getValue();
- if (contents) renderArea.innerHTML = `
${contents}
`;
- else
- renderArea.innerHTML = '
The file has no content.
';
+ if (fileType === 'course_info') {
+ const contents = webworkConfig?.pgCodeMirror?.getValue();
+ if (contents) renderArea.innerHTML = `
${contents}
`;
+ else
+ renderArea.innerHTML =
+ '
The file has no content.
';
+
+ // Typeset any math content that may be in the course info file.
+ if (window.MathJax) {
+ MathJax.startup.promise = MathJax.startup.promise.then(() =>
+ MathJax.typesetPromise(['#pgedit-render-area'])
+ );
+ }
- // Typeset any math content that may be in the course info file.
- if (window.MathJax) {
- MathJax.startup.promise =
- MathJax.startup.promise.then(() => MathJax.typesetPromise(['#pgedit-render-area']));
+ resolve();
+ return;
}
- resolve();
- return;
- }
+ if (fileType === 'hardcopy_theme') {
+ const contents = webworkConfig?.pgCodeMirror?.getValue();
+ if (contents) {
+ renderArea.innerHTML = '
' + contents.replace(/&/g, '&').replace(/';
+ } else
+ renderArea.innerHTML =
+ 'The file has no content.
';
- if (fileType === 'hardcopy_theme') {
- const contents = webworkConfig?.pgCodeMirror?.getValue();
- if (contents) {
- renderArea.innerHTML = '' + contents.replace(/&/g, "&").replace(/';
+ resolve();
+ return;
}
- else
- renderArea.innerHTML = 'The file has no content.
';
-
- resolve();
- return;
- }
- const isProblem = fileType && /problem/.test(fileType) ? 1 : 0;
+ const isProblem = fileType && /problem/.test(fileType) ? 1 : 0;
- renderProblem(new URLSearchParams({
- user: document.getElementById('hidden_user')?.value,
- courseID: document.getElementsByName('courseID')[0]?.value,
- key: document.getElementById('hidden_key')?.value,
- problemSeed: document.getElementById('action_view_seed_id')?.value ?? 1,
- sourceFilePath: document.getElementsByName('edit_file_path')[0]?.value,
- rawProblemSource: webworkConfig?.pgCodeMirror?.getValue()
- ?? document.getElementById('problemContents')?.value ?? '',
- outputformat: 'simple',
- showAnswerNumbers: 0,
- // The set id is really only needed by set headers to get the correct dates for the set.
- set_id: document.getElementsByName('hidden_set_id')[0]?.value ?? 'Unknown Set',
- // This should not be an actual problem number in the set. If so the current user's seed for that problem
- // will be used instead of the seed from the editor form.
- probNum: 0,
- showHints: 1,
- showSolutions: 1,
- isInstructor: 1,
- noprepostambles: 1,
- processAnswers: 0,
- showPreviewButton: isProblem,
- showCheckAnswersButton: isProblem,
- showCorrectAnswersButton: isProblem,
- showFooter: 0,
- displayMode: document.getElementById('action_view_displayMode_id')?.value ?? 'MathJax',
- language: document.querySelector('input[name="hidden_language"]')?.value ?? 'en',
- send_pg_flags: 1,
- view_problem_debugging_info: 1
- })).then(() => resolve());
- });
+ renderProblem(
+ new URLSearchParams({
+ user: document.getElementById('hidden_user')?.value,
+ courseID: document.getElementsByName('courseID')[0]?.value,
+ key: document.getElementById('hidden_key')?.value,
+ problemSeed: document.getElementById('action_view_seed_id')?.value ?? 1,
+ sourceFilePath: document.getElementsByName('edit_file_path')[0]?.value,
+ rawProblemSource:
+ webworkConfig?.pgCodeMirror?.getValue() ??
+ document.getElementById('problemContents')?.value ??
+ '',
+ outputformat: 'simple',
+ showAnswerNumbers: 0,
+ // The set id is really only needed by set headers to get the correct dates for the set.
+ set_id: document.getElementsByName('hidden_set_id')[0]?.value ?? 'Unknown Set',
+ // This should not be an actual problem number in the set. If so the current user's seed for that problem
+ // will be used instead of the seed from the editor form.
+ probNum: 0,
+ showHints: 1,
+ showSolutions: 1,
+ isInstructor: 1,
+ noprepostambles: 1,
+ processAnswers: 0,
+ showPreviewButton: isProblem,
+ showCheckAnswersButton: isProblem,
+ showCorrectAnswersButton: isProblem,
+ showFooter: 0,
+ displayMode: document.getElementById('action_view_displayMode_id')?.value ?? 'MathJax',
+ language: document.querySelector('input[name="hidden_language"]')?.value ?? 'en',
+ send_pg_flags: 1,
+ view_problem_debugging_info: 1
+ })
+ ).then(() => resolve());
+ });
// This is used to protect against rapid successive clicks on the "Randomize Seed" or "View/Reload" buttons.
let rendering = false;
- const renderProblem = (body) => new Promise((resolve) => {
- if (rendering) { resolve(); return; }
- rendering = true;
+ const renderProblem = (body) =>
+ new Promise((resolve) => {
+ if (rendering) {
+ resolve();
+ return;
+ }
+ rendering = true;
- // Put the placeholder back until the problem finishes rendering.
- renderArea.replaceChildren(placeholder);
+ // Put the placeholder back until the problem finishes rendering.
+ renderArea.replaceChildren(placeholder);
- const controller = new AbortController();
- const timeoutId = setTimeout(() => controller.abort(), 20000);
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 20000);
- fetch(renderURL, { method: 'post', mode: 'same-origin', signal: controller.signal, body })
- .then((response) => {
- clearTimeout(timeoutId);
- return response.json();
- })
- .then((data) => {
- // If the error is set, show that.
- if (data.error) throw data.error;
- // This generally shouldn't happen.
- if (!data.html) throw 'A server error occurred. The response had no content';
-
- renderArea.replaceChildren(iframe);
- iframe.srcdoc = data.html;
-
- if (data.pg_flags && data.pg_flags.comment) {
- // The problem has a comment, so show it.
- const container = document.createElement('div');
- container.classList.add('px-2', 'mb-2');
- container.innerHTML = data.pg_flags.comment;
- iframe.after(container);
- }
+ fetch(renderURL, { method: 'post', mode: 'same-origin', signal: controller.signal, body })
+ .then((response) => {
+ clearTimeout(timeoutId);
+ return response.json();
+ })
+ .then((data) => {
+ // If the error is set, show that.
+ if (data.error) throw data.error;
+ // This generally shouldn't happen.
+ if (!data.html) throw 'A server error occurred. The response had no content';
+
+ renderArea.replaceChildren(iframe);
+ iframe.srcdoc = data.html;
+
+ if (data.pg_flags && data.pg_flags.comment) {
+ // The problem has a comment, so show it.
+ const container = document.createElement('div');
+ container.classList.add('px-2', 'mb-2');
+ container.innerHTML = data.pg_flags.comment;
+ iframe.after(container);
+ }
- iframe.addEventListener('load', () => { rendering = false; resolve(); }, { once: true });
- })
- .catch((err) => {
- renderArea.innerHTML = `Rendering error: ${
- err?.message ?? err}
`;
- rendering = false;
- resolve();
- });
- });
+ iframe.addEventListener(
+ 'load',
+ () => {
+ rendering = false;
+ resolve();
+ },
+ { once: true }
+ );
+ })
+ .catch((err) => {
+ renderArea.innerHTML = `Rendering error: ${
+ err?.message ?? err
+ }
`;
+ rendering = false;
+ resolve();
+ });
+ });
// Render the content when the page loads.
render();
@@ -428,8 +457,10 @@
key: document.getElementById('hidden_key')?.value,
problemSeed: document.getElementById('action_hardcopy_seed_id')?.value ?? 1,
sourceFilePath: document.getElementsByName('edit_file_path')[0]?.value,
- rawProblemSource: webworkConfig?.pgCodeMirror?.getValue()
- ?? document.getElementById('problemContents')?.value ?? '',
+ rawProblemSource:
+ webworkConfig?.pgCodeMirror?.getValue() ??
+ document.getElementById('problemContents')?.value ??
+ '',
outputformat: document.getElementById('action_hardcopy_format_id')?.value ?? 'pdf',
hardcopy_theme: document.getElementById('action_hardcopy_theme_id')?.value ?? 'oneColumn',
// The set id is really only needed by set headers to get the correct dates for the set.
@@ -450,10 +481,11 @@
clearTimeout(timeoutId);
- if (!response.ok ||
+ if (
+ !response.ok ||
!response.headers.get('content-type') ||
- /text\/html/.test(response.headers.get('content-type')))
- {
+ /text\/html/.test(response.headers.get('content-type'))
+ ) {
throw await response.text();
return;
}
@@ -471,14 +503,16 @@
rendering = false;
} catch (err) {
if (typeof err === 'string') {
- renderArea.innerHTML = '' +
+ renderArea.innerHTML =
+ '
' +
'
Hardcopy generation errors:
' +
- err.split('\n').reduce((acc, line) => acc += `
${line}
`, '');
+ err.split('\n').reduce((acc, line) => (acc += `
${line}
`), '');
} else {
renderArea.innerHTML = `
Hardcopy generation error: ${
- err?.message ?? err}
`;
+ err?.message ?? err
+ }
`;
}
rendering = false;
- };
+ }
};
})();
diff --git a/htdocs/js/Problem/problem.js b/htdocs/js/Problem/problem.js
index e9c26b1d2e..26baf236f1 100644
--- a/htdocs/js/Problem/problem.js
+++ b/htdocs/js/Problem/problem.js
@@ -6,5 +6,7 @@
});
// Prevent problems which are disabled from acting as links
- $('.problem-list .disabled-problem').addClass('disabled').on('click', (e) => e.preventDefault());
+ $('.problem-list .disabled-problem')
+ .addClass('disabled')
+ .on('click', (e) => e.preventDefault());
})();
diff --git a/htdocs/js/ProblemGrader/problemgrader.js b/htdocs/js/ProblemGrader/problemgrader.js
index a5da03370a..e400d5f1fa 100644
--- a/htdocs/js/ProblemGrader/problemgrader.js
+++ b/htdocs/js/ProblemGrader/problemgrader.js
@@ -2,7 +2,9 @@
(() => {
const setPointInputValue = (pointInput, score) =>
- pointInput.value = (Math.round(score * pointInput.max / 100 / pointInput.step) * pointInput.step).toFixed(2);
+ (pointInput.value = (Math.round((score * pointInput.max) / 100 / pointInput.step) * pointInput.step).toFixed(
+ 2
+ ));
// Compute the problem score from any answer sub scores, and update the problem score input.
document.querySelectorAll('.answer-part-score').forEach((part) => {
@@ -37,7 +39,7 @@
const scoreInput = document.getElementById(`score_problem${problemId}`);
pointInput.classList.remove('is-invalid');
scoreInput.classList.remove('is-invalid');
- scoreInput.value = Math.round(100 * pointInput.value / pointInput.max);
+ scoreInput.value = Math.round((100 * pointInput.value) / pointInput.max);
} else {
pointInput.classList.add('is-invalid');
}
@@ -134,10 +136,10 @@
}
const recordedScore = document.getElementById('test-recorded-score');
if (recordedScore) {
- recordedScore.textContent = Math.round(100 * testValue / 2) / 100;
- document.getElementById('test-recorded-percent').textContent =
- Math.round(100 * testValue /
- (2 * document.getElementById('test-total-possible').textContent));
+ recordedScore.textContent = Math.round((100 * testValue) / 2) / 100;
+ document.getElementById('test-recorded-percent').textContent = Math.round(
+ (100 * testValue) / (2 * document.getElementById('test-total-possible').textContent)
+ );
}
}
@@ -196,7 +198,7 @@
setTimeout(() => messageArea.classList.remove('alert-danger'), 100);
}
});
- })
+ });
// Problem rendering.
diff --git a/htdocs/js/ProblemSetDetail/problemsetdetail.js b/htdocs/js/ProblemSetDetail/problemsetdetail.js
index a08097d9c9..f2f292b966 100644
--- a/htdocs/js/ProblemSetDetail/problemsetdetail.js
+++ b/htdocs/js/ProblemSetDetail/problemsetdetail.js
@@ -13,8 +13,14 @@
// Look for a list item a little above the current pointer position.
// If there is a collapsed list item there, then expand it.
const elt = document.elementFromPoint(lastX, y - 50)?.closest('.psd_list_item');
- if (elt && Sortable.dragged && Sortable.dragged !== elt && elt.subList && elt.collapseButton
- && lastX > elt.collapseButton.getBoundingClientRect().left)
+ if (
+ elt &&
+ Sortable.dragged &&
+ Sortable.dragged !== elt &&
+ elt.subList &&
+ elt.collapseButton &&
+ lastX > elt.collapseButton.getBoundingClientRect().left
+ )
bootstrap.Collapse.getInstance(elt.subList).show();
};
@@ -28,17 +34,16 @@
document.getElementById(item.id.replace('psd_list_item_', 'prob_parent_id_')).value = parentId ?? '';
// Update the displayed problem number for this problem and all children.
- item.querySelectorAll('.psd_list_item .pdr_problem_number')
- .forEach((itemNumber) => {
- itemNumber.textContent = itemNumber.textContent ? `${itemNumber.textContent}.${i + 1}`: (i + 1);
- });
+ item.querySelectorAll('.psd_list_item .pdr_problem_number').forEach((itemNumber) => {
+ itemNumber.textContent = itemNumber.textContent ? `${itemNumber.textContent}.${i + 1}` : i + 1;
+ });
if (item.subList)
recursiveRenumber(Sortable.get(item.subList).toArray(), item.id.replace('psd_list_item_', ''));
}
- }
+ };
const setProblemNumberFields = () => {
- container.querySelectorAll('.psd_list_item .pdr_problem_number').forEach((num) => num.textContent = '');
+ container.querySelectorAll('.psd_list_item .pdr_problem_number').forEach((num) => (num.textContent = ''));
recursiveRenumber(Sortable.get(container).toArray());
};
@@ -46,7 +51,7 @@
// Set up the bootstrap collapses. Note that if a list is empty, then the collapse is shown. Since it is empty
// you still see nothing, but dragging into the list is smoother because it doesn't need to be expanded first.
if (list.classList.contains('collapse'))
- list.collapse = new bootstrap.Collapse(list, { toggle: !list.querySelector('.psd_list_item') })
+ list.collapse = new bootstrap.Collapse(list, { toggle: !list.querySelector('.psd_list_item') });
if (list.id === container.id) list.nestDepth = 0;
else list.nestDepth = list.parentNode.closest('.sortable-branch').nestDepth + 1;
@@ -56,7 +61,8 @@
new Sortable(list, {
group: {
name: 'psd_list',
- put: (to, from) => from.el.nestDepth > to.el.nestDepth ||
+ put: (to, from) =>
+ from.el.nestDepth > to.el.nestDepth ||
lastX > to.el.parentNode.querySelector('.pdr_handle').getBoundingClientRect().right
},
handle: '.pdr_handle',
@@ -69,16 +75,21 @@
forceFallback: true,
onStart(evt) {
// Disable tooltips during a drag.
- container.querySelectorAll('[data-bs-toggle]').forEach(
- (tooltip) => bootstrap.Tooltip.getInstance(tooltip)?.disable()
- );
+ container
+ .querySelectorAll('[data-bs-toggle]')
+ .forEach((tooltip) => bootstrap.Tooltip.getInstance(tooltip)?.disable());
// If the dragged item has a non-empty child list, then collapse it while dragging.
- if (evt.item.subList && evt.item.subList.classList.contains('show')
- && evt.item.subList.querySelector('.psd_list_item')) {
+ if (
+ evt.item.subList &&
+ evt.item.subList.classList.contains('show') &&
+ evt.item.subList.querySelector('.psd_list_item')
+ ) {
hiddenCollapse = bootstrap.Collapse.getInstance(evt.item.subList);
hiddenCollapse.hide();
- evt.item.subList.addEventListener('shown.bs.collapse', () => hiddenCollapse = null, { once: true });
+ evt.item.subList.addEventListener('shown.bs.collapse', () => (hiddenCollapse = null), {
+ once: true
+ });
}
container.addEventListener('pointermove', pointerMove, { passive: true });
@@ -88,14 +99,15 @@
// Expand the dragged item if it was collapsed at the start.
if (hiddenCollapse?._isTransitioning)
- hiddenCollapse._element.addEventListener('hidden.bs.collapse',
- () => hiddenCollapse?.show(), { once: true });
+ hiddenCollapse._element.addEventListener('hidden.bs.collapse', () => hiddenCollapse?.show(), {
+ once: true
+ });
else hiddenCollapse?.show();
// Re-enable tooltips at the end of a drag.
- container.querySelectorAll('[data-bs-toggle]').forEach(
- (tooltip) => bootstrap.Tooltip.getInstance(tooltip)?.enable()
- );
+ container
+ .querySelectorAll('[data-bs-toggle]')
+ .forEach((tooltip) => bootstrap.Tooltip.getInstance(tooltip)?.enable());
},
onSort() {
setProblemNumberFields();
@@ -103,8 +115,9 @@
},
onRemove() {
if (hiddenCollapse?._isTransitioning)
- hiddenCollapse._element.addEventListener('hidden.bs.collapse',
- () => hiddenCollapse?.show(), { once: true });
+ hiddenCollapse._element.addEventListener('hidden.bs.collapse', () => hiddenCollapse?.show(), {
+ once: true
+ });
else hiddenCollapse?.show();
},
onChange(evt) {
@@ -124,8 +137,10 @@
// Set up the buttons that expand/contract JITAR nesting.
elt.collapseButton = elt.querySelector('.problem_detail_row').querySelector('.pdr_collapse');
if (elt.collapseButton) {
- elt.collapseButton.tooltip = new bootstrap.Tooltip(elt.collapseButton.firstElementChild,
- { title: elt.collapseButton.dataset.expandText, container: elt.collapseButton });
+ elt.collapseButton.tooltip = new bootstrap.Tooltip(elt.collapseButton.firstElementChild, {
+ title: elt.collapseButton.dataset.expandText,
+ container: elt.collapseButton
+ });
elt.collapseButton.dataset.bsTarget = `#${elt.subList.id}`;
@@ -133,8 +148,8 @@
if (!hasChildren) {
elt.collapseButton.setAttribute('aria-expanded', true);
elt.collapseButton.classList.remove('collapsed');
- elt.collapseButton.classList.add('d-none')
- };
+ elt.collapseButton.classList.add('d-none');
+ }
elt.collapseButton.setAttribute('aria-controls', elt.subList.id);
@@ -148,14 +163,18 @@
elt.subList.addEventListener('hide.bs.collapse', () => {
elt.collapseButton.setAttribute('aria-label', elt.collapseButton.dataset.expandText);
elt.collapseButton.tooltip.dispose();
- elt.collapseButton.tooltip = new bootstrap.Tooltip(elt.collapseButton.firstElementChild,
- { title: elt.collapseButton.dataset.expandText, container: elt.collapseButton });
+ elt.collapseButton.tooltip = new bootstrap.Tooltip(elt.collapseButton.firstElementChild, {
+ title: elt.collapseButton.dataset.expandText,
+ container: elt.collapseButton
+ });
});
elt.subList.addEventListener('show.bs.collapse', () => {
elt.collapseButton.setAttribute('aria-label', elt.collapseButton.dataset.collapseText);
elt.collapseButton.tooltip.dispose();
- elt.collapseButton.tooltip = new bootstrap.Tooltip(elt.collapseButton.firstElementChild,
- { title: elt.collapseButton.dataset.collapseText, container: elt.collapseButton });
+ elt.collapseButton.tooltip = new bootstrap.Tooltip(elt.collapseButton.firstElementChild, {
+ title: elt.collapseButton.dataset.collapseText,
+ container: elt.collapseButton
+ });
if (Sortable.dragged) elt.collapseButton.tooltip.disable();
});
}
@@ -191,15 +210,14 @@
};
// Initialize tooltips.
- document.querySelectorAll('.psd_view,.psd_edit,.pdr_render,.pdr_grader,.pdr_handle > i').forEach(
- (el) => new bootstrap.Tooltip(el)
- );
+ document
+ .querySelectorAll('.psd_view,.psd_edit,.pdr_render,.pdr_grader,.pdr_handle > i')
+ .forEach((el) => new bootstrap.Tooltip(el));
// If editing for user(s), then disable drag and drop re-ordering of problems.
if (document.getElementById('psd_list')?.classList.contains('disable_renumber')) {
Sortable.get(container)?.option('disabled', true);
- container.querySelectorAll('.sortable-branch').forEach((list) =>
- Sortable.get(list)?.option('disabled', true));
+ container.querySelectorAll('.sortable-branch').forEach((list) => Sortable.get(list)?.option('disabled', true));
}
// Set up the tooltips for the buttons that expand/contract details.
@@ -217,65 +235,88 @@
tooltip.dispose();
options.title = button.dataset.expandText;
tooltip = new bootstrap.Tooltip(button, options);
- })
+ });
detailCollapse?.addEventListener('show.bs.collapse', () => {
tooltip.dispose();
button.setAttribute('aria-label', button.dataset.collapseText);
options.title = button.dataset.collapseText;
tooltip = new bootstrap.Tooltip(button, options);
- })
+ });
});
// Set up the button to hide all rendered problems.
- document.getElementById('psd_hide_all')?.addEventListener('click', () => {
- document.querySelectorAll('.rpc_render_area').forEach((renderArea) => {
- const iframe = renderArea.querySelector('[id^="psr_render_area_"][id$="_iframe"]');
- if (iframe && iframe.iFrameResizer) iframe.iFrameResizer.close();
- });
- }, { passive: true });
+ document.getElementById('psd_hide_all')?.addEventListener(
+ 'click',
+ () => {
+ document.querySelectorAll('.rpc_render_area').forEach((renderArea) => {
+ const iframe = renderArea.querySelector('[id^="psr_render_area_"][id$="_iframe"]');
+ if (iframe && iframe.iFrameResizer) iframe.iFrameResizer.close();
+ });
+ },
+ { passive: true }
+ );
// Initialize the problem details collapses.
const collapsibles = Array.from(document.querySelectorAll('.psd_list_item')).reduce((accum, row) => {
const problemID = row.id.match(/^psd_list_item_(\d+)/)[1];
- accum[problemID] =
- new bootstrap.Collapse(document.getElementById(`pdr_details_${problemID}`), { toggle: false });
+ accum[problemID] = new bootstrap.Collapse(document.getElementById(`pdr_details_${problemID}`), {
+ toggle: false
+ });
return accum;
}, {});
// Set up the details expand/collapse all buttons.
- document.getElementById('psd_expand_details')?.addEventListener('click', () => {
- Object.keys(collapsibles).forEach((row) => collapsibles[row].show());
- }, { passive: true });
+ document.getElementById('psd_expand_details')?.addEventListener(
+ 'click',
+ () => {
+ Object.keys(collapsibles).forEach((row) => collapsibles[row].show());
+ },
+ { passive: true }
+ );
- document.getElementById('psd_collapse_details')?.addEventListener('click', () => {
- Object.keys(collapsibles).forEach((row) => collapsibles[row].hide());
- }, { passive: true });
+ document.getElementById('psd_collapse_details')?.addEventListener(
+ 'click',
+ () => {
+ Object.keys(collapsibles).forEach((row) => collapsibles[row].hide());
+ },
+ { passive: true }
+ );
// Set up the JITAR tree expand/collapse all buttons.
- document.getElementById('psd_expand_all')?.addEventListener('click', () => {
- document.querySelectorAll('.sortable-branch').forEach((branch) => {
- bootstrap.Collapse.getInstance(branch)?.show();
- });
- }, { passive: true });
+ document.getElementById('psd_expand_all')?.addEventListener(
+ 'click',
+ () => {
+ document.querySelectorAll('.sortable-branch').forEach((branch) => {
+ bootstrap.Collapse.getInstance(branch)?.show();
+ });
+ },
+ { passive: true }
+ );
- document.getElementById('psd_collapse_all')?.addEventListener('click', () => {
- document.querySelectorAll('.sortable-branch').forEach((branch) => {
- bootstrap.Collapse.getInstance(branch)?.hide();
- });
- }, { passive: true });
+ document.getElementById('psd_collapse_all')?.addEventListener(
+ 'click',
+ () => {
+ document.querySelectorAll('.sortable-branch').forEach((branch) => {
+ bootstrap.Collapse.getInstance(branch)?.hide();
+ });
+ },
+ { passive: true }
+ );
// This enables and disables problem fields that don't make sense based on the position of the problem.
const disableFields = (tree) => {
- for (const item of (tree ?? toTree())) {
- const countsForParentRow =
- document.getElementById(`problem.${item.id}.counts_parent_grade_id`)?.closest('tr');
+ for (const item of tree ?? toTree()) {
+ const countsForParentRow = document
+ .getElementById(`problem.${item.id}.counts_parent_grade_id`)
+ ?.closest('tr');
if (countsForParentRow) {
if (item.parent) countsForParentRow.classList.remove('d-none');
else countsForParentRow.classList.add('d-none');
}
- const attToOpenChildrenRow =
- document.getElementById(`problem.${item.id}.att_to_open_children_id`)?.closest('tr');
+ const attToOpenChildrenRow = document
+ .getElementById(`problem.${item.id}.att_to_open_children_id`)
+ ?.closest('tr');
if (attToOpenChildrenRow) {
if (item.children?.length) {
attToOpenChildrenRow.classList.remove('d-none');
@@ -283,70 +324,82 @@
} else attToOpenChildrenRow.classList.add('d-none');
}
}
- }
+ };
// Run disableFields on page load.
if (container) disableFields();
// Setup the renumber problems button.
- document.getElementById('psd_renumber')?.addEventListener('click', () => {
- setProblemNumberFields();
- }, { passive: true });
+ document.getElementById('psd_renumber')?.addEventListener(
+ 'click',
+ () => {
+ setProblemNumberFields();
+ },
+ { passive: true }
+ );
// Send a request to the webwork webservice and render a problem.
- const render = (id) => new Promise((resolve) => {
- const renderArea = document.getElementById(`psr_render_area_${id}`);
+ const render = (id) =>
+ new Promise((resolve) => {
+ const renderArea = document.getElementById(`psr_render_area_${id}`);
- const ro = {
- problemSeed: document.getElementById(`problem.${id}.problem_seed_id`)?.value ?? 1,
- sourceFilePath: document.getElementById(`problem.${id}.source_file_id`)?.value ||
- document.getElementById(`problem_${id}_default_source_file`)?.value,
- };
+ const ro = {
+ problemSeed: document.getElementById(`problem.${id}.problem_seed_id`)?.value ?? 1,
+ sourceFilePath:
+ document.getElementById(`problem.${id}.source_file_id`)?.value ||
+ document.getElementById(`problem_${id}_default_source_file`)?.value
+ };
- if (ro.sourceFilePath.startsWith('group')) {
- renderArea.innerHTML = '
'
- + 'Problem source is drawn from a grouping set.
';
- resolve();
- return;
- }
+ if (ro.sourceFilePath.startsWith('group')) {
+ renderArea.innerHTML =
+ '
' +
+ 'Problem source is drawn from a grouping set.
';
+ resolve();
+ return;
+ }
- const editForUserInputs = document.querySelector('input[name=editForUser]');
- if (editForUserInputs) ro.effectiveUser = editForUserInputs.value;
+ const editForUserInputs = document.querySelector('input[name=editForUser]');
+ if (editForUserInputs) ro.effectiveUser = editForUserInputs.value;
- const versionIDInput = document.getElementById('hidden_version_id');
- if (versionIDInput) ro.version_id = versionIDInput.value;
+ const versionIDInput = document.getElementById('hidden_version_id');
+ if (versionIDInput) ro.version_id = versionIDInput.value;
- ro.set_id = document.getElementById('hidden_set_id')?.value ?? 'Unknown Set';
- ro.probNum = id;
- ro.language = document.querySelector('input[name="hidden_language"]')?.value ?? 'en';
+ ro.set_id = document.getElementById('hidden_set_id')?.value ?? 'Unknown Set';
+ ro.probNum = id;
+ ro.language = document.querySelector('input[name="hidden_language"]')?.value ?? 'en';
- webworkConfig.renderProblem(renderArea, ro).then(resolve);
- });
+ webworkConfig.renderProblem(renderArea, ro).then(resolve);
+ });
// Set up the problem render buttons.
document.querySelectorAll('.pdr_render').forEach((renderButton) => {
- renderButton.addEventListener('click', () => {
- const id = renderButton.id.match(/^pdr_render_(\d+)/)[1];
- const renderArea = document.getElementById(`psr_render_area_${id}`);
- const iframe = document.getElementById(`psr_render_area_${id}_iframe`);
- if (iframe && iframe.iFrameResizer) {
- iframe.iFrameResizer.close();
- renderArea.innerHTML = '';
- } else if (/\S/.test(renderArea.innerHTML)) {
- renderArea.innerHTML = '';
- } else {
- collapsibles[id]?.show();
- renderArea.innerHTML = '
Loading Please Wait...
';
- render(id);
- }
- }, { passive: true });
+ renderButton.addEventListener(
+ 'click',
+ () => {
+ const id = renderButton.id.match(/^pdr_render_(\d+)/)[1];
+ const renderArea = document.getElementById(`psr_render_area_${id}`);
+ const iframe = document.getElementById(`psr_render_area_${id}_iframe`);
+ if (iframe && iframe.iFrameResizer) {
+ iframe.iFrameResizer.close();
+ renderArea.innerHTML = '';
+ } else if (/\S/.test(renderArea.innerHTML)) {
+ renderArea.innerHTML = '';
+ } else {
+ collapsibles[id]?.show();
+ renderArea.innerHTML = '
Loading Please Wait...
';
+ render(id);
+ }
+ },
+ { passive: true }
+ );
});
// Render all problems.
const renderAll = async () => {
Object.keys(collapsibles).forEach((row) => collapsibles[row].show());
- document.querySelectorAll('.sortable-branch.collapse').forEach(
- (branch) => bootstrap.Collapse.getInstance(branch)?.show());
+ document
+ .querySelectorAll('.sortable-branch.collapse')
+ .forEach((branch) => bootstrap.Collapse.getInstance(branch)?.show());
const renderAreas = document.querySelectorAll('.rpc_render_area');
for (const renderArea of renderAreas) {
renderArea.innerHTML = '
Loading Please Wait...
';
@@ -357,39 +410,46 @@
};
// Set up the render all button.
- document.getElementById('psd_render_all')?.addEventListener('click', () => {
- renderAll();
- }, { passive: true });
+ document.getElementById('psd_render_all')?.addEventListener(
+ 'click',
+ () => {
+ renderAll();
+ },
+ { passive: true }
+ );
// Render all problems on page load if requested.
if (document.getElementById('auto_render')?.checked) renderAll();
// Make the override checkboxes for text type inputs checked or unchecked appropriately
// as determined by the value of the input when that value changes.
- document.querySelectorAll('input[type="text"][data-override],input[type="hidden"][data-override]')
- .forEach((input) =>
- {
- const overrideCheck = document.getElementById(input.dataset.override);
- if (!overrideCheck) return;
- const changeHandler = () => overrideCheck.checked = input.value != '';
- input.addEventListener('change', changeHandler);
- if (input.parentElement.classList.contains('flatpickr')) {
- // Attach the keyup and blur handlers to the flatpickr alternate input.
- input.previousElementSibling?.addEventListener('keyup', changeHandler);
- input.previousElementSibling?.addEventListener('blur',
- () => { if (input.previousElementSibling.value == '') overrideCheck.checked = false; });
- } else {
- input.addEventListener('keyup', changeHandler);
- input.addEventListener('blur', () => { if (input.value == '') overrideCheck.checked = false; });
- }
- });
+ document
+ .querySelectorAll('input[type="text"][data-override],input[type="hidden"][data-override]')
+ .forEach((input) => {
+ const overrideCheck = document.getElementById(input.dataset.override);
+ if (!overrideCheck) return;
+ const changeHandler = () => (overrideCheck.checked = input.value != '');
+ input.addEventListener('change', changeHandler);
+ if (input.parentElement.classList.contains('flatpickr')) {
+ // Attach the keyup and blur handlers to the flatpickr alternate input.
+ input.previousElementSibling?.addEventListener('keyup', changeHandler);
+ input.previousElementSibling?.addEventListener('blur', () => {
+ if (input.previousElementSibling.value == '') overrideCheck.checked = false;
+ });
+ } else {
+ input.addEventListener('keyup', changeHandler);
+ input.addEventListener('blur', () => {
+ if (input.value == '') overrideCheck.checked = false;
+ });
+ }
+ });
// Make the override checkboxes for selects checked or unchecked appropriately
// as determined by the value of the select when that value changes.
document.querySelectorAll('select[data-override]').forEach((select) => {
const overrideCheck = document.getElementById(select.dataset.override);
if (!overrideCheck) return;
- select.addEventListener('change', () => overrideCheck.checked = select.value != '');
+ select.addEventListener('change', () => (overrideCheck.checked = select.value != ''));
});
// This changes the set header textbox text to the currently selected option in the select menu.
@@ -402,37 +462,40 @@
// Try to select best option in select menu as user types in the textbox.
comboBoxText.addEventListener('keyup', () => {
let i = 0;
- for (;
+ for (
+ ;
i < comboBoxSelect.options.length && comboBoxSelect.options[i].value.indexOf(comboBoxText.value) != 0;
- ++i) {}
+ ++i
+ ) {}
comboBoxSelect.selectedIndex = i;
});
// Set the textbox text to be same as that of select menu
- comboBoxSelect.addEventListener('change',
- () => comboBoxText.value = comboBoxSelect.options[comboBoxSelect.selectedIndex].value);
+ comboBoxSelect.addEventListener(
+ 'change',
+ () => (comboBoxText.value = comboBoxSelect.options[comboBoxSelect.selectedIndex].value)
+ );
});
// Set up seed randomization buttons.
const randomize_seeds_button = document.getElementById('randomize_seeds');
const randomize_seed_buttons = document.querySelectorAll('.randomize-seed-btn');
if (randomize_seeds_button) {
- randomize_seeds_button.addEventListener('click',
- () => (randomize_seed_buttons.forEach((btn) => {
+ randomize_seeds_button.addEventListener('click', () =>
+ randomize_seed_buttons.forEach((btn) => {
const exclude_correct = document.getElementById('excludeCorrect').checked;
const input = document.getElementById(btn.dataset.seedInput);
- const stat = document.getElementById(btn.dataset.statusInput).value || 0;
+ const stat = document.getElementById(btn.dataset.statusInput).value || 0;
if (input) {
if (!exclude_correct || (exclude_correct && stat < 1)) {
input.value = Math.floor(Math.random() * 10000);
}
}
- }))
- )
+ })
+ );
}
for (const btn of randomize_seed_buttons) {
const input = document.getElementById(btn.dataset.seedInput);
if (input) btn.addEventListener('click', () => (input.value = Math.floor(Math.random() * 10000)));
}
-
})();
diff --git a/htdocs/js/ProblemSetList/problemsetlist.js b/htdocs/js/ProblemSetList/problemsetlist.js
index 2053823014..20710f7c93 100644
--- a/htdocs/js/ProblemSetList/problemsetlist.js
+++ b/htdocs/js/ProblemSetList/problemsetlist.js
@@ -1,20 +1,20 @@
(() => {
// Show the filter error message if the 'Filter' button is clicked when matching set IDs without having entered
// a text to filter on.
- document.getElementById('take_action')?.addEventListener('click',
- (e) => {
- const filter_err_msg = document.getElementById('filter_err_msg');
+ document.getElementById('take_action')?.addEventListener('click', (e) => {
+ const filter_err_msg = document.getElementById('filter_err_msg');
- if (filter_err_msg &&
- document.getElementById('current_action')?.value === 'filter' &&
- document.getElementById('filter_select')?.selectedIndex === 3 &&
- document.getElementById('filter_text')?.value === '') {
- filter_err_msg.classList.remove('d-none');
- e.preventDefault();
- e.stopPropagation();
- }
+ if (
+ filter_err_msg &&
+ document.getElementById('current_action')?.value === 'filter' &&
+ document.getElementById('filter_select')?.selectedIndex === 3 &&
+ document.getElementById('filter_text')?.value === ''
+ ) {
+ filter_err_msg.classList.remove('d-none');
+ e.preventDefault();
+ e.stopPropagation();
}
- );
+ });
// Toggle the display of the filter elements as the filter select changes.
const filter_select = document.getElementById('filter_select');
@@ -65,17 +65,16 @@
// Initialize the date/time picker for the import form.
const importDateShift = document.getElementById('import_date_shift');
if (importDateShift) {
-
luxon.Settings.defaultLocale = importDateShift.dataset.locale ?? 'en';
// Compute the time difference between the current browser timezone and the course timezone.
// flatpickr gives the time in the browser's timezone, and this is used to adjust to the course timezone.
// Note that this is in seconds.
- const timezoneAdjustment = (
- (new Date((new Date).toLocaleString('en-US'))).getTime() -
- (new Date((new Date).toLocaleString('en-US',
- { timeZone: importDateShift.dataset.timezone ?? 'America/New_York' }))).getTime()
- );
+ const timezoneAdjustment =
+ new Date(new Date().toLocaleString('en-US')).getTime() -
+ new Date(
+ new Date().toLocaleString('en-US', { timeZone: importDateShift.dataset.timezone ?? 'America/New_York' })
+ ).getTime();
const fp = flatpickr(importDateShift.parentNode, {
allowInput: true,
diff --git a/htdocs/js/RenderProblem/renderproblem.js b/htdocs/js/RenderProblem/renderproblem.js
index 3041912cf1..ad61bdd8f1 100644
--- a/htdocs/js/RenderProblem/renderproblem.js
+++ b/htdocs/js/RenderProblem/renderproblem.js
@@ -1,84 +1,88 @@
(() => {
// renderElement may either be the id of an html element, or directly an html element.
// If it is an html element, then that element must have an id.
- webworkConfig.renderProblem = (renderElement, renderOptions) => new Promise((resolve) => {
- const renderArea = renderElement instanceof Element ? renderElement : document.getElementById(renderElement);
- if (!renderArea || !renderArea.id) return resolve();
+ webworkConfig.renderProblem = (renderElement, renderOptions) =>
+ new Promise((resolve) => {
+ const renderArea =
+ renderElement instanceof Element ? renderElement : document.getElementById(renderElement);
+ if (!renderArea || !renderArea.id) return resolve();
- let iframe = renderArea.querySelector(`#${renderArea.id}_iframe`);
- if (iframe && iframe.iFrameResizer) iframe.contentDocument.location.replace('about:blank');
+ let iframe = renderArea.querySelector(`#${renderArea.id}_iframe`);
+ if (iframe && iframe.iFrameResizer) iframe.contentDocument.location.replace('about:blank');
- const ro = {
- user: document.getElementById('hidden_user')?.value,
- key: document.getElementById('hidden_key')?.value,
- courseID: document.getElementsByName('hidden_course_id')[0]?.value,
- language: document.getElementsByName('hidden_language')[0]?.value ?? 'en',
- displayMode: document.getElementById('problem_displaymode').value ?? 'MathJax',
- problemSeed: 1,
- permissionLevel: 10,
- outputformat: 'simple',
- showAnswerNumbers: 0,
- showHints: 1,
- showSolutions: 1,
- isInstructor: 1,
- forceScaffoldsOpen: 1,
- noprepostambles: 1,
- processAnswers: 0,
- showFooter: 0,
- send_pg_flags: 1,
- extra_header_text:
- '',
- ...renderOptions
- };
+ const ro = {
+ user: document.getElementById('hidden_user')?.value,
+ key: document.getElementById('hidden_key')?.value,
+ courseID: document.getElementsByName('hidden_course_id')[0]?.value,
+ language: document.getElementsByName('hidden_language')[0]?.value ?? 'en',
+ displayMode: document.getElementById('problem_displaymode').value ?? 'MathJax',
+ problemSeed: 1,
+ permissionLevel: 10,
+ outputformat: 'simple',
+ showAnswerNumbers: 0,
+ showHints: 1,
+ showSolutions: 1,
+ isInstructor: 1,
+ forceScaffoldsOpen: 1,
+ noprepostambles: 1,
+ processAnswers: 0,
+ showFooter: 0,
+ send_pg_flags: 1,
+ extra_header_text:
+ '',
+ ...renderOptions
+ };
- const controller = new AbortController();
- const timeoutId = setTimeout(() => controller.abort(), 10000);
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 10000);
- fetch(`${webworkConfig?.webwork_url ?? '/webwork2'}/render_rpc`, {
- method: 'post',
- mode: 'same-origin',
- body: new URLSearchParams(ro),
- signal: controller.signal
- })
- .then((response) => {
- clearTimeout(timeoutId);
- return response.json();
+ fetch(`${webworkConfig?.webwork_url ?? '/webwork2'}/render_rpc`, {
+ method: 'post',
+ mode: 'same-origin',
+ body: new URLSearchParams(ro),
+ signal: controller.signal
})
- .then((data) => {
- // If the error is set, show that.
- if (data.error) throw data.error;
- // This shouldn't happen if the error is not set.
- if (!data.html) throw 'A server error occurred. The response had no content.';
- if (/this problem file was empty/i.test(data.html)) throw 'No such file or file was empty!';
- // Give nicer problem rendering error
- if (
- (data.pg_flags && data.pg_flags.error_flag) ||
- /error caught by translator while processing problem/i.test(data.html)
- )
- throw 'There was an error rendering this problem!';
+ .then((response) => {
+ clearTimeout(timeoutId);
+ return response.json();
+ })
+ .then((data) => {
+ // If the error is set, show that.
+ if (data.error) throw data.error;
+ // This shouldn't happen if the error is not set.
+ if (!data.html) throw 'A server error occurred. The response had no content.';
+ if (/this problem file was empty/i.test(data.html)) throw 'No such file or file was empty!';
+ // Give nicer problem rendering error
+ if (
+ (data.pg_flags && data.pg_flags.error_flag) ||
+ /error caught by translator while processing problem/i.test(data.html)
+ )
+ throw 'There was an error rendering this problem!';
- if (!(iframe && iframe.iFrameResizer)) {
- iframe = document.createElement('iframe');
- iframe.id = `${renderArea.id}_iframe`;
- iframe.style.border = 'none';
- while (renderArea.firstChild) renderArea.firstChild.remove();
- renderArea.append(iframe);
+ if (!(iframe && iframe.iFrameResizer)) {
+ iframe = document.createElement('iframe');
+ iframe.id = `${renderArea.id}_iframe`;
+ iframe.style.border = 'none';
+ while (renderArea.firstChild) renderArea.firstChild.remove();
+ renderArea.append(iframe);
- if (data.pg_flags && data.pg_flags.comment) {
- const container = document.createElement('div');
- container.innerHTML = data.pg_flags.comment;
- iframe.after(container);
+ if (data.pg_flags && data.pg_flags.comment) {
+ const container = document.createElement('div');
+ container.innerHTML = data.pg_flags.comment;
+ iframe.after(container);
+ }
+ iFrameResize({ checkOrigin: false, warningTimeout: 20000, scrolling: 'omit' }, iframe);
+ iframe.addEventListener('load', () => resolve());
}
- iFrameResize({ checkOrigin: false, warningTimeout: 20000, scrolling: 'omit' }, iframe);
- iframe.addEventListener('load', () => resolve());
- }
- iframe.srcdoc = data.html;
- })
- .catch((err) => {
- renderArea.innerHTML = `
${err?.message ?? err}
`;
- resolve();
- });
- });
+ iframe.srcdoc = data.html;
+ })
+ .catch((err) => {
+ renderArea.innerHTML = `
${
+ err?.message ?? err
+ }
`;
+ resolve();
+ });
+ });
})();
diff --git a/htdocs/js/SampleProblemViewer/viewer.js b/htdocs/js/SampleProblemViewer/viewer.js
index b86bf06cf8..33fecfaa98 100644
--- a/htdocs/js/SampleProblemViewer/viewer.js
+++ b/htdocs/js/SampleProblemViewer/viewer.js
@@ -1,4 +1,4 @@
const offcanvas = bootstrap.Offcanvas.getOrCreateInstance(document.getElementById('sidebar'));
for (const link of document.querySelectorAll('#sidebar-list .list-group-item-action')) {
- link.addEventListener('click', () => offcanvas.hide());
-}
\ No newline at end of file
+ link.addEventListener('click', () => offcanvas.hide());
+}
diff --git a/htdocs/js/SelectAll/selectall.js b/htdocs/js/SelectAll/selectall.js
index ad46584cf5..b300842b97 100644
--- a/htdocs/js/SelectAll/selectall.js
+++ b/htdocs/js/SelectAll/selectall.js
@@ -7,18 +7,22 @@
if (selectAll.type.toLowerCase() === 'checkbox') {
// Find additional select alls in the same group if any.
- const pairedSelectAlls =
- document.querySelectorAll(`.select-all[data-select-group="${selectAll.dataset.selectGroup}"]`);
+ const pairedSelectAlls = document.querySelectorAll(
+ `.select-all[data-select-group="${selectAll.dataset.selectGroup}"]`
+ );
selectAll.addEventListener('click', () => {
- checks.forEach(check => check.checked = selectAll.checked);
+ checks.forEach((check) => (check.checked = selectAll.checked));
// Also check/uncheck any select alls in the same group.
- pairedSelectAlls.forEach((check) => check.checked = selectAll.checked);
+ pairedSelectAlls.forEach((check) => (check.checked = selectAll.checked));
});
- checks.forEach(check => check.addEventListener('click',
- () => { if (!check.checked) selectAll.checked = false; }));
+ checks.forEach((check) =>
+ check.addEventListener('click', () => {
+ if (!check.checked) selectAll.checked = false;
+ })
+ );
// If all checks in the group are checked when the page loads, then also check the select all check.
// This can happen in AchievementList.pm.
@@ -26,12 +30,12 @@
}
if (selectAll.type.toLowerCase() === 'button') {
- selectAll.addEventListener('click', () => checks.forEach(check => check.checked = true));
+ selectAll.addEventListener('click', () => checks.forEach((check) => (check.checked = true)));
}
}
for (const selectNone of document.querySelectorAll('.select-none')) {
const checks = document.querySelectorAll(`input[name$=${selectNone.dataset.selectGroup}]`);
- selectNone.addEventListener('click', () => checks.forEach(check => check.checked = false));
+ selectNone.addEventListener('click', () => checks.forEach((check) => (check.checked = false)));
}
})();
diff --git a/htdocs/js/SetMaker/setmaker.js b/htdocs/js/SetMaker/setmaker.js
index e226bd6654..afb1ea610c 100644
--- a/htdocs/js/SetMaker/setmaker.js
+++ b/htdocs/js/SetMaker/setmaker.js
@@ -3,7 +3,7 @@
const basicWebserviceURL = `${webworkURL}/instructor_rpc`;
let unloading = false;
- window.addEventListener('beforeunload', () => unloading = true);
+ window.addEventListener('beforeunload', () => (unloading = true));
// Informational alerts/errors
const alertToast = (title, msg, good = false) => {
@@ -11,7 +11,13 @@
const toastContainer = document.createElement('div');
toastContainer.classList.add(
- 'toast-container', 'position-fixed', 'top-50', 'start-50', 'translate-middle', 'p-3');
+ 'toast-container',
+ 'position-fixed',
+ 'top-50',
+ 'start-50',
+ 'translate-middle',
+ 'p-3'
+ );
toastContainer.style.zIndex = 20;
toastContainer.innerHTML =
'
' +
@@ -23,7 +29,10 @@
'
';
document.body.prepend(toastContainer);
const bsToast = new bootstrap.Toast(toastContainer.firstElementChild);
- toastContainer.addEventListener('hidden.bs.toast', () => { bsToast.dispose(); toastContainer.remove(); })
+ toastContainer.addEventListener('hidden.bs.toast', () => {
+ bsToast.dispose();
+ toastContainer.remove();
+ });
bsToast.show();
};
@@ -73,8 +82,11 @@
requestObject.library_textbook = libraryTextbook?.value ?? '';
requestObject.library_textchapter = libraryChapter?.value ?? '';
requestObject.library_textsection = librarySection?.value ?? '';
- requestObject.includeOPL = (includeOPL.type === 'checkbox' && includeOPL?.checked) ||
- (includeOPL.type === 'hidden' && includeOPL.value) ? 1 : 0;
+ requestObject.includeOPL =
+ (includeOPL.type === 'checkbox' && includeOPL?.checked) ||
+ (includeOPL.type === 'hidden' && includeOPL.value)
+ ? 1
+ : 0;
requestObject.includeContrib = includeContrib?.checked ? 1 : 0;
if (who == 'count') {
@@ -104,9 +116,10 @@
throw data.error;
} else {
const num = data.result_data[0];
- countLine.firstElementChild.innerHTML = num === '1'
- ? 'There is 1 matching WeBWorK problem'
- : `There are ${num} matching WeBWorK problems.`;
+ countLine.firstElementChild.innerHTML =
+ num === '1'
+ ? 'There is 1 matching WeBWorK problem'
+ : `There are ${num} matching WeBWorK problems.`;
}
}
} catch (e) {
@@ -121,8 +134,14 @@
return;
}
- if (who == 'chapters' && requestObject.library_subjects == '') { lib_update(who, 'clear'); return; }
- if (who == 'sections' && requestObject.library_chapters == '') { lib_update(who, 'clear'); return; }
+ if (who == 'chapters' && requestObject.library_subjects == '') {
+ lib_update(who, 'clear');
+ return;
+ }
+ if (who == 'sections' && requestObject.library_chapters == '') {
+ lib_update(who, 'clear');
+ return;
+ }
requestObject.command = who == 'sections' ? 'getSectionListings' : 'getAllDBchapters';
@@ -174,8 +193,9 @@
libSections?.addEventListener('change', () => lib_update('count', 'clear'));
includeOPL?.addEventListener('change', () => lib_update('count', 'clear'));
includeContrib?.addEventListener('change', () => lib_update('count', 'clear'));
- document.querySelectorAll('input[name="level"]').forEach(
- (level) => level.addEventListener('change', () => lib_update('count', 'clear')));
+ document
+ .querySelectorAll('input[name="level"]')
+ .forEach((level) => level.addEventListener('change', () => lib_update('count', 'clear')));
// Set up the advanced view selects to submit the form when changed.
const libraryBrowserForm = document.forms['library_browser_form'];
@@ -190,8 +210,10 @@
const localSets = document.getElementById('local_sets');
const target = localSets?.value;
if (target === '') {
- alertToast(localSets?.dataset.noSetSelected ?? 'No Target Set Selected',
- localSets?.dataset.pickTargetSet ?? 'Pick a target set above to add this problem to.');
+ alertToast(
+ localSets?.dataset.noSetSelected ?? 'No Target Set Selected',
+ localSets?.dataset.pickTargetSet ?? 'Pick a target set above to add this problem to.'
+ );
return;
}
@@ -237,16 +259,22 @@
}
markinset();
- alertToast(localSets?.dataset.problemsAdded ?? 'Problems Added',
+ alertToast(
+ localSets?.dataset.problemsAdded ?? 'Problems Added',
(pathlist.length === 1 ? localSets?.dataset.addedToSingle : localSets?.dataset.addedToPlural)
- .replace(/{number}/, pathlist.length).replace(/{set}/, target.replaceAll('_', ' ')) ??
- `Added ${pathlist.length} problem${pathlist.length == 1 ? '' : 's'} to set ${
- target.replaceAll('_', ' ')}.`,
- true);
+ .replace(/{number}/, pathlist.length)
+ .replace(/{set}/, target.replaceAll('_', ' ')) ??
+ `Added ${pathlist.length} problem${pathlist.length == 1 ? '' : 's'} to set ${target.replaceAll(
+ '_',
+ ' '
+ )}.`,
+ true
+ );
};
document.querySelector('.library-action-btn.add-all-btn')?.addEventListener('click', () => addme('', 'all'));
- document.querySelectorAll('button.add_me')
+ document
+ .querySelectorAll('button.add_me')
.forEach((btn) => btn.addEventListener('click', () => addme(btn.dataset.sourceFile, 'one')));
// Update the messages about which problems are in the current set.
@@ -264,7 +292,7 @@
mode: 'same-origin',
body: new URLSearchParams(ro),
signal: controller.signal
- })
+ });
clearTimeout(timeoutId);
@@ -303,10 +331,12 @@
const delFromPGList = (path) => {
let j = findAPLindex(path) + 1;
while (document.querySelector(`[name="all_past_list${j}"]`)) {
- document.querySelector(`[name="all_past_list${j - 1}"]`).value =
- document.querySelector(`[name="all_past_list${j}"]`).value;
- document.querySelector(`[name="all_past_mlt${j - 1}"]`).value =
- document.querySelector(`[name="all_past_mlt${j}"]`).value;
+ document.querySelector(`[name="all_past_list${j - 1}"]`).value = document.querySelector(
+ `[name="all_past_list${j}"]`
+ ).value;
+ document.querySelector(`[name="all_past_mlt${j - 1}"]`).value = document.querySelector(
+ `[name="all_past_mlt${j}"]`
+ ).value;
++j;
}
--j;
@@ -385,7 +415,7 @@
const n2 = totalshown.textContent;
const mltIcon = document.getElementById(`mlt${cnt}`);
- if(mltIcon.textContent == 'M') {
+ if (mltIcon.textContent == 'M') {
unshownAreas.forEach((area) => area.classList.remove('d-none'));
// Render any problems that were hidden that have not yet been rendered.
for (const area of unshownAreas) {
@@ -396,44 +426,53 @@
mltIcon.textContent = 'L';
mltIcon.dataset.bsTitle = mltIcon.dataset.lessText;
bootstrap.Tooltip.getInstance(mltIcon)?.dispose();
- new bootstrap.Tooltip(mltIcon, { fallbackPlacements: [] })
+ new bootstrap.Tooltip(mltIcon, { fallbackPlacements: [] });
count = -count;
} else {
unshownAreas.forEach((area) => area.classList.add('d-none'));
mltIcon.textContent = 'M';
mltIcon.dataset.bsTitle = mltIcon.dataset.moreText;
bootstrap.Tooltip.getInstance(mltIcon)?.dispose();
- new bootstrap.Tooltip(mltIcon, { fallbackPlacements: [] })
+ new bootstrap.Tooltip(mltIcon, { fallbackPlacements: [] });
}
lastshown.textContent = n1 - count;
totalshown.textContent = n2 - count;
const last_shown = document.querySelector('[name="last_shown"]');
last_shown.value = last_shown.value - count;
- }
+ };
- document.querySelectorAll('.lb-mlt-parent').forEach((button) =>
- attachEventListeners(button, () => togglemlt(button.dataset.mltCnt, button.dataset.mltNoshowClass)));
+ document
+ .querySelectorAll('.lb-mlt-parent')
+ .forEach((button) =>
+ attachEventListeners(button, () => togglemlt(button.dataset.mltCnt, button.dataset.mltNoshowClass))
+ );
// Problem rendering
- const render = (id) => new Promise((resolve) => {
- const renderArea = document.getElementById(`problem_render_area_${id}`);
- if (!renderArea) { resolve(); return; }
-
- // Abort if the display mode is not set to None
- if (document.getElementById('problem_displaymode')?.value === 'None') {
- while (renderArea.firstChild) renderArea.firstChild.remove();
- resolve();
- return;
- }
+ const render = (id) =>
+ new Promise((resolve) => {
+ const renderArea = document.getElementById(`problem_render_area_${id}`);
+ if (!renderArea) {
+ resolve();
+ return;
+ }
- webworkConfig.renderProblem(renderArea, {
- sourceFilePath: renderArea.dataset.pgFile,
- problemSeed: Math.floor(Math.random() * 10000),
- showHints: document.querySelector('input[name="showHints"]')?.checked ? 1 : 0,
- showSolutions: document.querySelector('input[name="showSolutions"]')?.checked ? 1 : 0
- }).then(resolve);
- });
+ // Abort if the display mode is not set to None
+ if (document.getElementById('problem_displaymode')?.value === 'None') {
+ while (renderArea.firstChild) renderArea.firstChild.remove();
+ resolve();
+ return;
+ }
+
+ webworkConfig
+ .renderProblem(renderArea, {
+ sourceFilePath: renderArea.dataset.pgFile,
+ problemSeed: Math.floor(Math.random() * 10000),
+ showHints: document.querySelector('input[name="showHints"]')?.checked ? 1 : 0,
+ showSolutions: document.querySelector('input[name="showSolutions"]')?.checked ? 1 : 0
+ })
+ .then(resolve);
+ });
// Find all render areas
const renderAreas = document.querySelectorAll('.rpc_render_area');
@@ -453,11 +492,13 @@
})();
// Set up the problem rerandomization buttons.
- document.querySelectorAll('.rerandomize_problem_button').forEach((button) =>
- attachEventListeners(button, () => render(button.dataset.targetProblem)));
+ document
+ .querySelectorAll('.rerandomize_problem_button')
+ .forEach((button) => attachEventListeners(button, () => render(button.dataset.targetProblem)));
// Enable bootstrap popovers and tooltips.
document.querySelectorAll('.info-button').forEach((popover) => new bootstrap.Popover(popover));
- document.querySelectorAll('.lb-problem-add [data-bs-toggle], .lb-problem-icons [data-bs-toggle=tooltip]')
+ document
+ .querySelectorAll('.lb-problem-add [data-bs-toggle], .lb-problem-icons [data-bs-toggle=tooltip]')
.forEach((el) => new bootstrap.Tooltip(el, { fallbackPlacements: [] }));
})();
diff --git a/htdocs/js/UserDetail/userdetail.js b/htdocs/js/UserDetail/userdetail.js
index 88114021a7..5295406e3f 100644
--- a/htdocs/js/UserDetail/userdetail.js
+++ b/htdocs/js/UserDetail/userdetail.js
@@ -7,16 +7,18 @@
// This is a versioned set. If this is checked, make sure that the template set is also checked.
checkbox.addEventListener('change', () => {
if (checkbox.checked)
- document.querySelector(`input[type="checkbox"][name="set.${
- setID.replace(/,v\d*$/, '')}.assignment"]`).checked = true;
+ document.querySelector(
+ `input[type="checkbox"][name="set.${setID.replace(/,v\d*$/, '')}.assignment"]`
+ ).checked = true;
});
} else {
// This is a global set that may be versioned.
// So if it is unchecked, also uncheck any versions that may exist.
checkbox.addEventListener('change', () => {
if (!checkbox.checked) {
- document.querySelectorAll(`input[type="checkbox"][name^="set.${setID},v"][name$=".assignment"]`)
- .forEach((versionCheckbox) => versionCheckbox.checked = false);
+ document
+ .querySelectorAll(`input[type="checkbox"][name^="set.${setID},v"][name$=".assignment"]`)
+ .forEach((versionCheckbox) => (versionCheckbox.checked = false));
}
});
}
@@ -24,24 +26,26 @@
// Make the date override checkboxes checked or unchecked appropriately
// as determined by the value of the date input when that value changes.
- document.querySelectorAll('input[type="text"][data-override],input[type="hidden"][data-override]')
- .forEach((input) =>
- {
- const overrideCheck = document.getElementById(input.dataset.override);
- if (!overrideCheck) return;
- const changeHandler = () => overrideCheck.checked = input.value != '';
- input.addEventListener('change', changeHandler);
- // Attach the keyup and blur handlers to the flatpickr alternate input.
- input.previousElementSibling?.addEventListener('keyup', changeHandler);
- input.previousElementSibling?.addEventListener('blur',
- () => { if (input.previousElementSibling.value == '') overrideCheck.checked = false; });
- });
+ document
+ .querySelectorAll('input[type="text"][data-override],input[type="hidden"][data-override]')
+ .forEach((input) => {
+ const overrideCheck = document.getElementById(input.dataset.override);
+ if (!overrideCheck) return;
+ const changeHandler = () => (overrideCheck.checked = input.value != '');
+ input.addEventListener('change', changeHandler);
+ // Attach the keyup and blur handlers to the flatpickr alternate input.
+ input.previousElementSibling?.addEventListener('keyup', changeHandler);
+ input.previousElementSibling?.addEventListener('blur', () => {
+ if (input.previousElementSibling.value == '') overrideCheck.checked = false;
+ });
+ });
// If the "Assign All Sets to Current User" button is clicked, then check all assignments.
document.getElementsByName('assignAll').forEach((button) => {
button.addEventListener('click', () => {
- document.querySelectorAll('input[name^="set."][name$=".assignment"]')
- .forEach((check) => check.checked = true);
+ document
+ .querySelectorAll('input[name^="set."][name$=".assignment"]')
+ .forEach((check) => (check.checked = true));
});
});
})();
diff --git a/htdocs/themes/math4-green/_theme-colors.scss b/htdocs/themes/math4-green/_theme-colors.scss
index 1aaa5b0c09..f577945b9f 100644
--- a/htdocs/themes/math4-green/_theme-colors.scss
+++ b/htdocs/themes/math4-green/_theme-colors.scss
@@ -13,7 +13,7 @@
*/
// Include bootstrap scss functions (so you can manipulate colors, SVGs, calc, etc)
-@import "../../node_modules/bootstrap/scss/functions";
+@import '../../node_modules/bootstrap/scss/functions';
// Theme colors
$primary: #324f36;
diff --git a/htdocs/themes/math4-red/_theme-colors.scss b/htdocs/themes/math4-red/_theme-colors.scss
index cb0d0530bd..e1f057edb6 100644
--- a/htdocs/themes/math4-red/_theme-colors.scss
+++ b/htdocs/themes/math4-red/_theme-colors.scss
@@ -13,7 +13,7 @@
*/
// Include bootstrap scss functions (so you can manipulate colors, SVGs, calc, etc)
-@import "../../node_modules/bootstrap/scss/functions";
+@import '../../node_modules/bootstrap/scss/functions';
// Theme colors
$primary: #800;
diff --git a/htdocs/themes/math4-red/_theme-overrides.scss b/htdocs/themes/math4-red/_theme-overrides.scss
index 08cb611a80..20b5856367 100644
--- a/htdocs/themes/math4-red/_theme-overrides.scss
+++ b/htdocs/themes/math4-red/_theme-overrides.scss
@@ -1,4 +1,3 @@
a:not(.btn):focus {
- outline-color: #{lighten($link-hover-color, 26%)};
+ outline-color: #{lighten($link-hover-color, 26%)};
}
-
diff --git a/htdocs/themes/math4-yellow/_theme-colors.scss b/htdocs/themes/math4-yellow/_theme-colors.scss
index 9ef99947b9..b718e81b27 100644
--- a/htdocs/themes/math4-yellow/_theme-colors.scss
+++ b/htdocs/themes/math4-yellow/_theme-colors.scss
@@ -13,7 +13,7 @@
*/
// Include bootstrap scss functions (so you can manipulate colors, SVGs, calc, etc)
-@import "../../node_modules/bootstrap/scss/functions";
+@import '../../node_modules/bootstrap/scss/functions';
// Theme colors
$primary: #ffc700;
@@ -37,8 +37,8 @@ $ww-achievement-level-color: darken($primary, 15%);
$accordion-button-active-color: shade-color($primary, 50%);
// Make the navbar colors dark.
-$navbar-dark-color: rgba(#000, .55);
-$navbar-dark-hover-color: rgba(#000, .75);
-$navbar-dark-active-color: #000;
-$navbar-dark-disabled-color: rgba(#000, .25);
-$navbar-dark-toggler-border-color: rgba(#000, .1);
+$navbar-dark-color: rgba(#000, 0.55);
+$navbar-dark-hover-color: rgba(#000, 0.75);
+$navbar-dark-active-color: #000;
+$navbar-dark-disabled-color: rgba(#000, 0.25);
+$navbar-dark-toggler-border-color: rgba(#000, 0.1);
diff --git a/htdocs/themes/math4-yellow/_theme-overrides.scss b/htdocs/themes/math4-yellow/_theme-overrides.scss
index 9db468ea94..a27951d4f6 100644
--- a/htdocs/themes/math4-yellow/_theme-overrides.scss
+++ b/htdocs/themes/math4-yellow/_theme-overrides.scss
@@ -2,18 +2,30 @@
// Only the foreground colors are changed.
.btn-info {
@include button-variant(
- $info, // background color
- $info, // border color
- $primary, // foreground color
- tint-color($info, $btn-hover-bg-tint-amount), // hover background color
- tint-color($info, $btn-hover-border-tint-amount), // hover border color
- $primary, // hover foreground color
- tint-color($info, $btn-active-bg-tint-amount), // active background color
- tint-color($info, $btn-active-border-tint-amount), // active border color
- $primary, // active foreground color
- $info, // disabled background color
- $info, // disabled border color
- color-contrast($info) // disabled foreground color
+ // background color
+ $info,
+ // border color
+ $info,
+ // foreground color
+ $primary,
+ // hover background color
+ tint-color($info, $btn-hover-bg-tint-amount),
+ // hover border color
+ tint-color($info, $btn-hover-border-tint-amount),
+ // hover foreground color
+ $primary,
+ // active background color
+ tint-color($info, $btn-active-bg-tint-amount),
+ // active border color
+ tint-color($info, $btn-active-border-tint-amount),
+ // active foreground color
+ $primary,
+ // disabled background color
+ $info,
+ // disabled border color
+ $info,
+ // disabled foreground color
+ color-contrast($info)
);
}
diff --git a/htdocs/themes/math4/_theme-colors.scss b/htdocs/themes/math4/_theme-colors.scss
index d4bee928aa..d691ee809d 100644
--- a/htdocs/themes/math4/_theme-colors.scss
+++ b/htdocs/themes/math4/_theme-colors.scss
@@ -13,7 +13,7 @@
*/
// Include bootstrap scss functions (so you can manipulate colors, SVGs, calc, etc)
-@import "../../node_modules/bootstrap/scss/functions";
+@import '../../node_modules/bootstrap/scss/functions';
// Theme colors
$primary: #038;
@@ -27,4 +27,4 @@ $link-hover-color: $info;
$ww-logo-background-color: darken($info, 14%);
// Achievment level bar
-$ww-achievement-level-color: #88D;
+$ww-achievement-level-color: #88d;
diff --git a/htdocs/themes/math4/achievements.scss b/htdocs/themes/math4/achievements.scss
index 32643922af..783c9f1830 100644
--- a/htdocs/themes/math4/achievements.scss
+++ b/htdocs/themes/math4/achievements.scss
@@ -21,7 +21,7 @@
.levelinnerbar {
height: 100%;
- background-color: var(--ww-achievement-level-color, #88D);
+ background-color: var(--ww-achievement-level-color, #88d);
}
.cheevoouterbox img {
@@ -47,7 +47,7 @@
.cheevoinnerbar {
height: 100%;
- background-color: var(--ww-achievement-level-color, #88D);
+ background-color: var(--ww-achievement-level-color, #88d);
}
.cheevo-toast-container {
diff --git a/htdocs/themes/math4/bootstrap.scss b/htdocs/themes/math4/bootstrap.scss
index caedfdb53c..4e94098660 100644
--- a/htdocs/themes/math4/bootstrap.scss
+++ b/htdocs/themes/math4/bootstrap.scss
@@ -13,7 +13,7 @@
*/
// Include functions first (so you can manipulate colors, SVGs, calc, etc)
-@import "../../node_modules/bootstrap/scss/functions";
+@import '../../node_modules/bootstrap/scss/functions';
// Variable overrides
@@ -35,53 +35,53 @@ $link-hover-decoration: underline;
$breadcrumb-divider-color: #495057;
$breadcrumb-active-color: #495057;
-@import "./theme-colors";
+@import './theme-colors';
// Include the remainder of bootstrap's scss configuration
-@import "../../node_modules/bootstrap/scss/variables";
-@import "../../node_modules/bootstrap/scss/variables-dark";
-@import "../../node_modules/bootstrap/scss/maps";
-@import "../../node_modules/bootstrap/scss/mixins";
-@import "../../node_modules/bootstrap/scss/utilities";
+@import '../../node_modules/bootstrap/scss/variables';
+@import '../../node_modules/bootstrap/scss/variables-dark';
+@import '../../node_modules/bootstrap/scss/maps';
+@import '../../node_modules/bootstrap/scss/mixins';
+@import '../../node_modules/bootstrap/scss/utilities';
// Layout & components
-@import "../../node_modules/bootstrap/scss/root";
-@import "../../node_modules/bootstrap/scss/reboot";
-@import "../../node_modules/bootstrap/scss/type";
-@import "../../node_modules/bootstrap/scss/images";
-@import "../../node_modules/bootstrap/scss/containers";
-@import "../../node_modules/bootstrap/scss/grid";
-@import "../../node_modules/bootstrap/scss/tables";
-@import "../../node_modules/bootstrap/scss/forms";
-@import "../../node_modules/bootstrap/scss/buttons";
-@import "../../node_modules/bootstrap/scss/transitions";
-@import "../../node_modules/bootstrap/scss/dropdown";
-@import "../../node_modules/bootstrap/scss/button-group";
-@import "../../node_modules/bootstrap/scss/nav";
-@import "../../node_modules/bootstrap/scss/navbar";
-@import "../../node_modules/bootstrap/scss/card";
-@import "../../node_modules/bootstrap/scss/accordion";
-@import "../../node_modules/bootstrap/scss/breadcrumb";
-@import "../../node_modules/bootstrap/scss/pagination";
-@import "../../node_modules/bootstrap/scss/badge";
-@import "../../node_modules/bootstrap/scss/alert";
-@import "../../node_modules/bootstrap/scss/placeholders";
-@import "../../node_modules/bootstrap/scss/progress";
-@import "../../node_modules/bootstrap/scss/list-group";
-@import "../../node_modules/bootstrap/scss/close";
-@import "../../node_modules/bootstrap/scss/toasts";
-@import "../../node_modules/bootstrap/scss/modal";
-@import "../../node_modules/bootstrap/scss/tooltip";
-@import "../../node_modules/bootstrap/scss/popover";
-@import "../../node_modules/bootstrap/scss/carousel";
-@import "../../node_modules/bootstrap/scss/spinners";
-@import "../../node_modules/bootstrap/scss/offcanvas";
+@import '../../node_modules/bootstrap/scss/root';
+@import '../../node_modules/bootstrap/scss/reboot';
+@import '../../node_modules/bootstrap/scss/type';
+@import '../../node_modules/bootstrap/scss/images';
+@import '../../node_modules/bootstrap/scss/containers';
+@import '../../node_modules/bootstrap/scss/grid';
+@import '../../node_modules/bootstrap/scss/tables';
+@import '../../node_modules/bootstrap/scss/forms';
+@import '../../node_modules/bootstrap/scss/buttons';
+@import '../../node_modules/bootstrap/scss/transitions';
+@import '../../node_modules/bootstrap/scss/dropdown';
+@import '../../node_modules/bootstrap/scss/button-group';
+@import '../../node_modules/bootstrap/scss/nav';
+@import '../../node_modules/bootstrap/scss/navbar';
+@import '../../node_modules/bootstrap/scss/card';
+@import '../../node_modules/bootstrap/scss/accordion';
+@import '../../node_modules/bootstrap/scss/breadcrumb';
+@import '../../node_modules/bootstrap/scss/pagination';
+@import '../../node_modules/bootstrap/scss/badge';
+@import '../../node_modules/bootstrap/scss/alert';
+@import '../../node_modules/bootstrap/scss/placeholders';
+@import '../../node_modules/bootstrap/scss/progress';
+@import '../../node_modules/bootstrap/scss/list-group';
+@import '../../node_modules/bootstrap/scss/close';
+@import '../../node_modules/bootstrap/scss/toasts';
+@import '../../node_modules/bootstrap/scss/modal';
+@import '../../node_modules/bootstrap/scss/tooltip';
+@import '../../node_modules/bootstrap/scss/popover';
+@import '../../node_modules/bootstrap/scss/carousel';
+@import '../../node_modules/bootstrap/scss/spinners';
+@import '../../node_modules/bootstrap/scss/offcanvas';
// Helpers
-@import "../../node_modules/bootstrap/scss/helpers";
+@import '../../node_modules/bootstrap/scss/helpers';
// Utilities
-@import "../../node_modules/bootstrap/scss/utilities/api";
+@import '../../node_modules/bootstrap/scss/utilities/api';
// WeBWorK specific colors
:root {
@@ -99,4 +99,4 @@ a:not(.btn):focus {
outline-width: 1px;
}
-@import "theme-overrides";
+@import 'theme-overrides';
diff --git a/htdocs/themes/math4/gateway.scss b/htdocs/themes/math4/gateway.scss
index 665b7dc866..69ebedd7da 100644
--- a/htdocs/themes/math4/gateway.scss
+++ b/htdocs/themes/math4/gateway.scss
@@ -37,10 +37,10 @@ div.gwMessage {
}
#gwScoreSummary {
- background-color:#ffeeaa;
+ background-color: #ffeeaa;
color: black;
box-shadow: 3px 3px 0.5em darkgray;
- font-family:Times serif;
+ font-family: Times serif;
z-index: 30;
font-size: 85%;
border-color: #ffeeaa;
@@ -55,15 +55,18 @@ div.gwMessage {
border-radius: 4px;
table {
- border:0;
+ border: 0;
- td, th {
- margin-left:.2em;
+ td,
+ th {
+ margin-left: 0.2em;
}
}
}
-table.attemptResults { width: unset; }
+table.attemptResults {
+ width: unset;
+}
.gwProblem {
background-color: #fafafa;
@@ -84,12 +87,13 @@ table.attemptResults { width: unset; }
margin-bottom: 1rem;
text-align: center;
- th, td {
+ th,
+ td {
padding: 0 0.5rem;
}
th {
- text-align:right;
+ text-align: right;
font-weight: bold;
padding-right: 1rem;
}
diff --git a/htdocs/themes/math4/math4.js b/htdocs/themes/math4/math4.js
index 4a29c2ac2a..a76ed51e6e 100644
--- a/htdocs/themes/math4/math4.js
+++ b/htdocs/themes/math4/math4.js
@@ -16,7 +16,7 @@
// Enable site-navigation menu toggling if the page has a site-navigation element.
const navigation_element = document.getElementById('site-navigation');
if (navigation_element) {
- const threshold = 768
+ const threshold = 768;
let currentWidth = window.innerWidth;
const content = document.getElementById('content');
@@ -56,15 +56,18 @@
if (!navigation_element.classList.contains('toggle-width') && window.innerWidth >= threshold)
navigation_element.classList.remove('invisible');
- if ((navigation_element.classList.contains('toggle-width') &&
- window.innerWidth < threshold && currentWidth >= threshold) ||
+ if (
+ (navigation_element.classList.contains('toggle-width') &&
+ window.innerWidth < threshold &&
+ currentWidth >= threshold) ||
(navigation_element.classList.contains('toggle-width') &&
- window.innerWidth >= threshold && currentWidth < threshold))
- {
+ window.innerWidth >= threshold &&
+ currentWidth < threshold)
+ ) {
currentWidth = window.innerWidth;
toggleSidebar();
document.body.classList.remove('no-scroll');
- document.querySelectorAll('.sidebar-backdrop').forEach(overlay => overlay.remove());
+ document.querySelectorAll('.sidebar-backdrop').forEach((overlay) => overlay.remove());
}
currentWidth = window.innerWidth;
});
@@ -72,20 +75,20 @@
// Turn help boxes into popovers
document.querySelectorAll('.help-popup').forEach((popover) => {
- new bootstrap.Popover(popover, {trigger: 'hover focus'});
+ new bootstrap.Popover(popover, { trigger: 'hover focus' });
});
// Problem page popovers
- document.querySelectorAll('.student-nav-button').forEach(
- (el) => new bootstrap.Tooltip(el, {trigger: 'hover', fallbackPlacements: []})
- );
+ document
+ .querySelectorAll('.student-nav-button')
+ .forEach((el) => new bootstrap.Tooltip(el, { trigger: 'hover', fallbackPlacements: [] }));
// Sets up problems to rescale the image accoring to attr height width and not native height width.
const rescaleImage = (_index, element) => {
if (element.height != element.naturalHeight || element.width != element.naturalWidth) {
- element.height = element.getBoundingClientRect().width * element.height / element.width;
+ element.height = (element.getBoundingClientRect().width * element.height) / element.width;
}
- }
+ };
document.querySelectorAll('.problem-content img').forEach(rescaleImage);
window.addEventListener('resize', () => document.querySelectorAll('.problem-content img').forEach(rescaleImage));
@@ -97,9 +100,9 @@
});
// Hardcopy tooltips shown on the Problem Sets page.
- document.querySelectorAll('.hardcopy-tooltip').forEach(
- (el) => new bootstrap.Tooltip(el, { trigger: 'hover', fallbackPlacements: [], html: true })
- );
+ document
+ .querySelectorAll('.hardcopy-tooltip')
+ .forEach((el) => new bootstrap.Tooltip(el, { trigger: 'hover', fallbackPlacements: [], html: true }));
// PG Problem Editor
document.querySelectorAll('.reference-link').forEach((el) => new bootstrap.Tooltip(el));
@@ -122,10 +125,14 @@
// Hide the dismiss button when the last alert is dismissed.
for (const message of messages) {
- message.addEventListener('closed.bs.alert', () => {
- if (!document.querySelector('#message .alert-dismissible, #message_bottom .alert-dismissible'))
- dismissBtn.remove();
- }, { once: true });
+ message.addEventListener(
+ 'closed.bs.alert',
+ () => {
+ if (!document.querySelector('#message .alert-dismissible, #message_bottom .alert-dismissible'))
+ dismissBtn.remove();
+ },
+ { once: true }
+ );
}
dismissBtn?.addEventListener('click', () =>
diff --git a/htdocs/themes/math4/math4.scss b/htdocs/themes/math4/math4.scss
index 5adcdc09c2..a0d0c05436 100644
--- a/htdocs/themes/math4/math4.scss
+++ b/htdocs/themes/math4/math4.scss
@@ -110,7 +110,8 @@ $site-nav-width: 250px !default;
}
}
- a, span {
+ a,
+ span {
display: inline-block;
margin-right: 0.5rem;
}
@@ -220,7 +221,6 @@ $site-nav-width: 250px !default;
&.active {
background-color: var(--ww-site-nav-link-active-background-color, #038);
color: var(--ww-primary-foreground-color, white);
-
}
}
@@ -299,7 +299,10 @@ $site-nav-width: 250px !default;
padding: 0.25rem;
border-radius: 5px;
color: rgba(255, 255, 255, 0.85);
- transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out;
+ transition:
+ color 0.15s ease-in-out,
+ background-color 0.15s ease-in-out,
+ border-color 0.15s ease-in-out;
&:hover {
color: #fff;
@@ -353,9 +356,9 @@ $site-nav-width: 250px !default;
/* Show me another */
div.showMeAnotherBox {
- background-color: #EDE275;
+ background-color: #ede275;
border-radius: 5px;
- border: 2px solid #FDD017;
+ border: 2px solid #fdd017;
padding: 3px;
margin-bottom: 0.5rem;
}
@@ -461,11 +464,15 @@ h2.page-title {
}
}
-.font-visible { font-weight: bold; }
-.font-hidden { font-style: italic; }
+.font-visible {
+ font-weight: bold;
+}
+.font-hidden {
+ font-style: italic;
+}
.admin-messagebox {
- background-color: #FFFFCC;
+ background-color: #ffffcc;
width: 60%;
padding: 10px;
text-align: left;
@@ -495,7 +502,7 @@ ul.courses-list {
/* Instructor Tools page */
#instructor-tools-nav {
- input[name="number_of_students"] {
+ input[name='number_of_students'] {
max-width: 7em;
}
@@ -541,7 +548,8 @@ ul.courses-list {
font-weight: normal;
}
- .hardcopy, .hardcopy-link {
+ .hardcopy,
+ .hardcopy-link {
text-align: center;
}
@@ -604,7 +612,11 @@ ul.courses-list {
border-radius: 8px;
border: 1px solid #e6e6e6;
- h2, h3, h4, h5, h6 {
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
background: var(--bs-primary, #038);
border-radius: 8px;
color: var(--ww-primary-foreground-color, white);
@@ -616,17 +628,18 @@ ul.courses-list {
}
dl {
- margin: 1ex .5em 1ex 1ex;
+ margin: 1ex 0.5em 1ex 1ex;
padding: 0;
font-size: 80%;
}
- li, dt {
+ li,
+ dt {
line-height: 1.2rem;
}
dt {
- font-weight: bold
+ font-weight: bold;
}
dd {
@@ -642,7 +655,7 @@ ul.courses-list {
font-size: 80%;
font-style: italic;
margin-bottom: 1ex;
- margin-right: .5em;
+ margin-right: 0.5em;
}
form {
@@ -657,7 +670,7 @@ ul.courses-list {
}
#library_sets {
- max-width: 50%
+ max-width: 50%;
}
.browse-lib-btn,
@@ -726,11 +739,14 @@ div.AuthorComment {
}
}
-input.changed[type=text] { /* orange */
+input.changed[type='text'] {
+ /* orange */
border-color: #ca5000;
outline: 0;
outline: thin dotted \9;
- box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(202, 80, 0, 0.6);
+ box-shadow:
+ inset 0 1px 1px rgba(0, 0, 0, 0.075),
+ 0 0 8px rgba(202, 80, 0, 0.6);
color: inherit;
}
@@ -745,7 +761,7 @@ input.changed[type=text] { /* orange */
margin-bottom: 1em;
padding: 2px 5px 2px 5px;
max-width: 80%;
- background-color: #E8E8E8;
+ background-color: #e8e8e8;
border-style: outset;
border-width: 1px;
border-spacing: 2px;
@@ -767,13 +783,33 @@ input.changed[type=text] { /* orange */
}
/* Styles used when editing a temporary file */
-.temporaryFile { font-style: italic; color: #ca5000; background-color: inherit; }
+.temporaryFile {
+ font-style: italic;
+ color: #ca5000;
+ background-color: inherit;
+}
/* Text colors for Auditing, Current, and Dropped students */
-.Audit { font-style: normal; color: purple; background-color: inherit; }
-.Enrolled { font-weight: normal; color: black; background-color: inherit; }
-.Drop { font-style: italic; color: #555; background-color: inherit; }
-.Observer { font-style: normal; color: green; background-color: inherit; }
+.Audit {
+ font-style: normal;
+ color: purple;
+ background-color: inherit;
+}
+.Enrolled {
+ font-weight: normal;
+ color: black;
+ background-color: inherit;
+}
+.Drop {
+ font-style: italic;
+ color: #555;
+ background-color: inherit;
+}
+.Observer {
+ font-style: normal;
+ color: green;
+ background-color: inherit;
+}
/* Styles for the PGProblemEditor Page */
@@ -824,7 +860,7 @@ input.changed[type=text] { /* orange */
/* Problem Set Detail */
#problem_set_form {
- input[name=add_n_problems] {
+ input[name='add_n_problems'] {
flex-basis: 50px;
}
}
@@ -939,7 +975,8 @@ input.changed[type=text] { /* orange */
/* Course Configuration */
.config-tabs {
- a, span {
+ a,
+ span {
&.nav-link {
font-weight: bold;
color: inherit;
@@ -1022,7 +1059,8 @@ td.alt-source {
padding-left: 0.5rem;
padding-right: 0.5rem;
- &.alert-success, &.alert-danger {
+ &.alert-success,
+ &.alert-danger {
transition: none;
border-radius: 3px;
color: var(--bs-alert-color);