-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
99296b7
commit 4ab1fab
Showing
15 changed files
with
411 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Placeholders Toolkit Changelog | ||
|
||
## [0.1.3] - 2023-11-15? | ||
|
||
- Re-added the `{{selectedFileContents}}` (or just `{{contents}}`) placeholder. | ||
- Deprecated `PLApplicator.checkForPlaceholders()` in favor of `PLChecker.checkForPlaceholders()`. | ||
- Added `PLChecker.checkForPlaceholdersInRange()` and `PLChecker.getPlaceholderRanges()`. | ||
- Fixed bug where `{{fileNames}}` would only return the last file name. | ||
|
||
## [0.1.2] - 2023-11-11 | ||
|
||
- Removed debug console logs. | ||
|
||
## [0.1.1] - 2023-11-10 | ||
|
||
- Added syntax examples for each placeholder. | ||
- Added support for passing functions instead of strings when using JavaScript placeholders, e.g. `{{js:dialog(() => askAI("What is the capital of Canada?"))}}. | ||
- Added `{{chooseFile}}`, `{{chooseFolder}}`, and `{{chooseApplication}}` placeholders. | ||
- Added `{{write to="[path]":...}}` placeholder. | ||
- General documentation improvements. | ||
|
||
## [0.1.0] - 2023-11-07 | ||
|
||
- First generally stable release. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import { DefaultPlaceholders } from "./defaultPlaceholders"; | ||
import { PLRange, Placeholder } from "./types"; | ||
|
||
/** | ||
* Gets a list of placeholders that are included in a string. | ||
* @param str The string to check. | ||
* @param options The options for applying placeholders. | ||
* @param options.customPlaceholders The list of custom (user-defined) placeholders. Provide this if you have a separate list of custom placeholders. | ||
* @param options.defaultPlaceholders The list of default placeholders. Provide this if you have customized the order of default placeholders or added additional defaults. | ||
* @param options.allPlaceholders The list of all placeholders (custom and default). Provide this if you have a single list of all placeholders. | ||
* @param options.strict Whether to only include placeholders that are surrounded by double curly braces and match the placeholder regex. Defaults to false (will include placeholders that are not surrounded by double curly braces). | ||
* @returns The list of {@link Placeholder} objects. | ||
*/ | ||
export const checkForPlaceholders = async ( | ||
str: string, | ||
options?: { | ||
customPlaceholders?: Placeholder[]; | ||
defaultPlaceholders?: Placeholder[]; | ||
allPlaceholders?: Placeholder[]; | ||
strict?: boolean; | ||
} | ||
): Promise<Placeholder[]> => { | ||
const sortedPlaceholders = options?.allPlaceholders | ||
? options.allPlaceholders | ||
: [ | ||
...(options?.customPlaceholders || []), | ||
...(options?.defaultPlaceholders | ||
? options.defaultPlaceholders | ||
: Object.values(DefaultPlaceholders)), | ||
]; | ||
|
||
const includedPlaceholders = sortedPlaceholders | ||
.filter((placeholder) => { | ||
return ( | ||
str.match(placeholder.regex) != undefined || | ||
(!options?.strict && | ||
(str.match( | ||
new RegExp( | ||
"(^| )" + | ||
placeholder.regex.source.replace("{{", "").replace("}}", ""), | ||
"g" | ||
) | ||
) != undefined || | ||
str.match( | ||
new RegExp( | ||
`(^| |:|})({?{?)${placeholder.name.replace( | ||
/[!#+-]/g, | ||
"\\$1" | ||
)}(}?}?)`, | ||
"g" | ||
) | ||
) != undefined)) | ||
); | ||
}) | ||
.sort((placeholderA, placeholderB) => { | ||
// Order definitive occurrences first | ||
if (str.match(placeholderA.regex)) { | ||
return -1; | ||
} else if (str.match(placeholderB.regex)) { | ||
return 1; | ||
} else { | ||
return 0; | ||
} | ||
}); | ||
return includedPlaceholders; | ||
}; | ||
|
||
/** | ||
* Gets a list of the ranges of placeholders that are included in a string. | ||
* @param str The string to check. | ||
* @param options The options for applying placeholders. Optional. | ||
* @param options.customPlaceholders The list of custom (user-defined) placeholders. Provide this if you have a separate list of custom placeholders. | ||
* @param options.defaultPlaceholders The list of default placeholders. Provide this if you have customized the order of default placeholders or added additional defaults. | ||
* @param options.allPlaceholders The list of all placeholders (custom and default). Provide this if you have a single list of all placeholders. | ||
* @param options.strict Whether to only include placeholders that are surrounded by double curly braces and match the placeholder regex. Defaults to false (will include placeholders that are not surrounded by double curly braces). | ||
* @returns The list of placeholders and their ranges. | ||
*/ | ||
export const getPlaceholderRanges = async ( | ||
str: string, | ||
options?: { | ||
customPlaceholders?: Placeholder[]; | ||
defaultPlaceholders?: Placeholder[]; | ||
allPlaceholders?: Placeholder[]; | ||
strict?: boolean; | ||
} | ||
): Promise< | ||
{ | ||
placeholder: Placeholder; | ||
range: PLRange; | ||
}[] | ||
> => { | ||
const includedPlaceholders = await checkForPlaceholders(str, options); | ||
const ranges = includedPlaceholders.map((placeholder) => { | ||
const match = str.match(new RegExp(placeholder.regex.source)); | ||
if (match?.index) { | ||
return { | ||
placeholder, | ||
range: { | ||
startIndex: match.index, | ||
endIndex: match.index + match[0].length, | ||
}, | ||
}; | ||
} | ||
}); | ||
return ranges.filter((range) => range != undefined) as { | ||
placeholder: Placeholder; | ||
range: PLRange; | ||
}[]; | ||
}; | ||
|
||
/** | ||
* Checks if a string contains placeholders in a given range. | ||
* @param str The string to check. | ||
* @param range The range to check. | ||
* @param options The options for applying placeholders. Optional. | ||
* @param options.customPlaceholders The list of custom (user-defined) placeholders. Provide this if you have a separate list of custom placeholders. | ||
* @param options.defaultPlaceholders The list of default placeholders. Provide this if you have customized the order of default placeholders or added additional defaults. | ||
* @param options.allPlaceholders The list of all placeholders (custom and default). Provide this if you have a single list of all placeholders. | ||
* @param options.strict Whether to only include placeholders that are surrounded by double curly braces and match the placeholder regex. Defaults to false (will include placeholders that are not surrounded by double curly braces). | ||
* @returns The list of placeholders contained within the range. | ||
*/ | ||
export const checkForPlaceholdersInRange = async ( | ||
str: string, | ||
range: PLRange, | ||
options?: { | ||
customPlaceholders?: Placeholder[]; | ||
defaultPlaceholders?: Placeholder[]; | ||
allPlaceholders?: Placeholder[]; | ||
strict?: boolean; | ||
} | ||
): Promise<Placeholder[]> => { | ||
const substr = str.substring(range.startIndex, range.endIndex); | ||
const includedPlaceholders = await checkForPlaceholders(substr, options); | ||
const ranges = includedPlaceholders.map((placeholder) => { | ||
const match = str.match(new RegExp(placeholder.regex.source)); | ||
if (match?.index) { | ||
return placeholder | ||
} | ||
}); | ||
return ranges.filter((range) => range != undefined) as Placeholder[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
jest.mock("node-fetch", () => ({ fetch: console.log("mocked fetch") })); | ||
jest.mock("@raycast/utils", () => ({ | ||
runAppleScript: (script: string) => execScript(script, []).data, | ||
})); | ||
|
||
import { execScript } from "../lib/scripts"; | ||
import { PLChecker } from "../lib"; | ||
|
||
describe("Placeholder Checker Tests", () => { | ||
it("should detect 3 distinct placeholders", async () => { | ||
const str = "Hello, I am {{user}}. I am {{computerName}}. Today is {{day}}."; | ||
const placeholders = await PLChecker.checkForPlaceholders(str); | ||
expect(placeholders.length).toBe(3); | ||
}); | ||
|
||
it("should detect 3 distinct placeholders not surrounded by double curly braces when not using strict mode", async () => { | ||
const str = "Hello, I am user. I am computerName. Today is day."; | ||
const placeholders = await PLChecker.checkForPlaceholders(str, { | ||
strict: false, | ||
}); | ||
expect(placeholders.length).toBe(3); | ||
}); | ||
|
||
it("should not detect incomplete placeholders when using strict mode", async () => { | ||
const str = "Hello, I am user. I am computerName. Today is day."; | ||
const placeholders = await PLChecker.checkForPlaceholders(str, { | ||
strict: true, | ||
}); | ||
expect(placeholders.length).toBe(0); | ||
}); | ||
|
||
it("should correctly identify the range of placeholders", async () => { | ||
const str = "Hello, I am {{user}}. I am {{computerName}}. Today is {{day}}."; | ||
const ranges = await PLChecker.getPlaceholderRanges(str); | ||
expect(ranges.length).toBe(3); | ||
expect(ranges[0].range.startIndex).toBe(54); | ||
expect(ranges[0].range.endIndex).toBe(61); | ||
expect(ranges[1].range.startIndex).toBe(27); | ||
expect(ranges[1].range.endIndex).toBe(43); | ||
expect(ranges[2].range.startIndex).toBe(12); | ||
expect(ranges[2].range.endIndex).toBe(20); | ||
}); | ||
|
||
it("should correctly identify placeholders in a given range", async () => { | ||
const str = "Hello, I am {{user}}. I am {{computerName}}. Today is {{day}}."; | ||
const ranges = await PLChecker.getPlaceholderRanges(str); | ||
const placeholders = await PLChecker.checkForPlaceholdersInRange( | ||
str, | ||
ranges[0].range | ||
); | ||
expect(placeholders.length).toBe(1); | ||
expect(placeholders[0].name).toBe("day"); | ||
|
||
const customRange = { startIndex: 26, endIndex: 45 }; | ||
const morePlaceholders = await PLChecker.checkForPlaceholdersInRange( | ||
str, | ||
customRange | ||
); | ||
expect(morePlaceholders.length).toBe(1); | ||
expect(morePlaceholders[0].name).toBe("computerName"); | ||
}); | ||
}); |
Oops, something went wrong.