mirror of
https://github.com/zadam/trilium.git
synced 2026-01-07 16:02:13 +01:00
chore(nx): move all monorepo-style in subfolder for processing
This commit is contained in:
@@ -1,230 +0,0 @@
|
||||
import type { AttributeType, FAttributeRow } from "../entities/fattribute.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
interface Token {
|
||||
text: string;
|
||||
startIndex: number;
|
||||
endIndex: number;
|
||||
}
|
||||
|
||||
export interface Attribute {
|
||||
attributeId?: string;
|
||||
type: AttributeType;
|
||||
name: string;
|
||||
isInheritable?: boolean;
|
||||
value?: string;
|
||||
startIndex?: number;
|
||||
endIndex?: number;
|
||||
noteId?: string;
|
||||
}
|
||||
|
||||
function lex(str: string) {
|
||||
str = str.trim();
|
||||
|
||||
const tokens: Token[] = [];
|
||||
|
||||
let quotes: boolean | string = false;
|
||||
let currentWord = "";
|
||||
|
||||
function isOperatorSymbol(chr: string) {
|
||||
return ["=", "*", ">", "<", "!"].includes(chr);
|
||||
}
|
||||
|
||||
function previousOperatorSymbol() {
|
||||
if (currentWord.length === 0) {
|
||||
return false;
|
||||
} else {
|
||||
return isOperatorSymbol(currentWord[currentWord.length - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param endIndex - index of the last character of the token
|
||||
*/
|
||||
function finishWord(endIndex: number) {
|
||||
if (currentWord === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
tokens.push({
|
||||
text: currentWord,
|
||||
startIndex: endIndex - currentWord.length + 1,
|
||||
endIndex: endIndex
|
||||
});
|
||||
|
||||
currentWord = "";
|
||||
}
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const chr = str[i];
|
||||
|
||||
if (chr === "\\") {
|
||||
if (i + 1 < str.length) {
|
||||
i++;
|
||||
|
||||
currentWord += str[i];
|
||||
} else {
|
||||
currentWord += chr;
|
||||
}
|
||||
|
||||
continue;
|
||||
} else if (['"', "'", "`"].includes(chr)) {
|
||||
if (!quotes) {
|
||||
if (previousOperatorSymbol()) {
|
||||
finishWord(i - 1);
|
||||
}
|
||||
|
||||
quotes = chr;
|
||||
} else if (quotes === chr) {
|
||||
quotes = false;
|
||||
|
||||
finishWord(i - 1);
|
||||
} else {
|
||||
// it's a quote, but within other kind of quotes, so it's valid as a literal character
|
||||
currentWord += chr;
|
||||
}
|
||||
continue;
|
||||
} else if (!quotes) {
|
||||
if (currentWord.length === 0 && (chr === "#" || chr === "~")) {
|
||||
currentWord = chr;
|
||||
|
||||
continue;
|
||||
} else if (chr === " ") {
|
||||
finishWord(i - 1);
|
||||
continue;
|
||||
} else if (["(", ")"].includes(chr)) {
|
||||
finishWord(i - 1);
|
||||
|
||||
currentWord = chr;
|
||||
|
||||
finishWord(i);
|
||||
|
||||
continue;
|
||||
} else if (previousOperatorSymbol() !== isOperatorSymbol(chr)) {
|
||||
finishWord(i - 1);
|
||||
|
||||
currentWord += chr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
currentWord += chr;
|
||||
}
|
||||
|
||||
finishWord(str.length - 1);
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
function checkAttributeName(attrName: string) {
|
||||
if (attrName.length === 0) {
|
||||
throw new Error("Attribute name is empty, please fill the name.");
|
||||
}
|
||||
|
||||
if (!utils.isValidAttributeName(attrName)) {
|
||||
throw new Error(`Attribute name "${attrName}" contains disallowed characters, only alphanumeric characters, colon and underscore are allowed.`);
|
||||
}
|
||||
}
|
||||
|
||||
function parse(tokens: Token[], str: string, allowEmptyRelations = false) {
|
||||
const attrs: Attribute[] = [];
|
||||
|
||||
function context(i: number) {
|
||||
let { startIndex, endIndex } = tokens[i];
|
||||
startIndex = Math.max(0, startIndex - 20);
|
||||
endIndex = Math.min(str.length, endIndex + 20);
|
||||
|
||||
return `"${startIndex !== 0 ? "..." : ""}${str.substr(startIndex, endIndex - startIndex)}${endIndex !== str.length ? "..." : ""}"`;
|
||||
}
|
||||
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
const { text, startIndex } = tokens[i];
|
||||
|
||||
function isInheritable() {
|
||||
if (tokens.length > i + 3 && tokens[i + 1].text === "(" && tokens[i + 2].text === "inheritable" && tokens[i + 3].text === ")") {
|
||||
i += 3;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (text.startsWith("#")) {
|
||||
const labelName = text.substr(1);
|
||||
|
||||
checkAttributeName(labelName);
|
||||
|
||||
const attr: Attribute = {
|
||||
type: "label",
|
||||
name: labelName,
|
||||
isInheritable: isInheritable(),
|
||||
startIndex: startIndex,
|
||||
endIndex: tokens[i].endIndex // i could be moved by isInheritable
|
||||
};
|
||||
|
||||
if (i + 1 < tokens.length && tokens[i + 1].text === "=") {
|
||||
if (i + 2 >= tokens.length) {
|
||||
throw new Error(`Missing value for label "${text}" in ${context(i)}`);
|
||||
}
|
||||
|
||||
i += 2;
|
||||
|
||||
attr.value = tokens[i].text;
|
||||
attr.endIndex = tokens[i].endIndex;
|
||||
}
|
||||
|
||||
attrs.push(attr);
|
||||
} else if (text.startsWith("~")) {
|
||||
const relationName = text.substr(1);
|
||||
|
||||
checkAttributeName(relationName);
|
||||
|
||||
const attr: Attribute = {
|
||||
type: "relation",
|
||||
name: relationName,
|
||||
isInheritable: isInheritable(),
|
||||
startIndex: startIndex,
|
||||
endIndex: tokens[i].endIndex // i could be moved by isInheritable
|
||||
};
|
||||
|
||||
attrs.push(attr);
|
||||
|
||||
if (i + 2 >= tokens.length || tokens[i + 1].text !== "=") {
|
||||
if (allowEmptyRelations) {
|
||||
break;
|
||||
} else {
|
||||
throw new Error(`Relation "${text}" in ${context(i)} should point to a note.`);
|
||||
}
|
||||
}
|
||||
|
||||
i += 2;
|
||||
|
||||
let notePath = tokens[i].text;
|
||||
if (notePath.startsWith("#")) {
|
||||
notePath = notePath.substr(1);
|
||||
}
|
||||
|
||||
const noteId = notePath.split("/").pop();
|
||||
|
||||
attr.value = noteId;
|
||||
attr.endIndex = tokens[i].endIndex;
|
||||
} else {
|
||||
throw new Error(`Invalid attribute "${text}" in ${context(i)}`);
|
||||
}
|
||||
}
|
||||
|
||||
return attrs;
|
||||
}
|
||||
|
||||
function lexAndParse(str: string, allowEmptyRelations = false) {
|
||||
const tokens = lex(str);
|
||||
|
||||
return parse(tokens, str, allowEmptyRelations);
|
||||
}
|
||||
|
||||
export default {
|
||||
lex,
|
||||
parse,
|
||||
lexAndParse
|
||||
};
|
||||
Reference in New Issue
Block a user