@bernierllc/validators-editorial-style
v1.0.1
Published
Editorial style validation for the BernierLLC validators ecosystem - validates inclusive language, brand terms, prohibited terminology, and editorial tone
Downloads
14
Readme
@bernierllc/validators-editorial-style
Editorial style validation for the BernierLLC validators ecosystem. Validates inclusive language, brand terms, prohibited terminology, tone, and readability to ensure high-quality, professional documentation.
Installation
npm install @bernierllc/validators-editorial-styleFeatures
- Inclusive Language: Detects non-inclusive terminology and suggests alternatives
- Brand Terms: Validates correct capitalization of technology brands and terms
- Prohibited Terms: Identifies weak, vague, or unprofessional language
- Tone Validation: Ensures professional, respectful, and clear communication
- Readability Score: Calculates Flesch Reading Ease score for content accessibility
Usage
Basic Validation
import { validateEditorialStyle } from '@bernierllc/validators-editorial-style';
const content = `
Hey guys! This is a simple guide to using the API.
Obviously, you should whitelist the master server.
`;
const problems = await validateEditorialStyle(content);
problems.forEach(problem => {
console.log(`${problem.severity}: ${problem.message}`);
if (problem.suggestion) {
console.log(` Suggestion: ${problem.suggestion}`);
}
});Using Individual Rules
import {
inclusiveLanguage,
brandTerms,
prohibitedTerms,
toneValidation,
readabilityScore
} from '@bernierllc/validators-editorial-style';
import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
const content = 'Your content here';
const context = createRuleContext('editorial-style', content, createSharedUtils());
// Run individual rules
const rule = inclusiveLanguage.create(context);
rule(content);
const problems = context.getProblems();With Custom Utilities
import { validateEditorialStyle } from '@bernierllc/validators-editorial-style';
import { createSharedUtils } from '@bernierllc/validators-utils';
const utils = createSharedUtils();
const problems = await validateEditorialStyle(content, utils);Validation Rules
1. Inclusive Language
Detects non-inclusive terminology and suggests inclusive alternatives:
Non-inclusive terms detected:
whitelist→allowlistblacklist→denylist/blocklistmaster→primary/mainslave→secondary/replicaguys→folks/everyone/teammanpower→workforce/staffsanity check→verification/validationdummy→placeholder/samplecrazy/insane→unexpected/surprising
Example:
// ❌ Problematic
"Add the IP to the whitelist and configure the master server."
// ✅ Better
"Add the IP to the allowlist and configure the primary server."2. Brand Terms
Validates correct capitalization of technology brands and terms:
Brands validated:
- JavaScript (not javascript, Javascript)
- TypeScript (not typescript, Typescript)
- GitHub (not github, Github)
- npm (not NPM, Npm)
- Node.js (not nodejs, NodeJS)
- API, URL, HTML, CSS, JSON (all caps)
- macOS, iOS (specific capitalization)
Note: Skips validation inside code blocks (marked with backticks).
Example:
// ❌ Problematic
"Use javascript and github for your api."
// ✅ Better
"Use JavaScript and GitHub for your API."3. Prohibited Terms
Identifies weak, vague, or unprofessional language:
Vague intensifiers: very, really
Filler words: just, simply
Condescending: obviously, clearly, easy, simple
Informal: gonna, wanna, kinda, sorta
Absolute statements: always, never, impossible
Passive voice: it is believed, it is recommended
Example:
// ❌ Problematic
"This is very important. Just add the code and obviously it works."
// ✅ Better
"This is important. Add the code to enable the feature."4. Tone Validation
Ensures professional, clear, and respectful communication:
Tone issues detected:
- Condescending: "as you probably know", "of course", "needless to say"
- Overly casual: "hey guys", "cool", "awesome", "!!"
- Uncertain: "maybe", "perhaps", "I think", "??"
- Bureaucratic: "herein", "pursuant to", "utilize"
- Aggressive: "must", "cannot", "never do" (marked as errors)
Example:
// ❌ Problematic
"Obviously this is cool!! You must do this now."
// ✅ Better
"This approach is effective. We recommend implementing this feature."5. Readability Score
Calculates Flesch Reading Ease score for content accessibility:
Score ranges:
- 90-100: Very Easy (5th grade)
- 80-89: Easy (6th grade)
- 70-79: Fairly Easy (7th grade)
- 60-69: Standard (8th-9th grade)
- 50-59: Fairly Difficult (10th-12th grade)
- 30-49: Difficult (College)
- 0-29: Very Difficult (College graduate)
Target: 50-70 for technical documentation
Note: Skips content with fewer than 50 words. Removes code blocks before calculation.
API Reference
validateEditorialStyle(content: string, utils?: SharedUtils): Promise<Problem[]>
Main validation function that runs all editorial style rules.
Parameters:
content- The content string to validateutils- Optional shared utilities (creates default if not provided)
Returns: Array of validation problems
Validators
editorialStyleValidator
Primitive validator instance for editorial style.
Properties:
meta.name- Validator name ("editorial-style")meta.domain- Validation domain ("content")validate(content, context)- Validation method
Metadata
metadata
Package metadata including version, description, and rule information.
Properties:
name- Package nameversion- Package versiondescription- Package descriptiondomain- Validation domainrules- Array of rule metadata
Integration Status
- Logger: Not applicable - Pure validation package
- Docs-Suite: Ready - Exports markdown documentation
- NeverHub: Not applicable - Primitive validator with no service dependencies
Examples
Complete Validation Example
import { validateEditorialStyle } from '@bernierllc/validators-editorial-style';
const documentation = `
# API Documentation
Hey guys! This is a very simple guide to using our API.
Obviously, you should whitelist your IP addresses on the master server.
The api uses JSON for all responses. Just send a GET request to get data.
It's impossible to mess this up - the system always works perfectly!
`;
const problems = await validateEditorialStyle(documentation);
// Group problems by severity
const errors = problems.filter(p => p.severity === 'error');
const warnings = problems.filter(p => p.severity === 'warn');
const info = problems.filter(p => p.severity === 'info');
console.log(`Found ${errors.length} errors, ${warnings.length} warnings, ${info.length} info`);
// Show problems with suggestions
problems.forEach(problem => {
console.log(`\n${problem.severity.toUpperCase()}: ${problem.message}`);
if (problem.evidence?.snippet) {
console.log(` Context: "${problem.evidence.snippet}"`);
}
if (problem.suggestion) {
console.log(` 💡 ${problem.suggestion}`);
}
});Custom Rule Set
import { createPrimitiveValidator } from '@bernierllc/validators-core';
import {
inclusiveLanguage,
brandTerms,
readabilityScore
} from '@bernierllc/validators-editorial-style';
// Create validator with subset of rules
const customValidator = createPrimitiveValidator(
'custom-editorial',
'content',
[inclusiveLanguage, brandTerms, readabilityScore]
);
// Use custom validator
const context = createRuleContext('custom-editorial', content, createSharedUtils());
const problems = await customValidator.validate(content, context);CI/CD Integration
import { validateEditorialStyle } from '@bernierllc/validators-editorial-style';
import * as fs from 'fs';
async function validateDocumentation(filePath: string): Promise<boolean> {
const content = fs.readFileSync(filePath, 'utf-8');
const problems = await validateEditorialStyle(content);
const errors = problems.filter(p => p.severity === 'error');
if (errors.length > 0) {
console.error(`❌ ${errors.length} editorial errors in ${filePath}`);
errors.forEach(e => console.error(` - ${e.message}`));
return false;
}
const warnings = problems.filter(p => p.severity === 'warn');
if (warnings.length > 0) {
console.warn(`⚠️ ${warnings.length} editorial warnings in ${filePath}`);
warnings.forEach(w => console.warn(` - ${w.message}`));
}
return true;
}
// Validate all markdown files
const docFiles = ['README.md', 'docs/api.md', 'docs/guide.md'];
const results = await Promise.all(docFiles.map(validateDocumentation));
if (!results.every(r => r)) {
process.exit(1);
}Best Practices
- Run in CI/CD: Include editorial validation in your continuous integration pipeline
- Combine with Linters: Use alongside ESLint and Prettier for comprehensive code quality
- Document Exceptions: When false positives occur, document why specific terms are acceptable
- Educate Team: Share validation results to improve writing across your team
- Iterate: Start with errors only, gradually address warnings as team improves
Development
# Install dependencies
npm install
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Build
npm run build
# Lint
npm run lintLicense
Copyright (c) 2025 Bernier LLC. All rights reserved.
See Also
- @bernierllc/validators-core - Core validation types and utilities
- @bernierllc/validators-utils - Shared validation utilities
- @bernierllc/validators-markdown-structure - Markdown structure validation
- @bernierllc/validators-content - Domain validator for complete content quality
