diff --git a/README.es.md b/README.es.md index 40715ff..9b440d8 100644 --- a/README.es.md +++ b/README.es.md @@ -40,7 +40,7 @@ Este plugin se puede instalar desde Obsidian. - [ ] Consultas inline de la respuesta de una solicitud - [ ] Solicitudes predefinidas - [ ] GUI para bloques de código -- [ ] Traducir la documentación +- [x] Traducir la documentación ## ❤️ Patrocinadores diff --git a/README.md b/README.md index d0bd592..68db906 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ The plugin can be installed from within Obsidian. - [ ] Inline query from response - [ ] Predefined requests - [ ] GUI for code-blocks -- [ ] Translate documentation +- [x] Translate documentation ## ❤️ Sponsors diff --git a/docs/docs/en/codeblocks.md b/docs/docs/en/codeblocks.md index 0e2a7d0..c6d7191 100644 --- a/docs/docs/en/codeblocks.md +++ b/docs/docs/en/codeblocks.md @@ -6,21 +6,20 @@ The `codeblock` is a versatile block that can be used to write code in different Flags are the way to specify the parameters of our request and also the format in which we want our response. -| Flag | Default| -| ---| ---------| -| url | | -| method | GET | -| body | | -| headers | | -| show | ALL | -| format | `{}` | -| res-type | json | -| req-id | req-general | -| disabled | | -| req-repeat | 1t@1s | -| notify-if | | -| save-to | | -| properties | | +| Flag | Default | +| ------------| ---------| +| [url](#url) | | +| [method](#method) | GET | +| [body](#body) | | +| [headers](#headers) | | +| [show](#show) | ALL | +| [format](#format) | `{}` | +| [req-id](#req-id) | req-general | +| [disabled](#disabled) | | +| [req-repeat](#req-repeat) | 1t@1s | +| [notify-if](#notify-if) | | +| [save-to](#save-to) | | +| [properties](#properties) | | ### url @@ -140,24 +139,6 @@ format:
{}
!!! note "In this example, first `{}` will be replaced by the title, and second `{}` will be replaced by the body." -### res-type - -Specifies the type of response we are getting. The default value is `json`. The available values are: - -- json -- other - -When the response type is `other`, the response will be displayed as is. If the response is markdown, it will be rendered as markdown, if it's a raw text, it will be displayed as a text, and so on. - -!!! danger "Be carefull with `html` responses, it can break the page." - -~~~markdown -```req -url: https://raw.githubusercontent.com/Rooyca/Rooyca/main/README.md -res-type: other -``` -~~~ - ### req-id Specifies the id of the request. The default value is `req-general`. This is useful when we want to store the response in `localStorage` and use it in other blocks or notes. diff --git a/docs/docs/es/codeblocks.md b/docs/docs/es/codeblocks.md index 5cbddd1..f9a56dd 100644 --- a/docs/docs/es/codeblocks.md +++ b/docs/docs/es/codeblocks.md @@ -7,19 +7,19 @@ El `bloque de código` es un bloque versátil que se puede usar para escribir c Las banderas son la forma de especificar los parámetros de nuestra solicitud y también el formato en el que queremos nuestra respuesta. | Bandera | Valor predeterminado | -| --- | --------- | -| url | | -| method | GET | -| body | | -| headers | | -| show | ALL | -| format | `{}` | -| res-type | json | -| req-id | req-general | -| disabled | | -| req-repeat | 1t@1s | -| notify-if | | -| save-to | | +| ------------| ---------| +| [url](#url) | | +| [method](#method) | GET | +| [body](#body) | | +| [headers](#headers) | | +| [show](#show) | ALL | +| [format](#format) | `{}` | +| [req-id](#req-id) | req-general | +| [disabled](#disabled) | | +| [req-repeat](#req-repeat) | 1t@1s | +| [notify-if](#notify-if) | | +| [save-to](#save-to) | | +| [properties](#properties) | | ### url @@ -138,25 +138,6 @@ format:{}
!!! note "En este ejemplo, primero `{}` será reemplazado por el título, y segundo `{}` será reemplazado por el cuerpo." - -### res-type - -Especifica el tipo de respuesta que estamos obteniendo. El valor predeterminado es `json`. Los valores disponibles son: - -- json -- other - -Cuando el tipo de respuesta es `other`, la respuesta se mostrará tal como **está**; si es markdown, se renderizará como markdown, si es un texto, se mostrará como texto, y así sucesivamente. - -!!! danger "Ten cuidado con las respuestas `html`, pueden romper la página." - -~~~markdown -```req -url: https://raw.githubusercontent.com/Rooyca/Rooyca/main/README.md -res-type: other -``` -~~~ - ### req-id Especifica el ID con la que se almacenará la solicitud. El valor predeterminado es `req-general`. Esto es útil cuando queremos almacenar la respuesta en `localStorage` y usarla en otros bloques o notas. diff --git a/src/functions.ts b/src/functions.ts index 57590d9..091df01 100644 --- a/src/functions.ts +++ b/src/functions.ts @@ -1,51 +1,53 @@ +import { Notice, requestUrl, Editor } from 'obsidian'; + // Saves the response to the localStorage -export function saveToID(reqID: any, reqText: any) { +export function saveToID(reqID: string, reqText: string) { localStorage.setItem(reqID, reqText); } // Adds the copy button to the code block // Take from: https://github.com/jdbrice/obsidian-code-block-copy/ -export function addBtnCopy(el: any, copyThis: string) { - const btnCopy = el.createEl("button", {cls: "copy-req", text: "copy"}); +export function addBtnCopy(el: HTMLElement, copyThis: string) { + const btnCopy = el.createEl("button", { cls: "copy-req", text: "copy" }); btnCopy.addEventListener('click', function () { - navigator.clipboard.writeText(copyThis).then(function () { - btnCopy.blur(); - btnCopy.innerText = 'copied!'; - setTimeout(function () { - btnCopy.innerText = 'copy'; - }, 2000); - }, function (error) { - btnCopy.innerText = 'Error'; - }); + navigator.clipboard.writeText(copyThis).then(function () { + btnCopy.blur(); + btnCopy.innerText = 'copied!'; + setTimeout(function () { + btnCopy.innerText = 'copy'; + }, 2000); + }, function () { + btnCopy.innerText = 'Error'; + }); }); } // When more than one {} is defined in "format" // it will loop through the responses and replace the {} with the respective value -export function replaceOrder(stri, val) { - let index = 0; - let replaced = stri.replace(/{}/g, function(match) { - return val[index++]; - }); +export function replaceOrder(stri: string, val: []) { + let index = 0; + let replaced = stri.replace(/{}/g, function () { + return val[index++]; + }); - while (val.length > index) { - if (val[index] === undefined) break; - replaced += "\n"+stri.replace(/{}/g, val[index++]); - } + while (val.length > index) { + if (val[index] === undefined) break; + replaced += "\n" + stri.replace(/{}/g, val[index++]); + } - return replaced; + return replaced; } // Check if the user wants a nested response // In other words, if "->" is present in "show" -export function nestedValue(data: any, key: string) { +export function nestedValue(data, key: string) { const keySplit: string[] = key.split("->").map((item) => item.trim()); - var value: any = ""; - for (let i: number = 0; i < keySplit.length; i++) { + let value = ""; + for (let i = 0; i < keySplit.length; i++) { if (i === 0) { value = data.json[keySplit[i]]; - } else { - value = value[keySplit[i]]; + } else { + value = value[keySplit[i]]; } } @@ -59,32 +61,31 @@ export function nestedValue(data: any, key: string) { // Paste the response to the editor export function toDocument(settings: any, editor: Editor) { requestUrl({ - url: settings.URL, - method: settings.MethodRequest, - body: settings.DataRequest, + url: settings.URL, + method: settings.MethodRequest, + body: settings.DataRequest, }) - .then((data) => { - if (settings.DataResponse !== "") { - const DataResponseArray = settings.DataResponse.split(","); - for (let i = 0; i < DataResponseArray.length; i++) { - const key = DataResponseArray[i].trim(); + .then((data) => { + if (settings.DataResponse !== "") { + const DataResponseArray = settings.DataResponse.split(","); + for (let i = 0; i < DataResponseArray.length; i++) { + const key = DataResponseArray[i].trim(); - var value = JSON.stringify(data.json[key]); + let value = JSON.stringify(data.json[key]); - if (key.includes("->")) { - value = nestedValue(data, key); - value = JSON.stringify(value); - } + if (key.includes("->")) { + value = nestedValue(data, key); + value = JSON.stringify(value); + } - editor.replaceSelection("```markdown\n" + `${key.split("->").pop()} : ${value}\n` + "```\n\n"); - } - } else { - console.log(data.text) - editor.replaceSelection("\n" + `${data.text}\n` + "\n");
- }
- })
- .catch((error: Error) => {
- console.error(error);
- new Notice("Error: " + error.message);
- });
+ editor.replaceSelection("```markdown\n" + `${key.split("->").pop()} : ${value}\n` + "```\n\n");
+ }
+ } else {
+ editor.replaceSelection("\n" + `${data.text}\n` + "\n");
+ }
+ })
+ .catch((error: Error) => {
+ console.error(error);
+ new Notice("Error: " + error.message);
+ });
}
\ No newline at end of file
diff --git a/src/main.ts b/src/main.ts
index dd432f5..95c8265 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,7 +1,7 @@
-import { App, Editor, MarkdownView, Modal, Plugin, PluginSettingTab, Setting, Notice } from 'obsidian';
+import { App, Editor, MarkdownView, Modal, Plugin, PluginSettingTab, Setting, Notice, requestUrl } from 'obsidian';
import { readFrontmatter, parseFrontmatter } from './frontmatterUtils';
import { MarkdownParser } from './mdparse';
-import { checkFrontmatter, saveToID, addBtnCopy, replaceOrder, nestedValue, toDocument } from './functions';
+import { saveToID, addBtnCopy, replaceOrder, nestedValue, toDocument } from './functions';
import { num_braces_regx, num_hyphen_regx, nums_rex, in_braces_regx, varname_regx, no_varname_regx } from './regx';
const parser = new MarkdownParser();
@@ -12,8 +12,9 @@ interface LoadAPIRSettings {
DataRequest: string;
HeaderRequest: string;
DataResponse: string;
- URLs: string[];
+ URLs: object[];
Name: string;
+ DisabledReq: string;
}
const DEFAULT_SETTINGS: LoadAPIRSettings = {
@@ -24,6 +25,7 @@ const DEFAULT_SETTINGS: LoadAPIRSettings = {
DataResponse: '',
URLs: [],
Name: '',
+ DisabledReq: 'This request is disabled',
}
// Checks if the frontmatter is present in the request property
@@ -52,10 +54,10 @@ export function checkFrontmatter(req_prop: string) {
console.error(e.message);
new Notice("Error: " + e.message);
return;
- }
}
}
- return req_prop;
+ }
+ return req_prop;
}
export default class MainAPIR extends Plugin {
@@ -74,238 +76,270 @@ export default class MainAPIR extends Plugin {
});
try {
- this.registerMarkdownCodeBlockProcessor("req", async (source, el, ctx) => {
- const sourceLines = source.split("\n");
- let method = "GET", allowedMethods = ["GET", "POST", "PUT", "DELETE"], URL = "", show = "",
- headers = {}, body = {}, format = "{}", responseType = "json", responseAllow = ["json", "other"], reqID = "req-general",
- reqRepeat = { "times": 1, "every": 1000 }, notifyIf = "", saveTo = "", properties = "";
+ this.registerMarkdownCodeBlockProcessor("req", async (source, el, ctx) => {
+ const sourceLines = source.split("\n");
+ let [URL, show, saveTo, reqID] = [String(), String(), String(), String()];
+ let [notifyIf, properties] = [[String()], [String()]];
+ // 'format' is not and empty objet, is a string that will be replaced by the response
+ let [method, format] = ["GET", "{}"];
+ let [headers, body, reqRepeat] = [Object(), Object(), { "times": 1, "every": 1000 }];
+ const allowedMethods = ["GET", "POST", "PUT", "DELETE"];
- for (const line of sourceLines) {
- const lowercaseLine = line.toLowerCase();
- if (lowercaseLine.includes("method:")) {
- method = line.replace(/method:/i, "").toUpperCase();
- method = method.trim();
- if (!allowedMethods.includes(method)) {
- el.createEl("strong", { text: `Error: Method ${method} not supported` });
- return;
- }
- } else if (lowercaseLine.includes("notify-if:")) {
- notifyIf = line.replace(/notify-if:/i, "");
- notifyIf = notifyIf.split(" ");
- } else if (lowercaseLine.includes("req-repeat:")) {
- let repeat_values = line.replace(/req-repeat:/i, "");
- repeat_values = repeat_values.split("@");
-
- // check if there are two values and they are numbers
- if (repeat_values.length === 2 && !isNaN(repeat_values[0]) && !isNaN(repeat_values[1])) {
- reqRepeat = {"times": parseInt(repeat_values[0]), "every": parseInt(repeat_values[1])*1000};
- } else {
- el.createEl("strong", { text: "Error: req-repeat format is not valid (use Nt@Ns)" });
+ for (const line of sourceLines) {
+ const lowercaseLine = line.toLowerCase();
+ if (lowercaseLine.includes("method:")) {
+ method = line.replace(/method:/i, "").toUpperCase();
+ method = method.trim();
+ if (!allowedMethods.includes(method)) {
+ el.createEl("strong", { text: `Error: Method ${method} not supported` });
return;
}
- } else if (lowercaseLine.includes("url:")) {
- URL = checkFrontmatter(line.replace(/url:/i, ""));
- if (!URL.includes("http")) {
- URL = "https://" + URL;
- }
- } else if (lowercaseLine.includes("res-type:")) {
- responseType = line.replace(/res-type:/i, "").toLowerCase();
- responseType = responseType.trim();
- if (!responseAllow.includes(responseType)) {
- el.createEl("strong", { text: `Error: Response type ${responseType} not supported` });
- return;
- }
- } else if (lowercaseLine.includes("show:")) {
- show = line.replace(/show:/i, "");
- } else if (lowercaseLine.includes("headers:")) {
- headers = JSON.parse(checkFrontmatter(line.replace(/headers:/i, "")));
- } else if (lowercaseLine.includes("body:")) {
- body = checkFrontmatter(line.replace(/body:/i, ""));
- } else if (lowercaseLine.includes("format:")) {
- format = line.replace(/format:/i, "");
- if (!format.includes("{}")) {
- el.createEl("strong", { text: "Error: Use {} to show response in the document." });
- return;
- }
- } else if (lowercaseLine.includes("req-id:")) {
- reqID = line.replace(/id:/i, "");
+ } else if (lowercaseLine.includes("notify-if:")) {
+ const tempNotifyIf = line.replace(/notify-if:/i, "");
+ notifyIf = tempNotifyIf.trim().split(" ");
+ } else if (lowercaseLine.includes("req-repeat:")) {
+ const repeat_values: string[] = line.replace(/req-repeat:/i, "").trim().split("@");
- if (sourceLines.includes("disabled")) {
- const idExists = localStorage.getItem(reqID);
- if (idExists) {
- el.innerHTML += parser.parse(idExists);
- return;
- } else {
- sourceLines.splice(sourceLines.indexOf("disabled"), 1);
- }
- }
- } else if (lowercaseLine.includes("save-to:")) {
- saveTo = line.replace(/save-to:/i, "");
- if (saveTo === "") {
- el.createEl("strong", { text: "Error: save-to value is empty. Please provide a filename" });
- return;
- }
- } else if (lowercaseLine.includes("properties:")) {
- properties = line.replace(/properties:/i, "");
- properties = properties.replace(/\s/g, "");
- properties = properties.split(",");
- }
- if (URL === "") {
- el.createEl("strong", { text: "Error: URL not found" });
- return;
- }
- }
+ // Function to check if a string is a valid integer
+ const isValidNumber = (value: string): boolean => {
+ return /^\d+$/.test(value);
+ };
- if (sourceLines.includes("disabled")) {
- el.createEl("strong", { text: "This request is disabled." });
- return;
- }
+ // Check if there are two values and they are valid numbers
+ if (repeat_values.length === 2 && isValidNumber(repeat_values[0]) && isValidNumber(repeat_values[1])) {
+ reqRepeat = { "times": parseInt(repeat_values[0]), "every": parseInt(repeat_values[1]) * 1000 };
+ } else {
+ el.createEl("strong", { text: "Error: req-repeat format is not valid (use T@S)" });
+ return;
+ }
- for (let i = 0; i < reqRepeat.times; i++) {
- try {
- const responseData = await requestUrl({ url: URL, method, headers, body });
- // Save to File
- if (saveTo) {
- try {
- await this.app.vault.create(saveTo, responseData.text);
- new Notice("Saved to " + saveTo);
- } catch (e) {
- console.error(e.message);
- new Notice("Error: " + e.message);
- }
- }
+ } else if (lowercaseLine.includes("url:")) {
+ URL = checkFrontmatter(line.replace(/url:/i, "").trim()) ?? "";
+ if (!URL) {
+ el.createEl("strong", { text: "Error: URL not found" });
+ return;
+ }
+ if (URL && !URL.startsWith("http")) {
+ URL = "https://" + URL;
+ }
+ } else if (lowercaseLine.includes("show:")) {
+ show = line.replace(/show:/i, "").trim();
+ if (!show) {
+ el.createEl("strong", { text: "Error: show value is empty" });
+ return;
+ }
+ } else if (lowercaseLine.includes("headers:")) {
+ const tempHeaders = checkFrontmatter(line.replace(/headers:/i, "")) ?? "";
+ if (tempHeaders) {
+ try {
+ headers = JSON.parse(tempHeaders);
+ } catch (e) {
+ el.createEl("strong", { text: "Error: Headers format is not valid" });
+ return;
+ }
+ }
+ } else if (lowercaseLine.includes("body:")) {
+ body = checkFrontmatter(line.replace(/body:/i, ""));
+ } else if (lowercaseLine.includes("format:")) {
+ format = line.replace(/format:/i, "");
+ if (!format.includes("{}")) {
+ el.createEl("strong", { text: "Error: Use {} to show response in the document." });
+ return;
+ }
+ } else if (lowercaseLine.includes("req-id:")) {
+ reqID = line.replace(/id:/i, "").trim();
- if (responseType !== "json") {
- try {
- el.innerHTML += parser.parse(responseData.text);
- } catch (e) {
- new Notice("Error: " + e.message);
- el.createEl("strong", { text: responseData.text });
- }
- saveToID(reqID, responseData.text);
- addBtnCopy(el, responseData.text);
- return;
- }
+ if (sourceLines.includes("disabled")) {
+ const idExists = localStorage.getItem(reqID);
+ if (idExists) {
+ el.createDiv({ text: parser.parse(idExists) });
+ return;
+ } else {
+ sourceLines.splice(sourceLines.indexOf("disabled"), 1);
+ }
+ }
+ } else if (lowercaseLine.includes("save-to:")) {
+ saveTo = line.replace(/save-to:/i, "").trim();
+ if (!saveTo) {
+ el.createEl("strong", { text: "Error: save-to value is empty. Please provide a filename with extension" });
+ return;
+ }
+ } else if (lowercaseLine.includes("properties:")) {
+ // remove all spaces and split by comma
+ properties = line.replace(/properties:/i, "").replace(/\s/g, "").split(",");
+ }
+ }
- if (notifyIf) {
- const jsonPath = notifyIf[0];
- const symbol = notifyIf[1];
- const value = notifyIf[2]
- const int_value = parseInt(value);
+ if (sourceLines.includes("disabled")) {
+ el.createEl("strong", { text: this.settings.DisabledReq });
+ return;
+ }
- const jsonPathValue = jsonPath.split(".").reduce((acc, cv) => acc[cv], responseData.json);
- const lastValue = jsonPath.split(".").pop();
- if (symbol === ">" && jsonPathValue > int_value) {
- new Notice("APIR: " + lastValue + " is greater than " + int_value);
- } else if (symbol === "<" && jsonPathValue < int_value) {
- new Notice("APIR: " + lastValue + " is less than " + int_value);
- } else if (symbol === "=" && jsonPathValue === value) {
- new Notice("APIR: " + lastValue + " is equal to " + value);
- } else if (symbol === ">=" && jsonPathValue >= int_value) {
- new Notice("APIR: " + lastValue + " is greater than or equal to " + int_value);
- } else if (symbol === "<=" && jsonPathValue <= int_value) {
- new Notice("APIR: " + lastValue + " is less than or equal to " + int_value);
- }
- }
+ for (let i = 0; i < reqRepeat.times; i++) {
+ try {
+ const responseData = await requestUrl({ url: URL, method, headers, body });
+ // Save to a file
+ if (saveTo) {
+ try {
+ await this.app.vault.create(saveTo, responseData.text);
+ new Notice("Saved to: " + saveTo);
+ } catch (e) {
+ console.error(e.message);
+ new Notice("Error: " + e.message);
+ }
+ }
+
+ // Check if the response is not JSON
+ if (!responseData.headers["content-type"].includes("application/json")) {
+ try {
+ el.innerHTML = parser.parse(responseData.text);
+ } catch (e) {
+ new Notice("Error: " + e.message);
+ el.innerHTML = "" + responseData.text + ""; + } + + if (reqID) saveToID(reqID, responseData.text); + addBtnCopy(el, responseData.text); + return; + } + + if (notifyIf) { + const jsonPath = notifyIf[0]; + const symbol = notifyIf[1]; + const value = notifyIf[2] + const int_value = parseInt(value); + + const jsonPathValue = jsonPath.split(".").reduce((acc, cv) => acc[cv], responseData.json); + const lastValue = jsonPath.split(".").pop(); + if (symbol === ">" && jsonPathValue > int_value) { + new Notice("APIR: " + lastValue + " is greater than " + int_value); + } else if (symbol === "<" && jsonPathValue < int_value) { + new Notice("APIR: " + lastValue + " is less than " + int_value); + } else if (symbol === "=" && jsonPathValue === value) { + new Notice("APIR: " + lastValue + " is equal to " + value); + } else if (symbol === ">=" && jsonPathValue >= int_value) { + new Notice("APIR: " + lastValue + " is greater than or equal to " + int_value); + } else if (symbol === "<=" && jsonPathValue <= int_value) { + new Notice("APIR: " + lastValue + " is less than or equal to " + int_value); + } + } if (!show) { - el.innerHTML = "
" + JSON.stringify(responseData.json, null, 2) + ""; - saveToID(reqID, el.innerText); - addBtnCopy(el, el.innerText); - } else { - if (show.match(in_braces_regx)) { + if (properties.length > 0 && properties[0] !== '') { + el.createEl("strong", { text: "Error: Properties are not allowed without SHOW" }); + return; + } + el.innerHTML = "
" + JSON.stringify(responseData.json, null, 2) + ""; + if (reqID) saveToID(reqID, el.innerText); + addBtnCopy(el, el.innerText); + } else { + const checkBracesRegex = show.match(in_braces_regx); + if (checkBracesRegex) { if (show.includes(",")) { el.createEl("strong", { text: "Error: comma is not allowed when using {}" }); return; } let temp_show = ""; + let range = Object(); - if (show.match(num_braces_regx)) { - const range = show.match(nums_rex).map(Number); + try { + range = show.match(nums_rex)!.map(Number) if (range[0] > range[1]) { el.createEl("strong", { text: "Error: range is not valid" }); return; } - for (let i = range[0]; i <= range[1]; i++) { - temp_show += show.replace(show.match(num_braces_regx)[0], i) + ", "; + } catch (e) { + console.error(e.message) + } + + const numberBracesRegex = show.match(num_braces_regx) + + if (numberBracesRegex) { + for (let i: number = range[0]; i <= range[1]; i++) { + temp_show += show.replace(numberBracesRegex![0], i.toString()) + ", "; } show = temp_show; } else if (show.match(num_hyphen_regx)) { - const numbers = show.match(nums_rex).map(Number); - show = show.replace(in_braces_regx, "-"); - for (let i = 0; i < numbers.length; i++) { - temp_show += show.replace("-", numbers[i]) + ", "; - } - show = temp_show; + show = show.replace(in_braces_regx, "-"); + for (let i = 0; i < range.length; i++) { + temp_show += show.replace("-", range[i].toString()) + ", "; + } + show = temp_show; } else { - for (let i = 0; i < responseData.json.length; i++) { - temp_show += show.replace("{..}", i) + ", "; - } - show = temp_show; - } + for (let i = 0; i < responseData.json.length; i++) { + temp_show += show.replace("{..}", i.toString()) + ", "; + } + show = temp_show; + } } // adding properties to frontmatter - if (properties) { + if (properties.length > 0 && properties[0] !== '') { const showArray = show.split(","); const propertiesArray = properties; const activeView = this.app.workspace.getActiveViewOfType(MarkdownView); - const file = activeView.file; + const file: TFile = activeView!.file; - showArray.forEach(async (key, index) => { + await Promise.all(showArray.map(async (key, index) => { + const trimmedKey = key.trim(); let val = ""; - if (key.includes("->")) { - val = nestedValue(responseData, key); - } else if (responseData.json && responseData.json[key.trim()]) { - val = responseData.json[key.trim()]; + + if (trimmedKey.includes("->")) { + val = nestedValue(responseData, trimmedKey); + } else if (responseData.json && responseData.json[trimmedKey]) { + val = responseData.json[trimmedKey]; } + const propertyName = propertiesArray[index].trim(); if (propertyName) { await this.app.fileManager.processFrontMatter(file, (existingFrontmatter) => { - existingFrontmatter[propertyName] = val; + existingFrontmatter[propertyName] = val; }); } - }); + })); } - const values = show.includes(",") ? show.split(",").map(key => { - let value = responseData.json[key.trim()]; - if (key.includes("->")) value = nestedValue(responseData, key); - return value; - }) : [show.trim().includes("->") ? nestedValue(responseData, show.trim()) : responseData.json[show.trim()]]; - const replacedText = replaceOrder(format, values); - el.innerHTML = parser.parse(replacedText); - saveToID(reqID, replacedText); - addBtnCopy(el, replacedText); - } - } catch (error) { - console.error(error); - el.createEl("strong", { text: "Error: " + error.message }); - new Notice("Error: " + error.message); - } - await sleep(reqRepeat.every); - } - return; - }); + const trimAndProcessKey = (key: string) => { + const trimmedKey = key.trim(); + return trimmedKey.includes("->") + ? nestedValue(responseData, trimmedKey) + : JSON.stringify(responseData.json[trimmedKey]); + }; + + const values = show.split(",").map(trimAndProcessKey); + const replacedText = replaceOrder(format, values); + + el.innerHTML = parser.parse(replacedText); + if (reqID) saveToID(reqID, replacedText); + addBtnCopy(el, replacedText); + } + } catch (error) { + console.error(error); + el.createEl("strong", { text: "Error: " + error.message }); + new Notice("Error: " + error.message); + } + await sleep(reqRepeat.every); + } + return; + }); } catch (e) { - console.error(e.message); - el.createEl("strong", { text: "Error: " + error.message }); - new Notice("Error: " + e.message); + console.error(e.message); + new Notice("Error: " + e.message); } this.addCommand({ id: 'response-in-document', name: 'Paste response in current document', - editorCallback: (editor: Editor, view: MarkdownView) => { + editorCallback: (editor: Editor) => { toDocument(this.settings, editor); } }); for (let i = 0; i < this.settings.URLs.length; i++) { this.addCommand({ - id: 'response-in-document-' + this.settings.URLs[i].Name, - name: 'Response for api: ' + this.settings.URLs[i].Name, + id: 'response-in-document-' + this.settings.URLs[i]["Name"], + name: 'Response for api: ' + this.settings.URLs[i]["Name"], editorCallback: (editor: Editor, view: MarkdownView) => { const rea = this.settings.URLs[i]; toDocument(rea, editor); @@ -318,12 +352,12 @@ export default class MainAPIR extends Plugin { onunload() { console.log('unloading APIR'); - // Clean up localStorage - Object.keys(localStorage).forEach(key => { - if (key.startsWith("req-")) { - localStorage.removeItem(key); - } - }); + // Clean up localStorage + // Object.keys(localStorage).forEach(key => { + // if (key.startsWith("req-")) { + // localStorage.removeItem(key); + // } + // }); } async loadSettings() { @@ -336,55 +370,54 @@ export default class MainAPIR extends Plugin { } class ShowOutputModal extends Modal { - constructor(app: App, URL: string, MethodRequest: string, DataRequest: string, HeaderRequest: string, DataResponse: string) { - super(app); - this.props = { - URL, - MethodRequest, - DataRequest, - HeaderRequest, - DataResponse, - }; - } - - onOpen() { - const { contentEl } = this; - const { URL, MethodRequest, DataRequest, HeaderRequest, DataResponse } = this.props; - - const handleError = (error) => { - console.error(error); - new Notice("Error: " + error.message); - }; - - const parseAndCreate = (data) => (key) => { - const json = data.json; - const value = DataResponse.includes("->") ? nestedValue(data, key) : json[key]; - contentEl.createEl('b', { text: key + " : " + JSON.stringify(value, null, 2) }); - }; - - const requestOptions = { - url: URL, - method: MethodRequest, - headers: JSON.parse(HeaderRequest), - ...(MethodRequest !== "GET" && { body: DataRequest }) - }; - - requestUrl(requestOptions) - .then((data) => { - if (DataResponse !== "") { - const DataResponseArray = DataResponse.split(","); - DataResponseArray.forEach(parseAndCreate(data)); - } else { - contentEl.createEl('b', { text: JSON.stringify(data.json, null, 2) }); - } - }) - .catch(handleError); + constructor(app: App, URL: string, MethodRequest: string, DataRequest: string, HeaderRequest: string, DataResponse: string) { + super(app); + this.props = { + URL, + MethodRequest, + DataRequest, + HeaderRequest, + DataResponse, + }; } - onClose() { - const { contentEl } = this; - contentEl.empty(); - } + onOpen() { + const { contentEl } = this; + const { URL, MethodRequest, DataRequest, HeaderRequest, DataResponse } = this.props; + + const handleError = (error: Error) => { + console.error(error); + new Notice("Error: " + error.message); + }; + + const parseAndCreate = (data: object) => (key: string) => { + const value = DataResponse.includes("->") ? nestedValue(data, key) : data[key]; + contentEl.createEl('b', { text: key + " : " + JSON.stringify(value, null, 2) }); + }; + + const requestOptions = { + url: URL, + method: MethodRequest, + headers: JSON.parse(HeaderRequest), + ...(MethodRequest !== "GET" && { body: DataRequest }) + }; + + requestUrl(requestOptions) + .then((data) => { + if (DataResponse !== "") { + const DataResponseArray = DataResponse.split(","); + DataResponseArray.forEach(parseAndCreate(data)); + } else { + contentEl.createEl('b', { text: JSON.stringify(data.json, null, 2) }); + } + }) + .catch(handleError); + } + + onClose() { + const { contentEl } = this; + contentEl.empty(); + } } class APRSettings extends PluginSettingTab { @@ -396,10 +429,10 @@ class APRSettings extends PluginSettingTab { } display(): void { - const {containerEl} = this; + const { containerEl } = this; containerEl.empty(); - containerEl.createEl('h2', { text: "Add Request" }); + containerEl.createEl('h2', { text: "Add New Request" }); new Setting(containerEl) .setName('Name') @@ -424,90 +457,104 @@ class APRSettings extends PluginSettingTab { this.plugin.settings.URL = value; await this.plugin.saveSettings(); })); - new Setting(containerEl) - .setName('Method') - .setDesc("Select the desired method") - .addDropdown(dropDown => { - dropDown.addOption("GET", "GET"); - dropDown.addOption("POST", "POST"); - dropDown.addOption("POST", "PUT"); - dropDown.addOption("DELETE", "DELETE"); - dropDown.setValue(this.plugin.settings.MethodRequest) - dropDown.onChange(async value => { - this.plugin.settings.MethodRequest = value; - await this.plugin.saveSettings(); - }); - }); - new Setting(containerEl) - .setName('Body') - .setDesc("Data to send in the body") - .addTextArea(text => text - .setPlaceholder('{"data":"data"}') - .setValue(this.plugin.settings.DataRequest) - .onChange(async (value) => { - this.plugin.settings.DataRequest = value; - await this.plugin.saveSettings(); - })); - new Setting(containerEl) - .setName('Headers') - .setDesc("The headers of the request") - .addTextArea(text => text - .setPlaceholder('{"Content-Type": "application/json"}') - .setValue(this.plugin.settings.HeaderRequest) - .onChange(async (value) => { - this.plugin.settings.HeaderRequest = value; - await this.plugin.saveSettings(); - })); - new Setting(containerEl) - .setName('What to display') - .setDesc("Write the name of the variables you want to show (spaced by comma)") - .addTextArea(text => text - .setPlaceholder('varname') - .setValue(this.plugin.settings.DataResponse) - .onChange(async (value) => { - this.plugin.settings.DataResponse = value; - await this.plugin.saveSettings(); - })); - new Setting(containerEl) - .addButton(button => { - button.setClass('btn-add-apir'); - button.setButtonText('ADD').onClick(async () => { - const {Name} = this.plugin.settings; - if (Name === "") { - new Notice("Name is empty"); - return; - } - const {URL, MethodRequest, DataResponse, DataRequest, HeaderRequest} = this.plugin.settings; - const {URLs} = this.plugin.settings; - URLs.push({ - 'URL': URL, - 'Name': Name, - 'MethodRequest': MethodRequest, - 'DataRequest': DataRequest, - 'HeaderRequest': HeaderRequest, - 'DataResponse': DataResponse - }); - await this.plugin.saveSettings(); - this.display(); - this.plugin.addCommand({ - id: 'response-in-document-' + Name, - name: 'Response for api: ' + Name, - editorCallback: (editor: Editor, view: MarkdownView) => { - const rea = URLs[URLs.length - 1]; - toDocument(rea, editor); - } - }); - }); - }); + new Setting(containerEl) + .setName('Method') + .setDesc("Select the desired method") + .addDropdown(dropDown => { + dropDown.addOption("GET", "GET"); + dropDown.addOption("POST", "POST"); + dropDown.addOption("POST", "PUT"); + dropDown.addOption("DELETE", "DELETE"); + dropDown.setValue(this.plugin.settings.MethodRequest) + dropDown.onChange(async value => { + this.plugin.settings.MethodRequest = value; + await this.plugin.saveSettings(); + }); + }); + new Setting(containerEl) + .setName('Body') + .setDesc("Data to send in the body") + .addTextArea(text => text + .setPlaceholder('{"data":"data"}') + .setValue(this.plugin.settings.DataRequest) + .onChange(async (value) => { + this.plugin.settings.DataRequest = value; + await this.plugin.saveSettings(); + })); + new Setting(containerEl) + .setName('Headers') + .setDesc("The headers of the request") + .addTextArea(text => text + .setPlaceholder('{"Content-Type": "application/json"}') + .setValue(this.plugin.settings.HeaderRequest) + .onChange(async (value) => { + this.plugin.settings.HeaderRequest = value; + await this.plugin.saveSettings(); + })); + new Setting(containerEl) + .setName('What to display') + .setDesc("Write the name of the variables you want to show (spaced by comma)") + .addText(text => text + .setPlaceholder('varname') + .setValue(this.plugin.settings.DataResponse) + .onChange(async (value) => { + this.plugin.settings.DataResponse = value; + await this.plugin.saveSettings(); + })); + new Setting(containerEl) + .addButton(button => { + button.setClass('btn-add-apir'); + button.setButtonText('ADD').onClick(async () => { + const { Name } = this.plugin.settings; + if (Name === "") { + new Notice("Name is empty"); + return; + } + const { URL, MethodRequest, DataResponse, DataRequest, HeaderRequest } = this.plugin.settings; + const { URLs } = this.plugin.settings; + URLs.push({ + 'URL': URL, + 'Name': Name, + 'MethodRequest': MethodRequest, + 'DataRequest': DataRequest, + 'HeaderRequest': HeaderRequest, + 'DataResponse': DataResponse + }); + await this.plugin.saveSettings(); + this.display(); + this.plugin.addCommand({ + id: 'response-in-document-' + Name, + name: 'Response for api: ' + Name, + editorCallback: (editor: Editor) => { + const rea = URLs[URLs.length - 1]; + toDocument(rea, editor); + } + }); + }); + }); - containerEl.createEl('hr'); + containerEl.createEl('hr'); + + containerEl.createEl('h2', { text: 'Codeblock Settings' }); + new Setting(containerEl) + .setName('Text when request is Disabled') + .setDesc("What to show when a request is disabled") + .addText(text => text + .setPlaceholder('This request is disabled') + .setValue(this.plugin.settings.DisabledReq) + .onChange(async (value) => { + this.plugin.settings.DisabledReq = value; + await this.plugin.saveSettings(); + })); + + containerEl.createEl('hr'); containerEl.createEl('h2', { text: 'Manage Requests' }); this.displayInfoApirs(containerEl); - new Setting(containerEl) - .addButton(button => { - button.setClass('btn-clear-apir'); + new Setting(containerEl) + .addButton(button => { + button.setClass('btn-clear-apir'); button.setButtonText("Clear localStorage").onClick(async () => { Object.keys(localStorage).forEach(key => { if (key.startsWith("req-")) { @@ -516,62 +563,62 @@ class APRSettings extends PluginSettingTab { }); this.display(); }); - }); - } + }); + } -displayInfoApirs(containerEl: HTMLElement) { + displayInfoApirs(containerEl: HTMLElement) { // Render URL table - const { URLs } = this.plugin.settings; - const ct = containerEl.createEl('div', { cls: 'cocontainer' }); - if (URLs.length > 0) { - const tableContainer = ct.createEl('div', { cls: 'table-container' }); + const { URLs } = this.plugin.settings; + const ct = containerEl.createEl('div', { cls: 'cocontainer' }); + if (URLs.length > 0) { + const tableContainer = ct.createEl('div', { cls: 'table-container' }); - const table = tableContainer.createEl('table', { cls: 'api-table' }); - const thead = table.createEl('thead'); - const headerRow = thead.createEl('tr'); - headerRow.createEl('th', { text: 'Name' }); - headerRow.createEl('th', { text: 'URL' }); + const table = tableContainer.createEl('table', { cls: 'api-table' }); + const thead = table.createEl('thead'); + const headerRow = thead.createEl('tr'); + headerRow.createEl('th', { text: 'Name' }); + headerRow.createEl('th', { text: 'URL' }); - const tbody = table.createEl('tbody'); - URLs.forEach((url) => { - const row = tbody.createEl('tr'); + const tbody = table.createEl('tbody'); + URLs.forEach((url) => { + const row = tbody.createEl('tr'); - row.createEl('td', { text: url.Name }); + row.createEl('td', { text: url.Name }); - const urlCell = row.createEl('td'); - urlCell.createEl('a', { text: url.URL.length > 50 ? url.URL.substring(0, 50) + "..." : url.URL, cls: 'api-url' }); + const urlCell = row.createEl('td'); + urlCell.createEl('a', { text: url.URL.length > 50 ? url.URL.substring(0, 50) + "..." : url.URL, cls: 'api-url' }); - urlCell.addEventListener('click', async () => { - const index = URLs.indexOf(url); - URLs.splice(index, 1); - await this.plugin.saveSettings(); - this.display(); - }); - }); - } + urlCell.addEventListener('click', async () => { + const index = URLs.indexOf(url); + URLs.splice(index, 1); + await this.plugin.saveSettings(); + this.display(); + }); + }); + } - // Render localStorage table - const tableContainer = containerEl.createEl('div', { cls: 'table-container full-width' }); - const table = ct.createEl('table', { cls: 'api-table full-width' }); - const thead = table.createEl('thead'); - const headerRow = thead.createEl('tr'); - let hr = headerRow.createEl('th', { text: 'ID' }); + // Render localStorage table + containerEl.createEl('div', { cls: 'table-container full-width' }); + const table = ct.createEl('table', { cls: 'api-table full-width' }); + const thead = table.createEl('thead'); + const headerRow = thead.createEl('tr'); + const hr = headerRow.createEl('th', { text: 'ID' }); - const tbody = table.createEl('tbody'); - Object.keys(localStorage).forEach(key => { - if (key.startsWith("req-")) { - const row = tbody.createEl('tr'); - const idCell = row.createEl('td', { text: key }); + const tbody = table.createEl('tbody'); + Object.keys(localStorage).forEach(key => { + if (key.startsWith("req-")) { + const row = tbody.createEl('tr'); + const idCell = row.createEl('td', { text: key }); - idCell.addEventListener('click', async () => { - localStorage.removeItem(key); - this.display(); - }); - } - }); - // if table is empty - if (tbody.children.length === 0) { - hr.innerText = 'No response saved'; + idCell.addEventListener('click', async () => { + localStorage.removeItem(key); + this.display(); + }); + } + }); + // if table is empty + if (tbody.children.length === 0) { + hr.innerText = 'No response saved'; } } diff --git a/src/mdparse.js b/src/mdparse.js index ba616e3..e798aa6 100644 --- a/src/mdparse.js +++ b/src/mdparse.js @@ -2,6 +2,9 @@ export class MarkdownParser { parse(text) { + // Remove all