Themes: improve ability of 'rewrite' config
This commit is contained in:
parent
5da895276c
commit
f015604000
5 changed files with 335 additions and 161 deletions
322
src/Models/ThemeConfig/Conversion/ExpandRewrite.ts
Normal file
322
src/Models/ThemeConfig/Conversion/ExpandRewrite.ts
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
import { Conversion } from "./Conversion"
|
||||||
|
import RewritableConfigJson from "../Json/RewritableConfigJson"
|
||||||
|
import Translations from "../../../UI/i18n/Translations"
|
||||||
|
import { ConversionContext } from "./ConversionContext"
|
||||||
|
import { Utils } from "../../../Utils"
|
||||||
|
|
||||||
|
export class ExpandRewrite<T> extends Conversion<T | RewritableConfigJson<T>, T[]> {
|
||||||
|
constructor() {
|
||||||
|
super("Applies a rewrite", [], "ExpandRewrite")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for left|right group creation and replacement.
|
||||||
|
* Every 'keyToRewrite' will be replaced with 'target' recursively. This substitution will happen in place in the object 'tr'
|
||||||
|
*
|
||||||
|
* The 'target' object will be cloned, the changes will be applied in this clone
|
||||||
|
*
|
||||||
|
* // should substitute strings
|
||||||
|
* const spec = {
|
||||||
|
* "someKey": "somevalue {xyz}"
|
||||||
|
* }
|
||||||
|
* ExpandRewrite.RewriteParts("{xyz}", "rewritten", spec) // => {"someKey": "somevalue rewritten"}
|
||||||
|
*
|
||||||
|
* // should substitute all occurances in strings
|
||||||
|
* const spec = {
|
||||||
|
* "someKey": "The left|right side has {key:left|right}"
|
||||||
|
* }
|
||||||
|
* ExpandRewrite.RewriteParts("left|right", "left", spec) // => {"someKey": "The left side has {key:left}"}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static RewriteParts<T>(keyToRewrite: string, target: string | any, tr: T): T {
|
||||||
|
const targetIsTranslation = Translations.isProbablyATranslation(target)
|
||||||
|
|
||||||
|
function replaceRecursive(obj: string | any, target) {
|
||||||
|
if (obj === keyToRewrite) {
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof obj === "string") {
|
||||||
|
// This is a simple string - we do a simple replace
|
||||||
|
while (obj.indexOf(keyToRewrite) >= 0) {
|
||||||
|
obj = obj.replace(keyToRewrite, target)
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
// This is a list of items
|
||||||
|
return obj.map((o) => replaceRecursive(o, target))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof obj === "object") {
|
||||||
|
obj = { ...obj }
|
||||||
|
|
||||||
|
const isTr = targetIsTranslation && Translations.isProbablyATranslation(obj)
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
let subtarget = target
|
||||||
|
if (isTr && target[key] !== undefined) {
|
||||||
|
// The target is a translation AND the current object is a translation
|
||||||
|
// This means we should recursively replace with the translated value
|
||||||
|
subtarget = target[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
obj[key] = replaceRecursive(obj[key], subtarget)
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
return replaceRecursive(tr, target)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for check that a key is present in a string somewhere in the object
|
||||||
|
*
|
||||||
|
* // should substitute strings
|
||||||
|
* const spec = {
|
||||||
|
* "someKey": "somevalue {xyz}"
|
||||||
|
* }
|
||||||
|
* ExpandRewrite.contains("{xyz}", spec) // => true
|
||||||
|
* ExpandRewrite.contains("{abc}", spec) // => false
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static contains<T>(keyToRewrite: string, tr: T): boolean {
|
||||||
|
function findRecursive(obj: string | any): boolean {
|
||||||
|
if (obj === keyToRewrite) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof obj === "string") {
|
||||||
|
// This is a simple string - we do a simple replace
|
||||||
|
return obj.indexOf(keyToRewrite) >= 0
|
||||||
|
}
|
||||||
|
if (Array.isArray(obj)) {
|
||||||
|
// This is a list of items
|
||||||
|
return obj.some((o) => findRecursive(o))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof obj === "object") {
|
||||||
|
obj = { ...obj }
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
if (findRecursive(obj[key])) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return findRecursive(tr)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* // should convert simple strings
|
||||||
|
* const spec = <RewritableConfigJson<string>>{
|
||||||
|
* rewrite: {
|
||||||
|
* sourceString: ["xyz","abc"],
|
||||||
|
* into: [
|
||||||
|
* ["X", "A"],
|
||||||
|
* ["Y", "B"],
|
||||||
|
* ["Z", "C"]],
|
||||||
|
* },
|
||||||
|
* renderings: "The value of xyz is abc"
|
||||||
|
* }
|
||||||
|
* new ExpandRewrite().convertStrict(spec, ConversionContext.test()) // => ["The value of X is A", "The value of Y is B", "The value of Z is C"]
|
||||||
|
*
|
||||||
|
* // should rewrite with translations
|
||||||
|
* const spec = <RewritableConfigJson<any>>{
|
||||||
|
* rewrite: {
|
||||||
|
* sourceString: ["xyz","abc"],
|
||||||
|
* into: [
|
||||||
|
* ["X", {en: "value", nl: "waarde"}],
|
||||||
|
* ["Y", {en: "some other value", nl: "een andere waarde"}],
|
||||||
|
* },
|
||||||
|
* renderings: {en: "The value of xyz is abc", nl: "De waarde van xyz is abc"}
|
||||||
|
* }
|
||||||
|
* const expected = [
|
||||||
|
* {
|
||||||
|
* en: "The value of X is value",
|
||||||
|
* nl: "De waarde van X is waarde"
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* en: "The value of Y is some other value",
|
||||||
|
* nl: "De waarde van Y is een andere waarde"
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
* new ExpandRewrite().convertStrict(spec, ConversionContext.test()) // => expected
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* // should expand sublists
|
||||||
|
* const spec = <RewritableConfigJson<any>>{
|
||||||
|
* rewrite: {
|
||||||
|
* sourceString: ["{{key}}","{{values}}"],
|
||||||
|
* into: [
|
||||||
|
* ["a", [1,2,3] ],
|
||||||
|
* ["b", [42, 43] ],
|
||||||
|
* },
|
||||||
|
* subexpand: {"options": ["{{values}}"]},
|
||||||
|
* renderings: {question: "What are values for {{key}}?", options: [{if: "x={{values}}", then: "{{values}} is value" }] }
|
||||||
|
* }
|
||||||
|
* const expected = [
|
||||||
|
* {question: "What are values for a?",
|
||||||
|
* options: [{if: "x=1", then: "1 is value" },
|
||||||
|
* {if: "x=2", then: "2 is value" },
|
||||||
|
* {if: "x=3", then: "3 is value" }
|
||||||
|
* ] }
|
||||||
|
* {question: "What are values for b?", options: [
|
||||||
|
* {if: "x=42", then: "42 is value" },
|
||||||
|
* {if: "x=43", then: "43 is value" }
|
||||||
|
* ] }
|
||||||
|
* ]
|
||||||
|
* new ExpandRewrite().convertStrict(spec, ConversionContext.test()) // => expected
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* // should expand sublists if there is one
|
||||||
|
* const spec = <RewritableConfigJson<any>>{
|
||||||
|
* rewrite: {
|
||||||
|
* sourceString: ["{{key}}","{{values}}"],
|
||||||
|
* into: [
|
||||||
|
* ["a", [] ],
|
||||||
|
* ["b", [42, 43] ],
|
||||||
|
* ["c", null ],
|
||||||
|
* },
|
||||||
|
* subexpand: {"options": ["{{values}}"]},
|
||||||
|
* renderings: [
|
||||||
|
* {question: "What is {{key}}?", options: [{if: "x={{values}}", then: "{{values}} is value" }],
|
||||||
|
* {question: "How is {{key}}?", options: [{a: 5}, {b: 6}] },
|
||||||
|
* {question: "Why is {{key}}?" }
|
||||||
|
* ]
|
||||||
|
* }
|
||||||
|
* const expected = [
|
||||||
|
* {question: "What is a?",
|
||||||
|
* options: []},
|
||||||
|
* {question: "How is a?", options: [{a: 5}, {b: 6}] },
|
||||||
|
* {question: "Why is a?" },
|
||||||
|
* {question: "What is b?", options: [
|
||||||
|
* {if: "x=42", then: "42 is value" },
|
||||||
|
* {if: "x=43", then: "43 is value" }
|
||||||
|
* ] },
|
||||||
|
* {question: "How is b?", options: [{a: 5}, {b: 6}] },
|
||||||
|
* {question: "Why is b?" },
|
||||||
|
* {question: "What is c?"},
|
||||||
|
* {question: "How is c?", options: [{a: 5}, {b: 6}] },
|
||||||
|
* {question: "Why is c?" },
|
||||||
|
* ]
|
||||||
|
* new ExpandRewrite().convertStrict(spec, ConversionContext.test()) // => expected
|
||||||
|
*/
|
||||||
|
convert(json: T | RewritableConfigJson<T>, context: ConversionContext): T[] {
|
||||||
|
if (json === null || json === undefined) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json["rewrite"] === undefined) {
|
||||||
|
// not a rewrite
|
||||||
|
return [<T>json]
|
||||||
|
}
|
||||||
|
|
||||||
|
const rewrite = <RewritableConfigJson<T>>json
|
||||||
|
const keysToRewrite = rewrite.rewrite
|
||||||
|
const results: T[] = []
|
||||||
|
|
||||||
|
{
|
||||||
|
// sanity check: rewrite: ["xyz", "longer_xyz"] is not allowed as "longer_xyz" will never be triggered
|
||||||
|
for (let i = 0; i < keysToRewrite.sourceString.length; i++) {
|
||||||
|
const guard = keysToRewrite.sourceString[i]
|
||||||
|
for (let j = i + 1; j < keysToRewrite.sourceString.length; j++) {
|
||||||
|
const toRewrite = keysToRewrite.sourceString[j]
|
||||||
|
if (toRewrite.indexOf(guard) >= 0) {
|
||||||
|
context.err(
|
||||||
|
`sourcestring[${i}] is a substring of sourcestring[${j}]: ${guard} will be substituted away before ${toRewrite} is reached.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// sanity check: {rewrite: ["a", "b"] should have the right amount of 'intos' in every case
|
||||||
|
for (let i = 0; i < rewrite.rewrite.into.length; i++) {
|
||||||
|
const into = keysToRewrite.into[i]
|
||||||
|
if (into.length !== rewrite.rewrite.sourceString.length) {
|
||||||
|
context
|
||||||
|
.enters("into", i)
|
||||||
|
.err(
|
||||||
|
`Error in rewrite: there are ${rewrite.rewrite.sourceString.length} keys to rewrite, but entry ${i} has only ${into.length} values`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let renderings = Array.isArray(rewrite.renderings)
|
||||||
|
? rewrite.renderings
|
||||||
|
: [rewrite.renderings]
|
||||||
|
for (let i = 0; i < keysToRewrite.into.length; i++) {
|
||||||
|
let ts: T[] = <T[]>Utils.Clone(renderings)
|
||||||
|
for (const tx of ts) {
|
||||||
|
let t = <T>tx
|
||||||
|
const sourceKeysToIgnore: string[] = []
|
||||||
|
for (const listKey in rewrite.subexpand) {
|
||||||
|
const original = t[listKey]
|
||||||
|
if (!original) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const sourceKeys = rewrite.subexpand[listKey].filter((sk) =>
|
||||||
|
ExpandRewrite.contains(sk, original)
|
||||||
|
)
|
||||||
|
if (sourceKeys.length === 0) {
|
||||||
|
// no delete t[listKey] needed, fixed values we need to retain
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceKeys.length > 1) {
|
||||||
|
throw (
|
||||||
|
"Too much matching sourcekeys for sublist `" +
|
||||||
|
listKey +
|
||||||
|
"`: it matches all of " +
|
||||||
|
sourceKeys.join(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceKey = sourceKeys[0]
|
||||||
|
sourceKeysToIgnore.push(sourceKey)
|
||||||
|
const rw = rewrite.rewrite
|
||||||
|
const values = rw.into[i][rw.sourceString.indexOf(sourceKey)]
|
||||||
|
|
||||||
|
if (!values) {
|
||||||
|
delete t[listKey]
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (!Array.isArray(values)) {
|
||||||
|
throw (
|
||||||
|
"Sublist expansion of `" +
|
||||||
|
listKey +
|
||||||
|
"` failed: not an array to expand with:" +
|
||||||
|
JSON.stringify(values)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
t[listKey] = [].concat(
|
||||||
|
...values.map((v) => ExpandRewrite.RewriteParts(sourceKey, v, original))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < keysToRewrite.sourceString.length; j++) {
|
||||||
|
// The string that should be replaced everywhere in `t`
|
||||||
|
const key = keysToRewrite.sourceString[j]
|
||||||
|
if (sourceKeysToIgnore.indexOf(key) >= 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// The object that `key` should be replaced with
|
||||||
|
const target = keysToRewrite.into[i][j]
|
||||||
|
t = ExpandRewrite.RewriteParts(key, target, t)
|
||||||
|
}
|
||||||
|
results.push(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
import {
|
import {
|
||||||
Bypass,
|
|
||||||
Concat,
|
Concat,
|
||||||
Conversion,
|
Conversion,
|
||||||
DesugaringContext,
|
DesugaringContext,
|
||||||
|
@ -32,6 +31,7 @@ import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRende
|
||||||
import { ConfigMeta } from "../../../UI/Studio/configMeta"
|
import { ConfigMeta } from "../../../UI/Studio/configMeta"
|
||||||
import LineRenderingConfigJson from "../Json/LineRenderingConfigJson"
|
import LineRenderingConfigJson from "../Json/LineRenderingConfigJson"
|
||||||
import { ConversionContext } from "./ConversionContext"
|
import { ConversionContext } from "./ConversionContext"
|
||||||
|
import { ExpandRewrite } from "./ExpandRewrite"
|
||||||
|
|
||||||
class ExpandFilter extends DesugaringStep<LayerConfigJson> {
|
class ExpandFilter extends DesugaringStep<LayerConfigJson> {
|
||||||
private static readonly predefinedFilters = ExpandFilter.load_filters()
|
private static readonly predefinedFilters = ExpandFilter.load_filters()
|
||||||
|
@ -677,164 +677,6 @@ export class AddEditingElements extends DesugaringStep<LayerConfigJson> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExpandRewrite<T> extends Conversion<T | RewritableConfigJson<T>, T[]> {
|
|
||||||
constructor() {
|
|
||||||
super("Applies a rewrite", [], "ExpandRewrite")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for left|right group creation and replacement.
|
|
||||||
* Every 'keyToRewrite' will be replaced with 'target' recursively. This substitution will happen in place in the object 'tr'
|
|
||||||
*
|
|
||||||
* // should substitute strings
|
|
||||||
* const spec = {
|
|
||||||
* "someKey": "somevalue {xyz}"
|
|
||||||
* }
|
|
||||||
* ExpandRewrite.RewriteParts("{xyz}", "rewritten", spec) // => {"someKey": "somevalue rewritten"}
|
|
||||||
*
|
|
||||||
* // should substitute all occurances in strings
|
|
||||||
* const spec = {
|
|
||||||
* "someKey": "The left|right side has {key:left|right}"
|
|
||||||
* }
|
|
||||||
* ExpandRewrite.RewriteParts("left|right", "left", spec) // => {"someKey": "The left side has {key:left}"}
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static RewriteParts<T>(keyToRewrite: string, target: string | any, tr: T): T {
|
|
||||||
const targetIsTranslation = Translations.isProbablyATranslation(target)
|
|
||||||
|
|
||||||
function replaceRecursive(obj: string | any, target) {
|
|
||||||
if (obj === keyToRewrite) {
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof obj === "string") {
|
|
||||||
// This is a simple string - we do a simple replace
|
|
||||||
while (obj.indexOf(keyToRewrite) >= 0) {
|
|
||||||
obj = obj.replace(keyToRewrite, target)
|
|
||||||
}
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
if (Array.isArray(obj)) {
|
|
||||||
// This is a list of items
|
|
||||||
return obj.map((o) => replaceRecursive(o, target))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof obj === "object") {
|
|
||||||
obj = { ...obj }
|
|
||||||
|
|
||||||
const isTr = targetIsTranslation && Translations.isProbablyATranslation(obj)
|
|
||||||
|
|
||||||
for (const key in obj) {
|
|
||||||
let subtarget = target
|
|
||||||
if (isTr && target[key] !== undefined) {
|
|
||||||
// The target is a translation AND the current object is a translation
|
|
||||||
// This means we should recursively replace with the translated value
|
|
||||||
subtarget = target[key]
|
|
||||||
}
|
|
||||||
|
|
||||||
obj[key] = replaceRecursive(obj[key], subtarget)
|
|
||||||
}
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
|
|
||||||
return replaceRecursive(tr, target)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* // should convert simple strings
|
|
||||||
* const spec = <RewritableConfigJson<string>>{
|
|
||||||
* rewrite: {
|
|
||||||
* sourceString: ["xyz","abc"],
|
|
||||||
* into: [
|
|
||||||
* ["X", "A"],
|
|
||||||
* ["Y", "B"],
|
|
||||||
* ["Z", "C"]],
|
|
||||||
* },
|
|
||||||
* renderings: "The value of xyz is abc"
|
|
||||||
* }
|
|
||||||
* new ExpandRewrite().convertStrict(spec, ConversionContext.test()) // => ["The value of X is A", "The value of Y is B", "The value of Z is C"]
|
|
||||||
*
|
|
||||||
* // should rewrite with translations
|
|
||||||
* const spec = <RewritableConfigJson<any>>{
|
|
||||||
* rewrite: {
|
|
||||||
* sourceString: ["xyz","abc"],
|
|
||||||
* into: [
|
|
||||||
* ["X", {en: "value", nl: "waarde"}],
|
|
||||||
* ["Y", {en: "some other value", nl: "een andere waarde"}],
|
|
||||||
* },
|
|
||||||
* renderings: {en: "The value of xyz is abc", nl: "De waarde van xyz is abc"}
|
|
||||||
* }
|
|
||||||
* const expected = [
|
|
||||||
* {
|
|
||||||
* en: "The value of X is value",
|
|
||||||
* nl: "De waarde van X is waarde"
|
|
||||||
* },
|
|
||||||
* {
|
|
||||||
* en: "The value of Y is some other value",
|
|
||||||
* nl: "De waarde van Y is een andere waarde"
|
|
||||||
* }
|
|
||||||
* ]
|
|
||||||
* new ExpandRewrite().convertStrict(spec, ConversionContext.test()) // => expected
|
|
||||||
*/
|
|
||||||
convert(json: T | RewritableConfigJson<T>, context: ConversionContext): T[] {
|
|
||||||
if (json === null || json === undefined) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json["rewrite"] === undefined) {
|
|
||||||
// not a rewrite
|
|
||||||
return [<T>json]
|
|
||||||
}
|
|
||||||
|
|
||||||
const rewrite = <RewritableConfigJson<T>>json
|
|
||||||
const keysToRewrite = rewrite.rewrite
|
|
||||||
const ts: T[] = []
|
|
||||||
|
|
||||||
{
|
|
||||||
// sanity check: rewrite: ["xyz", "longer_xyz"] is not allowed as "longer_xyz" will never be triggered
|
|
||||||
for (let i = 0; i < keysToRewrite.sourceString.length; i++) {
|
|
||||||
const guard = keysToRewrite.sourceString[i]
|
|
||||||
for (let j = i + 1; j < keysToRewrite.sourceString.length; j++) {
|
|
||||||
const toRewrite = keysToRewrite.sourceString[j]
|
|
||||||
if (toRewrite.indexOf(guard) >= 0) {
|
|
||||||
context.err(
|
|
||||||
`sourcestring[${i}] is a substring of sourcestring[${j}]: ${guard} will be substituted away before ${toRewrite} is reached.`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// sanity check: {rewrite: ["a", "b"] should have the right amount of 'intos' in every case
|
|
||||||
for (let i = 0; i < rewrite.rewrite.into.length; i++) {
|
|
||||||
const into = keysToRewrite.into[i]
|
|
||||||
if (into.length !== rewrite.rewrite.sourceString.length) {
|
|
||||||
context
|
|
||||||
.enters("into", i)
|
|
||||||
.err(
|
|
||||||
`Error in rewrite: there are ${rewrite.rewrite.sourceString.length} keys to rewrite, but entry ${i} has only ${into.length} values`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < keysToRewrite.into.length; i++) {
|
|
||||||
let t = Utils.Clone(rewrite.renderings)
|
|
||||||
for (let j = 0; j < keysToRewrite.sourceString.length; j++) {
|
|
||||||
const key = keysToRewrite.sourceString[j]
|
|
||||||
const target = keysToRewrite.into[i][j]
|
|
||||||
t = ExpandRewrite.RewriteParts(key, target, t)
|
|
||||||
}
|
|
||||||
ts.push(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a 'special' translation into a regular translation which uses parameters
|
* Converts a 'special' translation into a regular translation which uses parameters
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { Utils } from "../../../Utils"
|
||||||
import SpecialVisualizations from "../../../UI/SpecialVisualizations"
|
import SpecialVisualizations from "../../../UI/SpecialVisualizations"
|
||||||
import { RenderingSpecification, SpecialVisualization } from "../../../UI/SpecialVisualization"
|
import { RenderingSpecification, SpecialVisualization } from "../../../UI/SpecialVisualization"
|
||||||
import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson"
|
import { QuestionableTagRenderingConfigJson } from "../Json/QuestionableTagRenderingConfigJson"
|
||||||
|
import { render } from "sass"
|
||||||
|
|
||||||
export default class ValidationUtils {
|
export default class ValidationUtils {
|
||||||
public static getAllSpecialVisualisations(
|
public static getAllSpecialVisualisations(
|
||||||
|
@ -43,6 +44,14 @@ export default class ValidationUtils {
|
||||||
if (renderingConfig[cacheName]) {
|
if (renderingConfig[cacheName]) {
|
||||||
return renderingConfig[cacheName]
|
return renderingConfig[cacheName]
|
||||||
}
|
}
|
||||||
|
if (!Array.isArray(renderingConfig.mappings ?? [])) {
|
||||||
|
throw (
|
||||||
|
"Mappings of renderingconfig " +
|
||||||
|
(renderingConfig["id"] ?? renderingConfig.render ?? "") +
|
||||||
|
" are supposed to be an array but it is: " +
|
||||||
|
JSON.stringify(renderingConfig.mappings)
|
||||||
|
)
|
||||||
|
}
|
||||||
const translations: any[] = Utils.NoNull([
|
const translations: any[] = Utils.NoNull([
|
||||||
renderingConfig.render,
|
renderingConfig.render,
|
||||||
...(renderingConfig.mappings ?? []).map((m) => m.then),
|
...(renderingConfig.mappings ?? []).map((m) => m.then),
|
||||||
|
|
|
@ -47,5 +47,6 @@ export default interface RewritableConfigJson<T> {
|
||||||
sourceString: string[]
|
sourceString: string[]
|
||||||
into: (string | any)[][]
|
into: (string | any)[][]
|
||||||
}
|
}
|
||||||
renderings: T
|
subexpand?: Record<string, string[]>
|
||||||
|
renderings: T | T[]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { LayerConfigJson } from "../../../../src/Models/ThemeConfig/Json/LayerConfigJson"
|
import { LayerConfigJson } from "../../../../src/Models/ThemeConfig/Json/LayerConfigJson"
|
||||||
import LineRenderingConfigJson from "../../../../src/Models/ThemeConfig/Json/LineRenderingConfigJson"
|
import LineRenderingConfigJson from "../../../../src/Models/ThemeConfig/Json/LineRenderingConfigJson"
|
||||||
import {
|
import {
|
||||||
ExpandRewrite,
|
|
||||||
PrepareLayer,
|
PrepareLayer,
|
||||||
RewriteSpecial,
|
RewriteSpecial,
|
||||||
} from "../../../../src/Models/ThemeConfig/Conversion/PrepareLayer"
|
} from "../../../../src/Models/ThemeConfig/Conversion/PrepareLayer"
|
||||||
|
@ -10,6 +9,7 @@ import RewritableConfigJson from "../../../../src/Models/ThemeConfig/Json/Rewrit
|
||||||
import { describe, expect, it } from "vitest"
|
import { describe, expect, it } from "vitest"
|
||||||
|
|
||||||
import { ConversionContext } from "../../../../src/Models/ThemeConfig/Conversion/ConversionContext"
|
import { ConversionContext } from "../../../../src/Models/ThemeConfig/Conversion/ConversionContext"
|
||||||
|
import { ExpandRewrite } from "../../../../src/Models/ThemeConfig/Conversion/ExpandRewrite"
|
||||||
|
|
||||||
describe("ExpandRewrite", () => {
|
describe("ExpandRewrite", () => {
|
||||||
it("should not allow overlapping keys", () => {
|
it("should not allow overlapping keys", () => {
|
||||||
|
|
Loading…
Reference in a new issue