Skip to content

Commit

Permalink
refactor and new error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Kamil-aexol committed Nov 16, 2023
1 parent 0338739 commit 930441a
Show file tree
Hide file tree
Showing 22 changed files with 442 additions and 321 deletions.
4 changes: 3 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": ["@typescript-eslint", "unused-imports"],
"plugins": ["@typescript-eslint", "unused-imports", "simple-import-sort"],
"rules": {
"no-multiple-empty-lines": ["error", { "max": 1 }],
"eqeqeq": ["error", "always"],
Expand All @@ -34,6 +34,8 @@
"react/react-in-jsx-scope": "off",
"@typescript-eslint/no-var-requires": 0,
"react/prop-types": 0,
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Landing Friend

Landing friend is a simple to use CLI tool which offers immense help for on-page SEO specialists. Run a couple simple commands you'll get:
Landing friend is a simple to use CLI tool which offers immense help for on-page SEO specialists. Run a couple simple commands you`ll get:
* sitemap.xml - localized or unlocalized depending on your project settings
* robots.txt - based on the pages you set up as excluded
* detailed SEO analysis (meta tags, keyword population, errors & duplicates)
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@types/yargs": "^17.0.30",
"@typescript-eslint/eslint-plugin": "6.11.0",
"eslint": "8.53.0",
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-unused-imports": "3.0.0",
"prettier": "2.7.1",
"ts-node": "10.9.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/landing-friend-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@landing-friend/core",
"version": "0.0.21",
"version": "0.0.22",
"description": "",
"main": "lib/index.js",
"keywords": [],
Expand Down
106 changes: 48 additions & 58 deletions packages/landing-friend-core/src/analyzer.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import path from "path";
import fs from "fs";
import open, { apps } from "open";
import path from "path";

import {
AdvancedTagsName,
AllTagsName,
checkFiles,
CombinedPatterns,
CombineTagsWithReason,
ConfigFile,
getHtmlFiles,
matchedSetting,
message,
checkFiles,
prepareHTMLWithTables,
CombinedPatterns,
AllTagsName,
saveAnalyze,
CombineTagsWithReason,
getHtmlFiles,
AdvancedTagsName,
} from "./index.js";
} from "@/index.js";

export const websiteAnalyzer = async (config: ConfigFile) => {
export const websiteAnalyzer = async (config: ConfigFile, interval: NodeJS.Timer) => {
const { input, analyzer, advancedAnalyzer, excludedPage, sitemap, domain } = config;
if (!analyzer) {
return message("Define analyzer in config", "redBright");
Expand All @@ -40,6 +42,9 @@ export const websiteAnalyzer = async (config: ConfigFile) => {
input,
tags: analyzer,
advancedTags: advancedAnalyzer,
domain,
countKeywords: analyzer.keywords.count,
countWordsInLast: analyzer.lastSentence.count,
})
);
}
Expand All @@ -61,65 +66,50 @@ export const websiteAnalyzer = async (config: ConfigFile) => {
Object.entries(tagData).forEach(([_tag, _value]) => {
const tag = _tag as AllTagsName;
const value = _value as CombineTagsWithReason;
if (
!(tag === "keywords" && analyzer.keywords.count) &&
!(tag === "lastSentence" && analyzer.lastSentence.count)
) {
tagArray = {
...tagArray,
[tag]: {
requirement: value.requirement && value.requirement.replace(/<\/?strong>/gs, ""),
quantity: value.quantity,
content: value.content,
forbiddenCharacters: value.forbiddenCharacters,
keywordsIncluded: tag !== "keywords" ? value.keywordsIncluded : undefined,
multipleTags: value.multipleTags,
tagAmount: tag in AdvancedTagsName ? value.tagAmount : undefined,
listOfFoundMeta: value.listOfFoundMeta,
isError: value.isError,
missingKeywords: value.missingKeywords,
toMuchKeywords: value.toMuchKeywords,
} as CombineTagsWithReason,
} as Record<AllTagsName, CombineTagsWithReason>;
} else {
tagArray = {
...tagArray,
[tag]: {
requirement: value.requirement && value.requirement.replace(/<\/?strong>/gs, ""),
quantity: value.quantity,
content: value.content,
forbiddenCharacters: value.forbiddenCharacters,
keywordsIncluded: tag !== "keywords" ? value.keywordsIncluded : undefined,
multipleTags: value.multipleTags,
tagAmount: value.tagAmount,
isError: value.isError,
missingKeywords: value.missingKeywords,
toMuchKeywords: value.toMuchKeywords,
} as CombineTagsWithReason,
} as Record<AllTagsName, CombineTagsWithReason>;
}
tagArray = {
...tagArray,
[tag]: {
requirement: value.requirement && value.requirement.replace(/<\/?strong>/gs, ""),
quantity: value.quantity,
content: value.content,
forbiddenCharacters: value.forbiddenCharacters,
keywordsIncluded: tag !== "keywords" ? value.keywordsIncluded : undefined,
multipleTags: value.multipleTags,
tagAmount: tag in AdvancedTagsName ? value.tagAmount : undefined,
listOfFoundMeta: value.listOfFoundMeta,
isError: value.isError,
missingKeywords: value.missingKeywords,
toMuchKeywords: value.toMuchKeywords,
} as CombineTagsWithReason,
} as Record<AllTagsName, CombineTagsWithReason>;
});
cleanedTagsPatterns[file] = tagArray;
});
});

const location = "./SEO";
const fileName = (extension: ".json" | ".html") => `seo-analyze${extension}`;
const pathname = (extension: ".json" | ".html") => `${location}/${fileName(extension)}`;
clearTimeout(interval);
try {
saveAnalyze("./SEO/seo-analyze.json", JSON.stringify(cleanedTagsPatterns, null, 2));
saveAnalyze("./SEO/seo-analyze.html", htmlWithTablesAndCharts);
saveAnalyze(pathname(".json"), JSON.stringify(cleanedTagsPatterns, null, 2));
saveAnalyze(pathname(".html"), htmlWithTablesAndCharts);
message(
"Your website has been analyzed, JSON and html files have been generated in ./SEO",
"green"
);
} catch {
message("Failed to create files", "red");
return;
}
try {
await open(path.join(process.cwd(), "./SEO", "seo-analyze.html"), {
app: { name: apps.browser },
});
message("The analysis file has been opened in your browser.", "green");
} catch {
message("Cannot open browser. Please open file manually", "red");
return;
} finally {
if (fs.existsSync(path.join(process.cwd(), location, fileName(".html")))) {
try {
await open(path.join(process.cwd(), location, fileName(".html")), {
app: { name: apps.browser },
});
message("The analysis file has been opened in your browser.", "green");
} catch {
message("Cannot open browser. Please open file manually", "red");
}
}
}
};
19 changes: 11 additions & 8 deletions packages/landing-friend-core/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from "fs";
import { message } from "./console.js";
import ts from "typescript";

import { message } from "./console.js";
import { ConfigFile } from "./index.js";

export const GLOBAL_CONFIG_FILE: ConfigFile = {
Expand Down Expand Up @@ -46,20 +47,22 @@ export const EXTENDED_ADVANCED_ANALYZER_GLOBAL_CONFIG_FILE: Pick<ConfigFile, "ad
},
};

export const readConfig = (filePath: string): ConfigFile | undefined => {
export const readConfig = (filePath: string, option: "init" | "generate") => {
if (!fs.existsSync(filePath)) {
message(
"No config detected. Please create one using init command or create it manually",
"red"
);
if (option === "generate") {
message(
"No config detected. Please create one using init command or create it manually",
"red"
);
}
return undefined;
}

try {
const configFileText = fs
.readFileSync(filePath, "utf8")
.replace(/'/g, '"')
.replace('import { ConfigFile } from "@landing-friend/core";', "")
.replace(/`/g, `"`)
.replace(`import { ConfigFile } from "@landing-friend/core";`, "")
.replace("export const GLOBAL_CONFIG_FILE: ConfigFile = ", "")
.replace(";", "")
.trim();
Expand Down
35 changes: 1 addition & 34 deletions packages/landing-friend-core/src/console.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import chalk from "chalk";
import cliSpinners from "cli-spinners";
import ora, { Color } from "ora";

type Colors = keyof Pick<
typeof chalk,
Expand All @@ -26,37 +24,6 @@ export const message = (m: string, color: Colors) => {
console.log(chalk[color](m));
};

export const messageWithContent = (
m: string,
content: string,
color: Colors
) => {
export const messageWithContent = (m: string, content: string, color: Colors) => {
console.log(`${chalk[color](m)}${content}`);
};

export const calcTime = (m: string, color: Colors) => {
console.time(chalk[color](m));
return {
end: () => console.timeEnd(chalk[color](m)),
};
};

export const loader = (input: {
text: string;
onSuccess?: string;
onFail?: string;
colorSpinner?: Color;
fastSpinner?: boolean;
}) => {
const { text, colorSpinner, fastSpinner, onFail, onSuccess } = input;
const spinner = ora({
text,
color: colorSpinner,
spinner: fastSpinner ? cliSpinners.bluePulse : cliSpinners.aesthetic,
}).start();
return {
succeed: () => spinner.succeed(onSuccess),
fail: () => spinner.fail(onFail),
clear: () => spinner.clear(),
};
};
4 changes: 2 additions & 2 deletions packages/landing-friend-core/src/data/exclude.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export const unicode = {
"&#x27;": "'",
"&#x27;": "`",
"&amp;": "&",
"&lt;": "<",
"&gt;": ">",
"&#x22;": '"',
"&#x22;": `"`,
"&#x2F;": "/",
"&#x60;": "`",
"&ldquo;": "“",
Expand Down
8 changes: 4 additions & 4 deletions packages/landing-friend-core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export * from "./console.js";
export * from "./config.js";
export * from "./sitemap.js";
export * from "./analyzer.js";
export * from "./config.js";
export * from "./console.js";
export * from "./data/index.js";
export * from "./utils/index.js";
export * from "./sitemap.js";
export * from "./types/index.js";
export * from "./utils/index.js";
1 change: 1 addition & 0 deletions packages/landing-friend-core/src/sitemap.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ISO from "iso-639-1";

import {
ConfigFile,
getHtmlFiles,
Expand Down
1 change: 1 addition & 0 deletions packages/landing-friend-core/src/types/configTypes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { LanguageCode } from "iso-639-1";

import { AdvancedTagsProps, TagsProps } from "./index.js";

export type SitemapSettings = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {
AdvancedTagsProps,
staticTags,
unicode,
forbiddenCharacters as _forbiddenCharacters,
AdvancedTagsNameType,
AdvancedTagsPatterns,
MetaNameWithProps,
AdvancedTagsProps,
forbiddenCharacters as _forbiddenCharacters,
MetaNameTagsProps,
MetaNameWithProps,
staticTags,
unicode,
} from "@/index.js";

interface MatchedArrayProps {
Expand All @@ -18,9 +18,9 @@ const matchedTags = (advancedTags: AdvancedTagsNameType, fileContent: string) =>
const matchedArray: { [tagName: string]: MatchedArrayProps }[] = [];

if (advancedTags === "og") {
regex = new RegExp('<meta property="og:(.*?)" content="(.*?)".*?/>', "gs");
regex = new RegExp(`<meta property="og:(.*?)" content="(.*?)".*?/>`, "gs");
} else if (advancedTags === "twitter") {
regex = new RegExp('<meta name="twitter:(.*?)" content="(.*?)".*?/>', "gs");
regex = new RegExp(`<meta name="twitter:(.*?)" content="(.*?)".*?/>`, "gs");
}

if (regex) {
Expand Down Expand Up @@ -109,7 +109,7 @@ export const checkFileToAdvanceAnalyzer = async ({
[tag]: {
tagAmount: matches.length,
listOfFoundMeta,
isError: Object.values(listOfFoundMeta).some(value => value?.status !== "OK"),
isError: Object.values(listOfFoundMeta).some(value => value?.status === "Not Found"),
} as MetaNameTagsProps,
};
}
Expand Down
Loading

0 comments on commit 930441a

Please sign in to comment.