Added SEO title check to see if it's lower than 60 chars

This commit is contained in:
Elio Struyf
2020-07-03 22:36:13 +02:00
parent 304377c3c4
commit 7d15b4c2e0
6 changed files with 104 additions and 50 deletions
+4
View File
@@ -1,5 +1,9 @@
# Change Log
## [1.2.0] - 2020-07-03
- Added SEO title warning when over 60 characters is used
## [1.1.1] - 2020-04-07
- `TOML` delimiter fix
-37
View File
@@ -1,37 +0,0 @@
import * as vscode from 'vscode';
import { ArticleHelper } from '../helpers';
export class StatusBar {
/**
* Update the text of the status bar
*
* @param frontMatterStatusBar
*/
public static async showDraftStatus(frontMatterSB: vscode.StatusBarItem) {
const draftMsg = "in draft";
const publishMsg = "to publish";
let editor = vscode.window.activeTextEditor;
if (editor && editor.document && editor.document.languageId.toLowerCase() === "markdown") {
try {
const article = ArticleHelper.getFrontMatter(editor);
if (article && typeof article.data["draft"] !== "undefined") {
console.log(`Draft status: ${article.data["draft"]}`);
if (article.data["draft"] === true) {
frontMatterSB.text = `$(book) ${draftMsg}`;
frontMatterSB.show();
} else if (article.data["draft"] === false) {
frontMatterSB.text = `$(book) ${publishMsg}`;
frontMatterSB.show();
}
return;
}
} catch (e) {
// Nothing to do
}
}
frontMatterSB.hide();
}
}
+71
View File
@@ -0,0 +1,71 @@
import * as vscode from 'vscode';
import { ArticleHelper } from '../helpers';
export class StatusListener {
/**
* Update the text of the status bar
*
* @param frontMatterSB
* @param collection
*/
public static async verify(frontMatterSB: vscode.StatusBarItem, collection: vscode.DiagnosticCollection) {
const draftMsg = "in draft";
const publishMsg = "to publish";
let editor = vscode.window.activeTextEditor;
if (editor && editor.document && editor.document.languageId.toLowerCase() === "markdown") {
try {
const article = ArticleHelper.getFrontMatter(editor);
// Update the StatusBar based on the article draft state
if (article && typeof article.data["draft"] !== "undefined") {
// console.log(`Draft status: ${article.data["draft"]}`);
if (article.data["draft"] === true) {
frontMatterSB.text = `$(book) ${draftMsg}`;
frontMatterSB.show();
} else if (article.data["draft"] === false) {
frontMatterSB.text = `$(book) ${publishMsg}`;
frontMatterSB.show();
}
}
// Check SEO of the title
if (article && article.data && article.data.title) {
const title: string = article.data.title;
console.log(`Title length: ${title.length}`);
if (title.length >= 60) {
const text = editor.document.getText();
const markdown = ArticleHelper.stringifyFrontMatter("", article.data);
const txtIdx = text.indexOf(title);
if (txtIdx !== -1 && txtIdx < markdown.length) {
collection.clear();
const posStart = editor.document.positionAt(txtIdx);
const posEnd = editor.document.positionAt(txtIdx + 1 + title.length);
collection.set(editor.document.uri, [{
code: '',
message: `Article title is longer than 60 characters (current length: ${title.length}). For SEO reasons, it would be better to make it less than 60 characters.`,
range: new vscode.Range(posStart, posEnd),
severity: vscode.DiagnosticSeverity.Warning,
source: 'Front Matter'
}]);
} else {
collection.clear();
}
} else {
collection.clear();
}
}
return;
} catch (e) {
// Nothing to do
}
}
frontMatterSB.hide();
}
}
+1 -1
View File
@@ -1,3 +1,3 @@
export * from './Article';
export * from './Settings';
export * from './StatusBar';
export * from './StatusListener';
+5 -3
View File
@@ -1,11 +1,13 @@
import * as vscode from 'vscode';
import { Article, Settings, StatusBar } from './commands';
import { Article, Settings, StatusListener } from './commands';
import { TaxonomyType } from './models';
let frontMatterStatusBar: vscode.StatusBarItem;
let debouncer: { (fnc: any, time: number): void; };
let collection: vscode.DiagnosticCollection;
export function activate({ subscriptions }: vscode.ExtensionContext) {
collection = vscode.languages.createDiagnosticCollection('frontMatter');
let insertTags = vscode.commands.registerCommand('frontMatter.insertTags', () => {
Article.insert(TaxonomyType.Tag);
@@ -50,7 +52,7 @@ export function activate({ subscriptions }: vscode.ExtensionContext) {
frontMatterStatusBar.command = toggleDraftCommand;
subscriptions.push(frontMatterStatusBar);
debouncer = debounceShowDraftTrigger();
// Register listeners that make sure the status bar
// Register listeners that make sure the status bar updates
subscriptions.push(vscode.window.onDidChangeActiveTextEditor(triggerShowDraftStatus));
subscriptions.push(vscode.window.onDidChangeTextEditorSelection(triggerShowDraftStatus));
// Automatically run the command
@@ -71,7 +73,7 @@ export function activate({ subscriptions }: vscode.ExtensionContext) {
export function deactivate() {}
const triggerShowDraftStatus = () => {
debouncer(() => { StatusBar.showDraftStatus(frontMatterStatusBar); }, 1000);
debouncer(() => { StatusListener.verify(frontMatterStatusBar, collection); }, 1000);
};
const debounceShowDraftTrigger = () => {
+23 -9
View File
@@ -35,16 +35,9 @@ export class ArticleHelper {
*/
public static async update(editor: vscode.TextEditor, article: matter.GrayMatterFile<string>) {
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
const indentArray = config.get(SETTING_INDENT_ARRAY) as boolean;
const removeQuotes = config.get(SETTING_REMOVE_QUOTES) as string[];
const language = getFmLanguage();
const langOpts = getFormatOpts(language);
let newMarkdown = matter.stringify(article.content, article.data, ({
...TomlEngine,
...langOpts,
noArrayIndent: !indentArray
} as DumpOptions as any));
let newMarkdown = this.stringifyFrontMatter(article.content, article.data);
// Check for field where quotes need to be removed
if (removeQuotes && removeQuotes.length) {
@@ -60,12 +53,33 @@ export class ArticleHelper {
await editor.edit(builder => builder.replace(new vscode.Range(new vscode.Position(0, 0), new vscode.Position(nrOfLines, 0)), newMarkdown));
}
/**
* Stringify the front matter
*
* @param content
* @param data
*/
public static stringifyFrontMatter(content: string, data: any) {
const config = vscode.workspace.getConfiguration(CONFIG_KEY);
const indentArray = config.get(SETTING_INDENT_ARRAY) as boolean;
const language = getFmLanguage();
const langOpts = getFormatOpts(language);
return matter.stringify(content, data, ({
...TomlEngine,
...langOpts,
noArrayIndent: !indentArray,
lineWidth: 500
} as DumpOptions as any));
}
/**
* Generate the slug
*
* @param articleTitle
*/
static createSlug(articleTitle: string): string | null {
public static createSlug(articleTitle: string): string | null {
if (!articleTitle) {
return null;
}