Define your team’s writing rules

Every team has writing rules it wants kept: a journal’s author guidelines, a company’s style guide. With chaff you write those rules in chaff.yaml, and a machine checks them. No code is needed. The features on this page are in chaff 0.18.0 and later.

There are three ways to set them.

What you wantWhereExample
Use a well-known style as a wholestyle:IEICE’s rules for papers in Japanese
Decide which way one rule goesoptions:Drop the final ー of katakana words
Add a rule of your owncustom_rules:“email”, not “e-mail”

Pick a style by name

Write a style’s name under style:, and chaff’s rules follow it. For example, IEICE papers drop the final long-vowel mark ー from katakana words of three morae or more (コンピュータ, プリンタ).

style: ieice

That is enough for chaff to point at such words that keep their ー:

  3:4     warning 「サーバー」は語末の「ー」を省いて「サーバ」と書きます(3 音以上の語)
                  katakana-long-vowel

The finding is in Japanese because the document is. There are five styles for now. A misspelt name stops chaff before it checks anything, and it lists the names.

NameWhat it decidesSource
ieiceDrop the final ー from words of three morae or moreIEICE, submission guide for papers in Japanese, 2.4
jis-z8301-2011The same (the 2019 edition dropped this rule)JIS Z 8301:2011, Table G.3
bunkachoKeep the final ー (コンピューター)外来語の表記, the 1991 Cabinet notice
jis-z8301-2019No すべきである and no closing できる in a provision; a numbered figure, table or clause is named by its number, not 上記の図 or 以下の箇条JIS Z 8301:2019, 7.3 to 7.5 and 10.6
koyobunA Japanese sentence of at most 60 characters, no mixing of です・ます with である, and the final ー kept公用文作成の考え方 (Council for Cultural Affairs, 2022), III-3 a, III-1 b, I-3 d

Morae are counted before the final ー, as コ・ン・ピュ・ー・タ (as JIS Z 8301:2011 Table G.3 counts). A small ャ, ュ or ョ joins the kana before it. Every one of these styles keeps the ー on words of two morae or fewer before it, such as カー, カバー and シャワー. ieice and jis-z8301-2011 drop only a ー that stands for English -er, -or, -ar (after a kana of the ア row). Words ending in ュー, エー or イー (メニュー, グレー, コピー) are left alone.

A plugin can ship styles too. A style from a plugin listed under plugins: is chosen with the plugin’s name in front (style: example/careful). Writing a plugin shows how to make one.

Decide which way one rule goes

You can also decide one rule’s direction without a style. Under options:, write the rule’s name and what to decide.

rules:
  katakana-long-vowel: normal
options:
  katakana-long-vowel:
    ending: drop      # or keep
    min_morae: 3      # the shortest word checked
    except: [カー]     # words left alone

Without ending, chaff takes no side. It only points at a word written both ways in one document (サーバー and サーバ).

chaff.yaml’s own settings are the strongest, then the style’s, then the genre’s defaults. explain shows where each value came from.

npx chaffjs explain katakana-long-vowel     this rule's settings, and where each came from
  Options (set under options in chaff.yaml):
    ending: drop   (from style: ieice)
      Which way the final ー goes
        consistent No side taken; only checks that the document is consistent
      → drop       Drop the final ー on words of min_morae morae or more (IEICE; JIS Z 8301 up to 2011)

Add a rule of your own

List your team’s rules under custom_rules:. There are three kinds.

type:What it findsGood for
wordsWords you listed“email”, not “e-mail”
patternMatches of a regular expressionNo “TBD” left in a document
tokensA run of parts of speech and base forms“make a decision” can be “decide”

Every rule has a name, a reason, a way to fix it and an example. Whoever reads a finding should understand why to change it.

custom_rules:
  - id: team-email
    type: words
    words:
      e-mail: email
      log-in: log in
    name: The team's spelling
    why: Our style guide spells these one way, so a search finds every mention.
    how_to_fix: Change it to "{preferred}".
    example:
      before: Send the log-in details by e-mail.
      after: Send the log in details by email.

  - id: team-tbd
    type: pattern
    pattern: '\b(TBD|TODO)\b'
    level: error
    name: Something is still undecided
    why: A document sent with TBD in it reads as if the thing were decided.
    how_to_fix: Write who decides it and by when.
    example:
      before: The launch date is TBD.
      after: The launch date is 1 October (Sam confirms it by 20 September).

  - id: team-make-decision
    type: tokens
    tokens:
      - base: make
      - pos: DET
      - surface: decision
    level: info
    name: A verb hidden in a noun
    message: '"{matched}" can be "decide"'
    why: "\"Make a decision\" says in three words what \"decide\" says in one."
    how_to_fix: Use the verb.
    example:
      before: We will make a decision on Friday.
      after: We will decide on Friday.

level is how serious a finding is: error, warning or info. Without it, a rule’s findings are warnings. A tokens rule reads the words’ base forms, so “made a decision” matches “make a decision”.

Save this plan as plan.md and check it.

# Launch plan

We made a decision to move the launch. The new date is TBD.

Send questions by e-mail.
$ npx chaffjs plan.md --compact

plan.md   blog/tech · English   genre from the default

  3:4     info    "made a decision" can be "decide"
                  team-make-decision
  3:56    error   Something is still undecided: "TBD"
                  team-tbd
  5:19    warning Write "email", not "e-mail"
                  team-email

3 findings, 71 rules not run

chaff treats your rules like its own. explain shows the reason and the example you wrote.

npx chaffjs explain team-tbd     what the team's rule is for, with its example
  Something is still undecided   (team-tbd)

  A document sent with TBD in it reads as if the thing were decided.

  How to fix: Write who decides it and by when.

  Example:  The launch date is TBD.
      →  The launch date is 1 October (Sam confirms it by 20 September).

  The team defined this rule under custom_rules in chaff.yaml.

npx chaffjs relax team-tbd makes its findings one step lighter. <!-- stet: team-tbd — reason --> silences it in one place.

When a rule is written wrong

If a rule is missing something, chaff stops before it reads any document and says what is missing. A rule that silently did not run would make a document look clean.

chaff: …/chaff.yaml: custom_rules team-tbd: example.before is missing
chaff: …/chaff.yaml: custom_rules team-tbd: example.after is missing

The path is shortened here.

Regular expressions are checked before they run. A repeat inside a repeat, such as (a+)+, is refused, since on a long line it may never finish. So are more than three * or +, and backreferences (\1). A pattern that still takes over a second on one document is stopped, and the rule is listed as not run, with the reason.

Parts of speech

Under tokens, pos takes everyday names (noun, verb, adjective, adverb, preposition, determiner) or the tags themselves (NOUN, VERB, DET). For Japanese documents it also takes 名詞, 動詞, 助詞 and the like. base is the base form (make), and surface is the word as written (decision). One token may have any of the three.

A rule that has to count or compare, which none of the forms here can say, can be a Node function (type: module, from 0.19.0). How to write one is in Adding a rule, and how to ship it as a package in Writing a plugin.