All files / owid-grapher/gridLang GridLangConstants.ts

100% Statements 126/126
100% Branches 3/3
66.67% Functions 2/3
100% Lines 126/126

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 1851x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                                                                                      
export const CellHasErrorsClass = "CellHasErrorsClass"
 
export enum GridBoolean {
    true = "true",
    false = "false",
}
 
export const GRID_NODE_DELIMITER = "\n"
export const GRID_CELL_DELIMITER = "\t"
export const GRID_EDGE_DELIMITER = "\t"
 
export type CellCoordinate = number // An integer >= 0
 
export type Grammar = { [keywordSlug: string]: CellDef }
 
// A CellDef is a tuple: part keyword and the other half is the contents. The contents can be 1 cell, a list of cells, and/or a subtable.
export interface CellDef {
    keyword: string
    cssClass: string
    description: string
    grammar?: Grammar
    headerCellDef?: CellDef
    terminalOptions?: CellDef[]
    catchAllCellDef?: CellDef // Only used by vertical grammars, this cell def, if present, will be used if a keyword is unrecognized during parsing.
    regex?: RegExp // A validation regex a value must pass. todo: seems like this is overloaded and used for testing keywords and contents.
    requirementsDescription?: string
    valuePlaceholder?: string
    positionalCellDefs?: readonly CellDef[] // Additional cell types as positional arguments.
    isHorizontalList?: boolean // a list type, such as "colors\tred\torange\tgreen"
    parse?: (value: any) => any
}
 
export interface ParsedCell {
    errorMessage?: string
    cssClasses?: string[]
    optionKeywords?: string[]
    comment?: string
    cellDef?: CellDef
    placeholder?: string
    contents?: any
}
 
export interface CellPosition {
    row: CellCoordinate
    column: CellCoordinate
}
 
export const Origin: CellPosition = {
    row: 0,
    column: 0,
}
 
export const BooleanCellDef: CellDef = {
    keyword: "",
    terminalOptions: [
        { keyword: GridBoolean.true, cssClass: "", description: "" },
        { keyword: GridBoolean.false, cssClass: "", description: "" },
    ],
    cssClass: "BooleanCellDef",
    description: "Boolean",
    parse: (value: any) => value === GridBoolean.true,
}
 
export const StringCellDef: CellDef = {
    keyword: "",
    cssClass: "StringCellDef",
    description: "",
}
 
export const StringDeclarationDef: CellDef = {
    keyword: "",
    cssClass: "StringDeclarationDef",
    description: "",
}
 
export const EnumCellDef: CellDef = {
    keyword: "",
    cssClass: "EnumCellDef",
    description: "",
}
 
export const RootKeywordCellDef: CellDef = {
    keyword: "",
    cssClass: "KeywordCellDef",
    description: "Keyword",
}
 
export const NumericCellDef: CellDef = {
    keyword: "",
    cssClass: "NumericCellDef",
    description: "",
    regex: /^-?\d+\.?\d*$/,
    requirementsDescription: `Must be a number`,
    valuePlaceholder: "98.6",
    parse: (value: any) => parseFloat(value),
}
 
export const IntegerCellDef: CellDef = {
    keyword: "",
    cssClass: "IntegerCellDef",
    description: "",
    regex: /^[0-9]+$/,
    requirementsDescription: `Must be an integer`,
    valuePlaceholder: "12345",
    parse: (value: any) => parseInt(value),
}
 
export const SubTableHeaderCellDef: CellDef = {
    keyword: "",
    cssClass: "SubTableHeaderCellDef",
    description: "",
}
 
export const SubTableValueCellDef: CellDef = {
    keyword: "",
    cssClass: "SubTableValueCellDef",
    description: "",
}
 
const MatchUrlsOnlyRegex =
    /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/
 
export const UrlCellDef: CellDef = {
    keyword: "",
    cssClass: "UrlCellDef",
    description: "",
    regex: MatchUrlsOnlyRegex,
}
 
export const QueryStringCellDef: CellDef = {
    keyword: "",
    cssClass: "QueryStringCellDef",
    description: "",
}
 
export const NothingGoesThereCellDef: CellDef = {
    keyword: "",
    cssClass: "NothingGoesThereType",
    description:
        "Nothing should be here. You can make this a comment by prepending a ##",
}
 
export const CommentCellDef: CellDef = {
    keyword: "",
    cssClass: "CommentType",
    description: "Just a comment.",
    regex: /^(\#\#|💬)/,
}
 
export const WorkInProgressCellDef: CellDef = {
    keyword: "",
    cssClass: "WorkInProgressCellDef",
    description: "Not a recognized statement. Treating as a work in progress.",
}
 
export const SlugDeclarationCellDef: CellDef = {
    keyword: "",
    cssClass: "SlugDeclarationType",
    description: "A unique URL-friendly name.",
    regex: /^[a-zA-Z0-9-_]+$/,
    requirementsDescription: `Can only contain the characters a-zA-Z0-9-_`,
}
 
// This is the name for a cell that is on the "frontier", where the next user input is expected to go. Okay to rename if you have a better word.
export const FrontierCellClass = "ShowDropdownArrow"
 
export const SlugsDeclarationCellDef: CellDef = {
    keyword: "",
    cssClass: "SlugDeclarationType",
    description: "Unique URL-friendly names.",
    regex: /^[a-zA-Z0-9-_ ]+$/,
    requirementsDescription: `Can only contain the characters a-zA-Z0-9-_ `,
}
 
export const JSONObjectCellDef: CellDef = {
    keyword: "",
    cssClass: "JSONObjectCellDef",
    description: "JSON object",
    regex: /^\{.*\}$/, // very basic validation that expression starts with { and ends with }
    requirementsDescription: "Must contain a valid JSON object",
}
 
export type MatrixLine = string[]
export type MatrixProgram = MatrixLine[]