From 99447e00a1419c6e9ef5bb3ffcbc6e9cde7f5eb3 Mon Sep 17 00:00:00 2001 From: dualfroz Date: Fri, 2 Oct 2026 16:06:32 +0200 Subject: [PATCH] Don't read a titlecase gerund after a colon as a proper noun --- .../preTagger/compute/tagger/2nd-pass/01-case.js | 8 +++++++- src/2-two/preTagger/compute/tagger/index.js | 9 ++++++--- tests/two/tagger/ambiguity/gerund.test.js | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/2-two/preTagger/compute/tagger/2nd-pass/01-case.js b/src/2-two/preTagger/compute/tagger/2nd-pass/01-case.js index 3cf5379..c43adcf 100644 --- a/src/2-two/preTagger/compute/tagger/2nd-pass/01-case.js +++ b/src/2-two/preTagger/compute/tagger/2nd-pass/01-case.js @@ -20,7 +20,7 @@ const nope = { } // if it's a unknown titlecase word, it's a propernoun -const checkCase = function (terms, i, model) { +const checkCase = function (terms, i, model, afterColon) { const term = terms[i] // assume terms are already indexed term.index ||= [0, 0] @@ -40,6 +40,12 @@ const checkCase = function (terms, i, model) { if (/["']$/.test(term.pre)) { return null } + // gerund after a colon - 'Tutorial: Creating a cake' + const before = terms[i - 1] + const hasColon = before ? /:/.test(before.post) : afterColon + if (hasColon && term.tags.has('Gerund')) { + return null + } if (term.normal === 'the') { return null } diff --git a/src/2-two/preTagger/compute/tagger/index.js b/src/2-two/preTagger/compute/tagger/index.js index 52dcc05..8a39e33 100644 --- a/src/2-two/preTagger/compute/tagger/index.js +++ b/src/2-two/preTagger/compute/tagger/index.js @@ -37,7 +37,7 @@ const firstPass = function (docs, model, world) { } // these methods don't care about word-neighbours -const secondPass = function (terms, model, world, isYelling) { +const secondPass = function (terms, model, world, isYelling, afterColon) { for (let i = 0; i < terms.length; i += 1) { // skip frozen terms, for now if (terms[i].frozen === true) { @@ -47,7 +47,7 @@ const secondPass = function (terms, model, world, isYelling) { tagSwitch(terms, i, model) // is it titlecased? if (isYelling === false) { - checkCase(terms, i, model) + checkCase(terms, i, model, afterColon) } // look at word ending checkSuffix(terms, i, model) @@ -104,8 +104,11 @@ const preTagger = function (view) { const terms = document[n] // is it all upper-case? const isYelling = ignoreCase(terms) + // does it follow a colon? + const before = document[n - 1] + const afterColon = before !== undefined && /:/.test(before[before.length - 1].post) // guess by the letters - secondPass(terms, model, world, isYelling) + secondPass(terms, model, world, isYelling, afterColon) // guess by the neighbours thirdPass(terms, model, world, isYelling) } diff --git a/tests/two/tagger/ambiguity/gerund.test.js b/tests/two/tagger/ambiguity/gerund.test.js index 09c50ce..83da321 100644 --- a/tests/two/tagger/ambiguity/gerund.test.js +++ b/tests/two/tagger/ambiguity/gerund.test.js @@ -119,3 +119,17 @@ test('match:', function (t) { }) t.end() }) + +test('titlecase after a colon', function (t) { + const arr = [ + ['Tutorial: Creating a cake', '. #Gerund #Determiner #Noun'], + ['Step two: Mixing the flour', '. #Value #Gerund the #Noun'], + ['On Tuesday: Baking a cake', 'on #Date #Singular a #Noun'], + ] + arr.forEach(function (a) { + const [str, match] = a + const doc = nlp(str) + t.equal(doc.match(match).text(), doc.text(), here + str) + }) + t.end() +})