Skip to content

Commit

Permalink
Merge pull request #41 from yakisova41/add-comment
Browse files Browse the repository at this point in the history
💡 Add comment
  • Loading branch information
yakisova41 authored Apr 19, 2024
2 parents 60d0599 + 4246c3f commit e08a368
Show file tree
Hide file tree
Showing 20 changed files with 302 additions and 3 deletions.
33 changes: 33 additions & 0 deletions packages/crx-monkey/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ const defaultConfig: CrxMonkeyConfig = {
userscriptInjectPage: [],
};

/**
* Get the path to crx-monkey.config.js.
* @returns
*/
async function getConfigPath(): Promise<string | null> {
return await new Promise((resolve, reject) => {
let dir = process.cwd();
Expand Down Expand Up @@ -47,6 +51,11 @@ async function getConfigPath(): Promise<string | null> {
});
}

/**
* Find config file.
* @param dir
* @returns
*/
async function search(dir: string): Promise<string | null> {
return await new Promise((resolve) => {
void promises.readdir(dir + '/').then((files) => {
Expand All @@ -63,6 +72,12 @@ async function search(dir: string): Promise<string | null> {
});
}

/**
* [Type guard] Is the key contained object??
* @param obj
* @param key
* @returns
*/
function isKeyof<T>(obj: object, key: T | string): key is T {
let result = false;
Object.keys(obj).forEach((objkey) => {
Expand All @@ -73,6 +88,11 @@ function isKeyof<T>(obj: object, key: T | string): key is T {
return result;
}

/**
* If value in config is undefined, that value will be default value.
* @param config LKoaded config data.
* @returns
*/
function setDefaultConfig(config: Record<string, never>) {
const newConf: CrxMonkeyConfig = {
...defaultConfig,
Expand All @@ -89,8 +109,16 @@ function setDefaultConfig(config: Record<string, never>) {
return newConf;
}

/**
* Loaded config data.
* It is null when before use loadConfig() use.
*/
let configCahce: null | CrxMonkeyConfig = null;

/**
* Load config file in project.
* @returns
*/
export async function loadConfig(): Promise<CrxMonkeyConfig> {
return await new Promise((resolve) => {
void getConfigPath()
Expand All @@ -111,6 +139,11 @@ export async function loadConfig(): Promise<CrxMonkeyConfig> {
});
}

/**
* Get config that had loaded.
* Must run loadConfig() before use!
* @returns
*/
export function getConfig() {
if (configCahce !== null) {
return configCahce;
Expand Down
7 changes: 7 additions & 0 deletions packages/crx-monkey/src/node/handlers/build/Build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ export class Build {
this.config = config;
}

/**
* Build multiple js files.
* @param jsFilePaths pathes.
* @param onBuild
* @param overrideOptions
* @param overridePlugins
*/
protected async buildByJsFilePaths(
jsFilePaths: string[],
onBuild: (result: BuildResult<BuildOptions>, jsFilePath: string) => void,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export class BuildContentScript extends Build implements BuildImplements {
}
}

/**
* Copy css files to dist.
* @param cssFilePaths
*/
private copyCssFiles(cssFilePaths: string[]) {
cssFilePaths.forEach((cssFilePath, index) => {
const fileName = path.basename(cssFilePath);
Expand Down
18 changes: 18 additions & 0 deletions packages/crx-monkey/src/node/handlers/build/BuildPopup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export class BuildPopup extends Build implements BuildImplements {
}
}

/**
* Build scripts that loaded in popup html.
* @param popupPath
*/
private async buildLocalScripts(popupPath: string) {
await Promise.all(
Object.keys(this.requestLocalScripts).map(async (src) => {
Expand Down Expand Up @@ -48,13 +52,22 @@ export class BuildPopup extends Build implements BuildImplements {
);
}

/**
* Get Html parser instance.
* @param htmlPath
* @returns
*/
private getParser(htmlPath: string) {
const content = fse.readFileSync(htmlPath).toString();
const root = parse(content);

return root;
}

/**
* Load paths of local script loaded by popup html.
* @param root
*/
private loadRequestLocalResources(root: HTMLElement) {
const scriptElems = root.querySelectorAll('script');

Expand All @@ -63,6 +76,7 @@ export class BuildPopup extends Build implements BuildImplements {
scriptElems.forEach((elem) => {
const src = elem.getAttribute('src');
if (src !== undefined && src !== null) {
// Except the script href that start http.
if (src.match('^http.*') === null) {
requestLocalScripts[src] = elem;
}
Expand All @@ -72,6 +86,10 @@ export class BuildPopup extends Build implements BuildImplements {
this.requestLocalScripts = requestLocalScripts;
}

/**
* Output html data in parser instance to dist.
* @param parserRoot
*/
private outputHTML(parserRoot: HTMLElement) {
fse.outputFile(
path.join(this.config.chromeOutputDir!, 'popup/popup.html'),
Expand Down
60 changes: 59 additions & 1 deletion packages/crx-monkey/src/node/handlers/build/BuildUserScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,19 @@ export class BuildUserScript extends Build implements BuildImplements {
this.headerFactory = headerFactory;
}

/**
* Build userscript
*/
public async build() {
if (this.config.devServer === undefined) {
throw new Error('Dev Server is not enabled');
}

/**
* Build and output content scripts.
*/
const contentScripts = this.manifest.content_scripts;

if (contentScripts !== undefined) {
const { jsFiles, cssFiles } = getAllJsAndCSSByContentScripts(contentScripts);

Expand All @@ -60,26 +67,46 @@ export class BuildUserScript extends Build implements BuildImplements {
}
}

/**
* Register meta data to userscript header factory.
* @param allMatches
* @param unsafeWindow
*/
private async headerRegister(allMatches: string[], unsafeWindow: boolean) {
/**
* Set all match to header.
*/
allMatches.forEach((match) => {
this.headerFactory.push('@match', match);
});

/**
* Set version designation by manifest to header.
*/
this.headerFactory.push('@version', this.manifest.version);

if (this.manifest.run_at !== undefined) {
this.headerFactory.push('@run-at', convertChromeRunAtToUserJsRunAt(this.manifest.run_at));
}

/**
* Set name.
* If can not found locale message, even if language key is not en, it will be en.
*/
const names = await geti18nMessages(this.manifest.name);
Object.keys(names).forEach((lang) => {
if (lang === 'en') {
// default is en.
this.headerFactory.push('@name', names[lang]);
} else {
this.headerFactory.push(`@name:${lang}`, names[lang]);
}
});

/**
* Set description.
* If can not found locale message, even if language key is not en, it will be en.
*/
if (this.manifest.description !== undefined) {
const descriptions = await geti18nMessages(this.manifest.description);
Object.keys(descriptions).forEach((lang) => {
Expand All @@ -94,9 +121,11 @@ export class BuildUserScript extends Build implements BuildImplements {
const configHeader = this.config.userScriptHeader;
if (configHeader !== undefined) {
configHeader.forEach((configHeaderItem) => {
// If key is not @grant and already exists it in header, it replace value into configHeaderItem[1].
if (this.headerFactory.exist(configHeaderItem[0]) && configHeaderItem[0] !== '@grant') {
this.headerFactory.replace(configHeaderItem[0], configHeaderItem[1]);
} else {
// If key is @grant and already exists it in header, add an add additional it.
this.headerFactory.push(configHeaderItem[0], configHeaderItem[1]);

// If already included unsafewindow in grant, after no need include.
Expand All @@ -108,9 +137,13 @@ export class BuildUserScript extends Build implements BuildImplements {
}

if (unsafeWindow) {
// If not already included unsafewindow, run it.
this.headerFactory.push('@grant', 'unsafeWindow');
}

/**
* Add icon of 48size that converted to base64 in manifest.json to userscript.
*/
if (this.config.importIconToUsercript) {
const icons = this.manifest.icons;

Expand Down Expand Up @@ -143,7 +176,7 @@ export class BuildUserScript extends Build implements BuildImplements {
}

/**
* Build content scripts for each match and generate code to restrict execution for each match using if
* Build content scripts for each match and generate code to restrict execution for each match using the if syntax.
* @param matchMap
* @param jsBuildResultStore
* @param cssResultStore
Expand All @@ -154,32 +187,43 @@ export class BuildUserScript extends Build implements BuildImplements {
jsBuildResultStore: Record<string, Uint8Array>,
cssResultStore: Record<string, Buffer>,
) {
// script result tmp.
let scriptContent = '';

Object.keys(matchMap).forEach((filePath) => {
const matches = matchMap[filePath];

// Start conditional statement of if for branch of href.
scriptContent = scriptContent + 'if (';

// Does this contentscript have multiple match href?
let isOr = false;

matches.forEach((matchPattern) => {
scriptContent =
scriptContent + `${isOr ? ' ||' : ''}location.href.match('${matchPattern}') !== null`;

isOr = true;
});

// End conditional statement.
scriptContent = scriptContent + ') {\n';

if (jsBuildResultStore[filePath] !== undefined) {
const buildResultText = new TextDecoder().decode(jsBuildResultStore[filePath]);

if (this.config.userscriptInjectPage.includes(filePath)) {
// Inject script using DOM.
scriptContent = scriptContent + generateInjectScriptCode(buildResultText);
} else {
// Run script in userscript sandbox.
scriptContent = scriptContent + buildResultText;
}
}

/**
* Inject style using DOM.
*/
if (cssResultStore[filePath] !== undefined) {
const cssText = cssResultStore[filePath].toString();
scriptContent =
Expand All @@ -191,12 +235,17 @@ export class BuildUserScript extends Build implements BuildImplements {
].join('\n');
}

// End if.
scriptContent = scriptContent + '}\n\n';
});

return scriptContent;
}

/**
* Marge userscript header, content script code and css inject code and output it.
* @param matchMap
*/
private outputFile(matchMap: Record<string, string[]>) {
const contentScriptcode = this.generateContentScriptcode(
matchMap,
Expand All @@ -213,6 +262,10 @@ export class BuildUserScript extends Build implements BuildImplements {
}
}

/**
* Load content of css file selected by manifest.json and store it Buffer to this.cssResultStore.
* @param cssFilePaths
*/
private loadContentCssFiles(cssFilePaths: string[]) {
cssFilePaths.forEach((cssFilePath, index) => {
const fileName = path.basename(cssFilePath);
Expand All @@ -224,6 +277,11 @@ export class BuildUserScript extends Build implements BuildImplements {
});
}

/**
* Does "userscriptInjectPage" in config contain even one js files?
* @param jsFiles js file paths.
* @returns
*/
private isIncludedInjectScripts(jsFiles: string[]) {
let result = false;

Expand Down
9 changes: 9 additions & 0 deletions packages/crx-monkey/src/node/handlers/dev/Watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ export class Watch {
});
}

/**
* Watch multiple js files.
* @param jsFilePaths
* @param onBuild
* @param overrideOptions
* @param onFirstBuild
* @param overridePlugins
* @returns
*/
protected async watchByJsFilePaths(
jsFilePaths: string[],
onBuild: (result: BuildResult<BuildOptions>, jsFilePath: string) => void,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export class WatchContentScripts extends Watch implements WatchImplements {
}
}

/**
* Copy css files to dist.
* @param cssFilePaths
*/
private copyCssFiles(cssFilePaths: string[]) {
cssFilePaths.forEach((cssFilePath, index) => {
const fileName = path.basename(cssFilePath);
Expand Down
Loading

0 comments on commit e08a368

Please sign in to comment.