Global macros for KaTeX in docusaurus - docusaurus

I'm trying out docusaurus to write a rather technical manual.
One of the requirements is LaTeX support with macros.
Macros allow me to make fewer mistakes and easily change how some output looks for the entire document at once.
E.g. in stead of writing \text{P}_\text{location} = 5 \text{mbar} I could write \def\plocation#1{<definition>} and then \plocation{5}.
Docusaurus supports KaTeX, which in turn supports global macros. At least, in theory. I can't get it to work, unfortunately.
I've tried setting globalGroup: true in the config. I've also tried adding macros to the config itself. Stripped version of my config below.
Just to check defining macros does work, \def\x#1{x+#1}\x{5} results in x+5.
Adding \global or replacing \def with \gdef does not work.
What am I doing wrong? Or is this just not supported?
...
const macros = {
"\\x": "x+1"
};
/** #type {import('#docusaurus/types').Config} */
const config = {
...
presets: [
[
'classic',
/** #type {import('#docusaurus/preset-classic').Options} */
({
docs: {
...
remarkPlugins: [math],
rehypePlugins: [katex, {
throwOnError: true,
globalGroup: true,
macros
}],
},
...
}),
],
],
...
};

As one should, I figured out what I did wrong 34 minutes after posting this.
When adding config to a plugin, the plugin and config need to be inside [...].
The proper config is:
rehypePlugins: [[katex, {
throwOnError: true,
globalGroup: true,
macros
}]],

Related

How do I get Watch Mode with Sanity.io and Gatsby to refresh content when referenced documents are edited in the CMS / Studio?

I'm using Sanity.io, GatsbyJS 3.x
Watch mode works great when you update content in the CMS, except for when the content you edit is part of a referenced schema of type 'document'.
Put another way, changes made to a document referenced by another document will not re-render the page despite having watch mode on and configured properly.
For example, here is a snippet from my Page schema.
...
{
name: "content",
type: "array",
title: "Page Sections",
description: "Add, edit, and reorder sections",
of: [
{
type: 'reference',
to: [
{ type: 'nav' },
{ type: 'section' },
{ type: 'footer' }
]
}
],
},
...
The above schema references a
nav schema
section schema
footer schema
Each of these are type 'document'.
See the example below.
export default {
type: 'document',
name: 'section',
title: 'Page Sections',
fields: [
{
name: 'meta',
title: 'Section Meta Data',
type: 'meta'
},
...
I want to reference a document, rather than an object, because I need to use the content created based on these schemas to be re-used in throughout the application.
Finally, I've configured the source plugin correctly for watch mode.
Gatsby Config is set properly
{
resolve: `gatsby-source-sanity`,
options: {
projectId: `asdfasdf`,
dataset: `template`,
watchMode: true,
overlayDrafts: true,
token: process.env.MY_SANITY_TOKEN,
},
},
In the CMS / Studio, when you edit one of the fields, you can see Gatsby re-compile in dev mode from the terminal. However, the page does not auto reload and display the changes made to the referenced document.
I've tried reloading the page with the reload button and via hard refresh, the changes do not render.
The only way to render the changes is to go back to the CMS and edit a field on the main “Page” document. Then it refreshes immediately.
Am I doing something wrong? Is this expected behavior? Is there a way to get this to work?
For those that run across this issue, I was able to answer my own question. I hope this saves you the day's it took me to find a solution.
Solution TLDR
You need to explicitly query the referenced document in order for watch mode to work properly.
Details with Examples
Summary
The gatsby-source-sanity plugin provides convenience queries that start with _raw for array types. When you use the _raw query in your GraphQL query, it will not trigger watch mode to reload the data. You need to explicitly query the referenced document in order for watch mode to work properly. This may have to do with how the plugin sets up listeners and I don't know if this is a bug or a feature.
Example
My Page Document has the following schema
{
name: "content",
type: "array",
title: "Page Sections",
description: "Add, edit, and reorder sections",
of: [
{
type: "reference",
to: [
{ type: "nav" },
{ type: 'section' },
],
},
],
},
The section is a reference to a section document.
{ type: 'section' }
The reason I'm not using an object is because I want the page sections to be re-usable on multiple pages.
Assuming you have watch mode enabled properly in your gatsby-config.js file, watch mode, like so...
// gatsby-config.js
{
resolve: `gatsby-source-sanity`,
options: {
projectId: `asdf123sg`,
dataset: `datasetname`,
watchMode: true,
overlayDrafts: true,
token: process.env.SANITY_TOKEN,
},
},
Then you should see the following behavior:
listen for document/content updates
re-run queries, update the data, hot-reload the page
You'll see the following scroll in your terminal window.
success Re-building development bundle - 1.371s
success building schema - 0.420s
success createPages - 0.020s
info Total nodes: 64, SitePage nodes: 9 (use --verbose for breakdown)
success Checking for changed pages - 0.001s
success update schema - 0.081s
success onPreExtractQueries - 0.006s
success extract queries from components - 0.223s
success write out requires - 0.002s
success run page queries - 0.010s - 1/1 99.82/s
This works great if you are querying the main document or any referenced objects. However, if you are querying any references to another document then there is one gotcha you need to be aware of.
The Gotcha
When you use the _raw query in your GraphQL query, it will not trigger watch mode to reload the data. You need to explicitly query the referenced document in order for watch mode to work properly.
Example: This Query will NOT work
export const PageQuery = graphql`
fragment PageInfo on SanityPage {
_id
_key
_updatedAt
_rawContent(resolveReferences: {maxDepth: 10})
}
`
Example: This query WILL Work
export const PageQuery = graphql`
fragment PageInfo on SanityPage {
_id
_key
_updatedAt
_rawContent(resolveReferences: {maxDepth: 10})
content {
... on SanitySection {
id
}
}
}
`
This additional query is the key
Here is where I am explicitly querying the document that is being referenced in the 'content' array.
content {
... on SanitySection {
id
}
}
You don't actually need to use the data that results from that query, you simply need to include this in your query.
My guess is that this informs the gatsby-source-sanity plugin to set up a listener, whereas the _rawContent fragment does not.
Not sure if this is a feature, bug, or just expected behavior. At the time of writing the versions were as follows.
"gatsby": "3.5.1",
"gatsby-source-sanity": "^7.0.0",

Translations Service

I'm looking for a solution/idea to dynamically change the translation value of each key in Sparatcus translations files outside the code. I don't want only to create a file and override the I18nModule config, I'm looking for some kind of service/API like Lokalize API to be able to change the translation values outside the code.
Thanks in advance!
The internationalisation features are prepared for this. Although we do not have a service at hand for the localised labels, Spartacus is prepared for this. You can read more about this at https://sap.github.io/spartacus-docs/i18n/#lazy-loading. You can configure loadPath to an API endpoint, including the variable language (lng) and namespace (ns).
imports: [
B2cStorefrontModule.withConfig({
i18n: {
backend: {
loadPath: 'assets/i18n-assets/{{lng}}/{{ns}}.json'
// crossOrigin: true (use this option when i18n assets come from a different domain)
},
chunks: translationChunksConfig
}
})
];

intern.js How to test legacy non modular code

I'm using intern.js as a test framework to test dojo modules and it works well.
Now I have to test some non modular legacy code but I can't.
This is an example of a simple file to test:
var Component = function() {
this.itWorks = function() {
return true;
}
};
And this is the test
define([
'intern!object',
'intern/chai!assert',
'intern/order!controls/component',
], function (registerSuite, assert) {
registerSuite({
name: 'test legacy code',
'simple test': function () {
console.log(Component);
}
});
});
The test fails sayng that "Component is not defined".
I've notice that it works only if I write
window.Component = Component
At the bottom of file to test.
I can't modify all the file to test, is it possible to test the file in a different way?
This should work fine. One possible issue is where you're loading component from. The 'controls/component' dependency in 'intern/order!controls/component' is, barring any special loader config, relative to the file doing the loading. That means that if the project is setup like this:
project/
controls/
component.js
tests/
intern.js
componentTest.js
and component is being loaded from componentTest.js, then the dependency should be 'intern/order!../controls/component.js'. (It will actually work without the '../' in this case since controls is a top level directory in the project.)
Another potential issue is that a non-AMD identifier should use the .js suffix. This tells the loader that the thing being loaded is a generic script rather than an AMD module.
Also note that the order plugin is only needed to load multiple legacy files in a specific order. If order doesn't matter, or you're just loading one script, you can just use the script itself '../controls/component.js' as the dependency.
<"/"https://stackoverflow.com/tags" term="legacy" /">
<"/!-- begin snippet: js hide: false console: true babel: false --"/">
"var Component" = function() {
"this.itWorks" = function() {
return=true;
}
};
<"/"!-- end snippet --"/">

Change locale dynamically after plugin is applied

How can I change locale after the plugin has been applied?
Let say I have "en_US" locale assigned. Now I want to change it on runtime.
I tried to re-apply plugin to element:
$(element).formValidation({locale: 'es_ES',....});
But no effect. Any idea?
How can I refresh the view?
EDIT: 2015-06-18
Before you follow the solution bellow (step 1 & step 2 (option 3)), make sure that you downloaded the i18n add-on from here, this add-on will help you define messages in different languages.
Include it and then use it as following:
$(form).formValidation({
framework: '...',
icon: {
// ...
},
addOns: {
i18n: {}
},
fields: {
// ...
}
});
For more information, see http://formvalidation.io/addons/i18n/
This is how to solve your problem:
Include the language file es_ES.(min.)js after including formvalidation.(min.)js.
Set the locale:
Option 1: Use the locale option as you provided in your question.
Option 2: You can add the attribute data-fv-locale="es_ES" to your form.
Option 3: Use the setLocale method:
$('#yourFormId').formValidation('setLocale', 'es_ES');
NOTES:
the setLocale method is not documented, to see its usage see
the example here http://formvalidation.io/addons/i18n/.
Option 1 & 2 should be used before you initialize the plugin and without using the i18n add-on.
Option 3 after initialization.

Is it possible to load an aliased module?

I have a module "default/foo/bar" and a module "agency/foo/bar". I setup an alias to load the agency module instead of the default module. Yet I still want "agency/foo/bar" to load "default/foo/bar" but that's not possible because of the alias. Is there a way to accomplish this?
Here's actual snippets:
aliases: [
["gis/ol/config", "agency/ol/config"],
["aliased/gis/config", "gis/ol/config"]
],
Try to load the original module but it doesn't work..config is an Object:
define(["aliased/gis/config"], function (config) { // config is an object });
I find that using map instead of aliases is much clearer and easier to understand:
map: {
'*': {
'gis/ol/config': 'agency/ol/config'
},
'agency/ol/config': {
'gis/ol/config': 'gis/ol/config'
}
}
This configuration causes all modules to load 'agency/ol/config' in place of 'gis/ol/config', except for 'agency/ol/config' which will load 'gis/ol/config' as 'gis/ol/config'.