diff --git a/docs/userGuide/syntax/variables.mbdf b/docs/userGuide/syntax/variables.mbdf
index 168ba3b47f..4b712f4bc9 100644
--- a/docs/userGuide/syntax/variables.mbdf
+++ b/docs/userGuide/syntax/variables.mbdf
@@ -172,6 +172,26 @@ However, this is a combination of *both* syntaxes above, and thus this will allo
+### Defining variables with JSON
+
+You could also have your variables defined in a JSON file to define multiple variables in a more concise manner.
+
+{{ icon_example }}
+`variables.md`:
+```html
+{{ const_note }} :fas-arrow-right: Note: This is a constant.
+When defining variables with incomplete HTML fragments, we can define variables as a separate JSON file.
+
+{{ icon_example }} variables containing HTML fragments:
+
+`index.md`:
+```html
+
{{ front_fragment }} and {{ back_fragment }} :fas-arrow-right: Front and Back
+
Global variables:
diff --git a/src/Site.js b/src/Site.js
index d8fc4eb3ed..92fc785280 100644
--- a/src/Site.js
+++ b/src/Site.js
@@ -503,10 +503,10 @@ class Site {
this.baseUrlMap.forEach((base) => {
const userDefinedVariables = {};
Object.assign(userDefinedVariables, markbindVariable);
-
+ const userDefinedVariablesPath = path.resolve(base, USER_VARIABLES_PATH);
+ const userDefinedVariablesDir = path.dirname(userDefinedVariablesPath);
let content;
try {
- const userDefinedVariablesPath = path.resolve(base, USER_VARIABLES_PATH);
content = fs.readFileSync(userDefinedVariablesPath, 'utf8');
} catch (e) {
content = '';
@@ -521,9 +521,27 @@ class Site {
const $ = cheerio.load(content);
$('variable,span').each(function () {
const name = $(this).attr('name') || $(this).attr('id');
- // Process the content of the variable with nunjucks, in case it refers to other variables.
- const html = nunjuckUtils.renderEscaped(nunjucks, $(this).html(), userDefinedVariables);
- userDefinedVariables[name] = html;
+ const variableSource = $(this).attr('from');
+
+ if (variableSource !== undefined) {
+ try {
+ const variableFilePath = path.resolve(userDefinedVariablesDir, variableSource);
+ const jsonData = fs.readFileSync(variableFilePath);
+ const varData = JSON.parse(jsonData);
+ Object.entries(varData).forEach(([varName, varValue]) => {
+ // Process the content of the variable with nunjucks, in case it refers to other variables.
+ const variableValue = nunjuckUtils.renderEscaped(nunjucks, varValue, userDefinedVariables);
+
+ userDefinedVariables[varName] = variableValue;
+ });
+ } catch (err) {
+ logger.warn(`Error ${err.message}`);
+ }
+ } else {
+ // Process the content of the variable with nunjucks, in case it refers to other variables.
+ const html = nunjuckUtils.renderEscaped(nunjucks, $(this).html(), userDefinedVariables);
+ userDefinedVariables[name] = html;
+ }
});
});
}
diff --git a/src/lib/markbind/src/parser.js b/src/lib/markbind/src/parser.js
index 97ec8811c3..32a1dec330 100644
--- a/src/lib/markbind/src/parser.js
+++ b/src/lib/markbind/src/parser.js
@@ -8,6 +8,7 @@ const slugify = require('@sindresorhus/slugify');
const componentParser = require('./parsers/componentParser');
const componentPreprocessor = require('./preprocessors/componentPreprocessor');
const nunjuckUtils = require('./utils/nunjuckUtils');
+const logger = require('../../../util/logger');
const _ = {};
_.clone = require('lodash/clone');
@@ -67,6 +68,7 @@ class Parser {
*/
// eslint-disable-next-line class-methods-use-this
extractPageVariables(fileName, data, userDefinedVariables, includedVariables) {
+ const fileDir = path.dirname(fileName);
const $ = cheerio.load(data);
const pageVariables = {};
Parser.VARIABLE_LOOKUP.set(fileName, new Map());
@@ -92,21 +94,42 @@ class Parser {
importedVariables[name] = `{{${alias}.${name}}}`;
});
});
- $('variable').each(function () {
- const variableElement = $(this);
- const variableName = variableElement.attr('name');
- if (!variableName) {
- // eslint-disable-next-line no-console
- console.warn(`Missing 'name' for variable in ${fileName}\n`);
- return;
- }
+ const setPageVariable = (variableName, rawVariableValue) => {
+ const otherVariables = {
+ ...importedVariables,
+ ...pageVariables,
+ ...userDefinedVariables,
+ ...includedVariables,
+ };
+ const variableValue = nunjuckUtils.renderEscaped(nunjucks, rawVariableValue, otherVariables);
if (!pageVariables[variableName]) {
- const variableValue = nunjuckUtils.renderEscaped(nunjucks, md.renderInline(variableElement.html()), {
- ...importedVariables, ...pageVariables, ...userDefinedVariables, ...includedVariables,
- });
pageVariables[variableName] = variableValue;
Parser.VARIABLE_LOOKUP.get(fileName).set(variableName, variableValue);
}
+ };
+ $('variable').each(function () {
+ const variableElement = $(this);
+ const variableName = variableElement.attr('name');
+ const variableSource = $(this).attr('from');
+ if (variableSource !== undefined) {
+ try {
+ const variableFilePath = path.resolve(fileDir, variableSource);
+ const jsonData = fs.readFileSync(variableFilePath);
+ const varData = JSON.parse(jsonData);
+ Object.entries(varData).forEach(([varName, varValue]) => {
+ setPageVariable(varName, varValue);
+ });
+ } catch (err) {
+ logger.warn(`Error ${err.message}`);
+ }
+ } else {
+ if (!variableName) {
+ // eslint-disable-next-line no-console
+ console.warn(`Missing 'name' for variable in ${fileName}\n`);
+ return;
+ }
+ setPageVariable(variableName, md.renderInline(variableElement.html()));
+ }
});
return { ...importedVariables, ...pageVariables };
}
diff --git a/src/template/default/_markbind/variables.json b/src/template/default/_markbind/variables.json
new file mode 100644
index 0000000000..04d0b977d3
--- /dev/null
+++ b/src/template/default/_markbind/variables.json
@@ -0,0 +1,3 @@
+{
+ "jsonVariableExample": "Your variables can be defined here as well"
+}
\ No newline at end of file
diff --git a/src/template/default/_markbind/variables.md b/src/template/default/_markbind/variables.md
index d1f129e068..aab37f29a9 100644
--- a/src/template/default/_markbind/variables.md
+++ b/src/template/default/_markbind/variables.md
@@ -1,4 +1,6 @@
Inline footnotes: Here is an inline note.[3]
Json Variable
+Json Variable can be referenced Referencing jsonVar1: Json Variable can be referenced
Variables that reference another variable
This variable can be referenced.
References can be several levels deep.
Page Variable
- Page Variable + +Page Variable Json Variable
Page Variable with HTML and MD
Page Variable with HTML and Markdown diff --git a/test/functional/test_site/expected/jsonPageVariable.json b/test/functional/test_site/expected/jsonPageVariable.json new file mode 100644 index 0000000000..28d96f5cd7 --- /dev/null +++ b/test/functional/test_site/expected/jsonPageVariable.json @@ -0,0 +1,3 @@ +{ + "json_page_variable": "Json Variable" +} \ No newline at end of file diff --git a/test/functional/test_site/index.md b/test/functional/test_site/index.md index d36f7f8261..06c35acb8d 100644 --- a/test/functional/test_site/index.md +++ b/test/functional/test_site/index.md @@ -18,6 +18,12 @@ tags: ["tag-frontmatter-shown", "tag-included-file", "+tag-exp*", "-tag-exp-hidd