Skip to content

Commit

Permalink
Merge pull request #21779 from Yoast/add-rule-description-field-to-in…
Browse files Browse the repository at this point in the history
…clusive-language-assessments

Change how we retrieve rule descriptions when generating the inclusive language database
  • Loading branch information
Jordi-PV authored Nov 5, 2024
2 parents fefa3a7 + 8a44457 commit 91a8f44
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,6 @@ const fs = require( "fs" );
* Note: this file is not a regular Jest test, as it exports the inclusive language configuration, rather than testing it.
*/
describe( "Export of the inclusive language configuration", () => {
/**
* Retrieves the rules from a function call in a prettier format.
* @param {string} str The function call.
* @returns {string} The prettier formatted string.
*/
const retrieveRule = ( str ) => {
const matches = [ ...str.matchAll( /\.filter.*?_is(.*?)Exception.*?\[(.*?)]/g ) ];
return matches.map( match => "Not" + match[ 1 ] + ": " + match[ 2 ] ).join( " and " );
};

/**
* Retrieves the href value from a string containing an anchor.
* @param {string} str The string containing an anchor.
Expand Down Expand Up @@ -77,7 +67,7 @@ describe( "Export of the inclusive language configuration", () => {
nonInclusivePhrases: assessment.nonInclusivePhrases.join( ", " ),
inclusiveAlternatives: assessment.inclusiveAlternatives.join( ", " ).replace( /<\/?i>/g, "" ),
score: assessment.score === SCORES.POTENTIALLY_NON_INCLUSIVE ? "orange" : "red",
rule: assessment.rule.name === "includesConsecutiveWords" ? "" : retrieveRule( assessment.rule.toString() ),
ruleDescription: assessment.ruleDescription,
caseSensitive: assessment.caseSensitive ? "yes" : "no",
feedbackFormat: sprintf( assessment.feedbackFormat, "\"x\"", "\"y\"", "\"z\"" ).replace( /<\/?i>/g, "" ),
learnMoreUrl: retrieveAnchor( assessment.learnMoreUrl ),
Expand All @@ -95,21 +85,6 @@ describe( "Export of the inclusive language configuration", () => {
}
} );

it.skip( "should retrieve rules in a more pretty format", () => {
let assessment = new InclusiveLanguageAssessment( inclusiveLanguageAssessmentsConfigs.find( obj => obj.identifier === "firemen" ) );
expect( retrieveRule( assessment.rule.toString() ) ).toEqual( "" );

assessment = new InclusiveLanguageAssessment( inclusiveLanguageAssessmentsConfigs.find( obj => obj.identifier === "binge" ) );
expect( retrieveRule( assessment.rule.toString() ) ).toEqual(
"NotFollowedBy: \"drink\", \"drinks\", \"drinking\", \"eating disorder\", \"and purge\", " +
"\"behavior\", \"behaviors\", \"behaviour\", \"behaviours\"" );

assessment = new InclusiveLanguageAssessment( inclusiveLanguageAssessmentsConfigs.find( obj => obj.identifier === "seniors" ) );
expect( retrieveRule( assessment.rule.toString() ) ).
toEqual( "NotPrecededBy: \"high school\", \"college\", \"graduating\", \"juniors and\"" +
" and NotFollowedBy: \"in high school\", \"in college\", \"who are graduating\"" );
} );

it( "should retrieve the href value for an anchor", () => {
const assessment = new InclusiveLanguageAssessment( inclusiveLanguageAssessmentsConfigs.find( obj => obj.identifier === "firemen" ) );
expect( retrieveAnchor( assessment.learnMoreUrl ) ).toEqual( "https://yoa.st/inclusive-language-gender" );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { isPreceded, notPreceded, notFollowed, notPrecededAndNotFollowed } from "../../../../../src/scoring/assessments/inclusiveLanguage/helpers/createRuleDescriptions";

describe( "A test for creating assessment rule descriptions", function() {
it( "should create a rule description for phrases that should be targeted only when preceded by specific words", function() {
expect( isPreceded( [ "I am", "you are" ] ) ).toBe( "Targeted when preceded by 'I am', 'you are'." );
} );
it( "should create a rule description for phrases that should be targeted unless preceded by specific words", function() {
expect( notPreceded( [ "I am", "you are" ] ) ).toBe( "Targeted unless preceded by 'I am', 'you are'." );
} );
it( "should create a rule description for phrases that should be targeted unless followed by specific words", function() {
expect( notFollowed( [ "in college", "in high school" ] ) ).toBe( "Targeted unless followed by 'in college', 'in high school'." );
} );
it( "should create a rule description for phrases that should be targeted unless preceded and/or followed by specific words", function() {
expect( notPrecededAndNotFollowed( [ "high school", "college" ], [ "in college", "in high school" ] ) ).toBe( "Targeted unless preceded by 'high school', 'college' and/or followed by 'in college', 'in high school'." );
} );
} );
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ export default class InclusiveLanguageAssessment {
* and `%2$s` (and potentially further replacements) for the suggested alternative(s).
* @param {string} config.learnMoreUrl The URL to an article explaining more about this specific assessment.
* @param {function} [config.rule] A potential additional rule for targeting the non-inclusive phrases.
* @param {string} [config.ruleDescription] A description of the rule.
* @param {boolean} [config.caseSensitive=false] If the inclusive phrase is case-sensitive, defaults to `false`.
* @param {string} [config.category] The category of the assessment.
*
* @returns {void}
*/
constructor( { identifier, nonInclusivePhrases, inclusiveAlternatives,
score, feedbackFormat, learnMoreUrl, rule, caseSensitive, category } ) {
score, feedbackFormat, learnMoreUrl, rule, ruleDescription, caseSensitive, category } ) {
this.identifier = identifier;
this.nonInclusivePhrases = nonInclusivePhrases;
this.inclusiveAlternatives = inclusiveAlternatives;
Expand All @@ -48,6 +50,7 @@ export default class InclusiveLanguageAssessment {
this.learnMoreUrl = createAnchorOpeningTag( learnMoreUrl );

this.rule = rule || includesConsecutiveWords;
this.ruleDescription = ruleDescription;
this.caseSensitive = caseSensitive || false;
this.category = category;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { isNotFollowedByException } from "../helpers/isFollowedByException";
import { includesConsecutiveWords } from "../helpers/includesConsecutiveWords";
import { SCORES } from "./scores";
import notInclusiveWhenStandalone from "../helpers/notInclusiveWhenStandalone";
import { nonInclusiveWhenStandalone, notPrecededAndNotFollowed } from "../helpers/createRuleDescriptions";

const ageAssessments = [
{
Expand Down Expand Up @@ -60,6 +61,8 @@ const ageAssessments = [
.filter( isNotPrecededByException( words, [ "high school", "college", "graduating", "juniors and" ] ) )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "in high school", "in college", "who are graduating" ] ) );
},
ruleDescription: notPrecededAndNotFollowed( [ "high school", "college", "graduating", "juniors and" ],
[ "in high school", "in college", "who are graduating" ] ),
},
{
identifier: "theAged",
Expand All @@ -71,6 +74,7 @@ const ageAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( notInclusiveWhenStandalone( words, nonInclusivePhrase ) );
},
ruleDescription: nonInclusiveWhenStandalone,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { redHarmful,
import { SCORES } from "./scores";
import { includesConsecutiveWords } from "../helpers/includesConsecutiveWords";
import notInclusiveWhenStandalone from "../helpers/notInclusiveWhenStandalone";
import { nonInclusiveWhenStandalone } from "../helpers/createRuleDescriptions";

const appearanceAssessments = [
{
Expand All @@ -24,6 +25,7 @@ const appearanceAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( notInclusiveWhenStandalone( words, nonInclusivePhrase ) );
},
ruleDescription: nonInclusiveWhenStandalone,
},
{
identifier: "obese",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import {
orangeUnlessCultureOfOrigin, orangeUnlessCultureUsesTerm,
} from "./feedbackStrings/cultureAssessmentStrings";
import { notFollowed } from "../helpers/createRuleDescriptions";

const cultureAssessments = [
{
Expand All @@ -22,6 +23,7 @@ const cultureAssessments = [
caseSensitive: true,
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "War", "war", "Assembly", "assembly" ] ) ),
ruleDescription: notFollowed( [ "War", "war", "Assembly", "assembly" ] ),
},
{
identifier: "thirdWorld",
Expand All @@ -32,6 +34,7 @@ const cultureAssessments = [
caseSensitive: true,
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "War", "war", "Quarterly", "quarterly", "country" ] ) ),
ruleDescription: notFollowed( [ "War", "war", "Quarterly", "quarterly", "country" ] ),
},
{
identifier: "tribe",
Expand All @@ -58,6 +61,7 @@ const cultureAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "longhair", "longhairs", "shorthair", "shorthairs" ] ) );
},
ruleDescription: notFollowed( [ "longhair", "longhairs", "shorthair", "shorthairs" ] ),
},
{
identifier: "sherpa",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ import {
shouldNotPrecedeStandaloneCrazyWhenFollowedByAbout,
} from "./disabilityRulesData";
import { sprintf } from "@wordpress/i18n";
import {
nonInclusiveWhenStandalone,
isPreceded,
notFollowed,
notPreceded,
} from "../helpers/createRuleDescriptions";

const disabilityAssessments = [
{
Expand All @@ -36,6 +42,7 @@ const disabilityAssessments = [
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase,
[ "drink", "drinks", "drinking", "eating disorder", "and purge", "behavior", "behaviors", "behaviour", "behaviours" ] ) ),
ruleDescription: notFollowed( [ "drink", "drinks", "drinking", "eating disorder", "and purge", "behavior", "behaviors", "behaviour", "behaviours" ] ),
},
{
identifier: "bingeing",
Expand All @@ -47,6 +54,7 @@ const disabilityAssessments = [
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase,
[ "and purging", "behavior", "behaviors", "behaviour", "behaviours" ] ) ),
ruleDescription: notFollowed( [ "and purging", "behavior", "behaviors", "behaviour", "behaviours" ] ),
},
{
identifier: "binged",
Expand All @@ -57,6 +65,7 @@ const disabilityAssessments = [
"If you are not referencing a symptom, consider other alternatives to describe the trait or behavior, such as %2$s.",
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "and purged" ] ) ),
ruleDescription: notFollowed( [ "and purged" ] ),
},
{
identifier: "binges",
Expand All @@ -67,6 +76,7 @@ const disabilityAssessments = [
"If you are not referencing a symptom, consider other alternatives to describe the trait or behavior, such as %2$s.",
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "and purges" ] ) ),
ruleDescription: notFollowed( [ "and purges" ] ),
},
{
identifier: "wheelchairBound",
Expand All @@ -92,6 +102,7 @@ const disabilityAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotPrecededByException( words, [ "mentally" ] ) );
},
ruleDescription: notPreceded( [ "mentally" ] ),
},
{
identifier: "alcoholic",
Expand All @@ -101,6 +112,7 @@ const disabilityAssessments = [
feedbackFormat: orangeUnlessSomeoneWants,
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "drink", "beverage" ] ) ),
ruleDescription: notFollowed( [ "drink", "beverage" ] ),
},
{
identifier: "alcoholics",
Expand All @@ -110,6 +122,7 @@ const disabilityAssessments = [
feedbackFormat: orangeUnlessSomeoneWants,
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "anonymous" ] ) ),
ruleDescription: notFollowed( [ "anonymous" ] ),
},
{
identifier: "cripple",
Expand Down Expand Up @@ -148,6 +161,7 @@ const disabilityAssessments = [
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase,
[ "toilet", "toilets", "parking", "bathroom", "bathrooms", "stall", "stalls" ] ) ),
ruleDescription: notFollowed( [ "toilet", "toilets", "parking", "bathroom", "bathrooms", "stall", "stalls" ] ),
},
{
identifier: "insane",
Expand Down Expand Up @@ -195,6 +209,7 @@ const disabilityAssessments = [
"Consider using an alternative, such as %2$s, unless referring to how you characterize your own condition.",
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "autism" ] ) ),
ruleDescription: notFollowed( [ "autism" ] ),
},
{
identifier: "autismHigh",
Expand Down Expand Up @@ -327,6 +342,7 @@ const disabilityAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotPrecededByException( words, [ "deaf and" ] ) );
},
ruleDescription: notPreceded( [ "deaf and" ] ),
},
{
identifier: "deaf",
Expand Down Expand Up @@ -395,6 +411,7 @@ const disabilityAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isPrecededByException( words, formsOfToBeNotWithOptionalIntensifier ) );
},
ruleDescription: "Targeted when preceded by a negated form of 'to be' or 'to get' and an optional intensifier.",
},
{
identifier: "to be crazy about",
Expand All @@ -407,6 +424,7 @@ const disabilityAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isPrecededByException( words, formsOfToBeWithOptionalIntensifier ) );
},
ruleDescription: "Targeted when preceded by a form of 'to be' or 'to get' and an optional intensifier.",
},
{
identifier: "crazy in love",
Expand All @@ -427,6 +445,7 @@ const disabilityAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isPrecededByException( words, formsOfToGo ) );
},
ruleDescription: isPreceded( formsOfToGo ),
},
{
identifier: "to drive crazy",
Expand All @@ -440,6 +459,7 @@ const disabilityAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isPrecededByException( words, combinationsOfDriveAndObjectPronoun ) );
},
ruleDescription: "Targeted when preceded by a form of 'to drive' and an object pronoun (e.g. 'driving me')",
},
{
identifier: "crazy",
Expand All @@ -457,6 +477,8 @@ const disabilityAssessments = [
shouldNotPrecedeStandaloneCrazyWhenFollowedByAbout,
shouldNotFollowStandaloneCrazyWhenPrecededByToBe ) );
},
ruleDescription: "Not targeted with this feedback when part of a more specific phrase that we target ('to drive crazy', " +
"to go crazy', 'to (not) be crazy about', 'crazy in love').",
},
{
identifier: "crazier",
Expand Down Expand Up @@ -489,6 +511,7 @@ const disabilityAssessments = [
feedbackFormat: orangeUnlessMedicalCondition,
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "disorder" ] ) ),
ruleDescription: notFollowed( [ "disorder" ] ),
},
{
identifier: "paranoid",
Expand All @@ -499,6 +522,7 @@ const disabilityAssessments = [
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase,
[ "personality disorder", "delusion", "delusions", "ideation" ] ) ),
ruleDescription: notFollowed( [ "personality disorder", "delusion", "delusions", "ideation" ] ),
},
{
identifier: "manic",
Expand All @@ -509,6 +533,7 @@ const disabilityAssessments = [
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase,
[ "episode", "episodes", "state", "states", "symptoms", "and depressive episodes", "and hypomanic", "or hypomanic" ] ) ),
ruleDescription: notFollowed( [ "episode", "episodes", "state", "states", "symptoms", "and depressive episodes", "and hypomanic", "or hypomanic" ] ),
},
{
identifier: "hysterical",
Expand Down Expand Up @@ -562,6 +587,7 @@ const disabilityAssessments = [
" If you are not referencing the medical condition, consider other alternatives to describe the trait or behavior, such as %3$s.",
rule: ( words, nonInclusivePhrase ) => includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotFollowedByException( words, nonInclusivePhrase, [ "personality disorder" ] ) ),
ruleDescription: notFollowed( [ "personality disorder" ] ),
},
{
identifier: "OCD",
Expand All @@ -577,6 +603,8 @@ const disabilityAssessments = [
return includesConsecutiveWords( words, inclusivePhrases )
.filter( isPrecededByException( words, formsOfToBeAndToBeNotWithOptionalIntensifier ) );
},
ruleDescription: "Targeted when preceded by a form of 'to be' or 'to get' (including their negated forms)" +
"and an optional intensifier",
},
{
identifier: "theMentallyIll",
Expand All @@ -588,6 +616,7 @@ const disabilityAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( notInclusiveWhenStandalone( words, nonInclusivePhrase ) );
},
ruleDescription: nonInclusiveWhenStandalone,
},
{
identifier: "theDisabled",
Expand All @@ -599,6 +628,7 @@ const disabilityAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( notInclusiveWhenStandalone( words, nonInclusivePhrase ) );
},
ruleDescription: nonInclusiveWhenStandalone,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { orangeExclusionaryUnless,
import { SCORES } from "./scores";
import { includesConsecutiveWords } from "../helpers/includesConsecutiveWords";
import notInclusiveWhenStandalone from "../helpers/notInclusiveWhenStandalone";
import { nonInclusiveWhenStandalone } from "../helpers/createRuleDescriptions";

const genderAssessments = [
{
Expand Down Expand Up @@ -281,6 +282,7 @@ const genderAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( notInclusiveWhenStandalone( words, nonInclusivePhrase ) );
},
ruleDescription: nonInclusiveWhenStandalone,
},
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from "./feedbackStrings/generalFeedbackStrings";
import { includesConsecutiveWords } from "../helpers/includesConsecutiveWords";
import { isNotPrecededByException } from "../helpers/isPrecededByException";
import { notPreceded } from "../helpers/createRuleDescriptions";

const otherAssessments = [
{
Expand All @@ -30,6 +31,7 @@ const otherAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotPrecededByException( words, [ "mentally", "behaviorally", "behaviourally" ] ) );
},
ruleDescription: notPreceded( [ "mentally", "behaviorally", "behaviourally" ] ),
},
{
identifier: "normalPeople",
Expand All @@ -43,6 +45,7 @@ const otherAssessments = [
return includesConsecutiveWords( words, nonInclusivePhrase )
.filter( isNotPrecededByException( words, [ "mentally", "behaviorally", "behaviourally" ] ) );
},
ruleDescription: notPreceded( [ "mentally", "behaviorally", "behaviourally" ] ),
},
{
identifier: "mentallyNormal",
Expand Down
Loading

0 comments on commit 91a8f44

Please sign in to comment.