vicary 0.2.16 → 0.2.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/vicary/candidates.rb +67 -6
- data/lib/vicary/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 381ed16c17b2aa427a72b173af92825ad08db621b13e562fdc7977d41d760a26
|
|
4
|
+
data.tar.gz: 9e7a68508af7f405888c9a0e5ebc9b7993b3f0e7de6149c91156cf7c23b9fe29
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 87ffdbf4edb505a3c1d5faca88c817a5a1ad44b093fbfc329f99958c05a528b078c3fdcc1d97c9e6ffca2d255be617cb3912d6d6e2a9735f02861600aa0f0ce6
|
|
7
|
+
data.tar.gz: ec871699f441d07106e5f32981eb9a34f35ce2935f75a7f78163fc0ae277dc1afbe8fdd042e3dbf9676b8a4493dc9fb8078c36a0e3ba9cb65804cad79b17c93b
|
data/lib/vicary/candidates.rb
CHANGED
|
@@ -300,6 +300,39 @@ module Vicary
|
|
|
300
300
|
most much many few several enough
|
|
301
301
|
]).freeze
|
|
302
302
|
|
|
303
|
+
# Phonetic spellings of English stop words, each with the stop word it
|
|
304
|
+
# spells. Young writers, and young Spanish-L1 writers most of all,
|
|
305
|
+
# spell the closed-class words by ear — "dey sai ai smel", "so ai dont get
|
|
306
|
+
# mai clos dirtier" — and several of those spellings are given names the
|
|
307
|
+
# tier knows, so the lowercase route masked "sai ai" and "mai clos" and the
|
|
308
|
+
# sentence-initial rule let the tier vouch for "Ai", "Mi" and "De". A
|
|
309
|
+
# spelling of a stop word is the same word, so in a document that writes
|
|
310
|
+
# this way it is a stop word too. Only the spellings are read; the pairing
|
|
311
|
+
# is documentation. See `phonetic_function_words` for when a document
|
|
312
|
+
# qualifies.
|
|
313
|
+
PHONETIC_FUNCTION_WORDS = {
|
|
314
|
+
"ai" => "i", "becuz" => "because", "bicuz" => "because", "bot" => "but",
|
|
315
|
+
"cud" => "could", "da" => "the", "dan" => "than", "dat" => "that",
|
|
316
|
+
"de" => "the", "deir" => "their", "dem" => "them", "den" => "then",
|
|
317
|
+
"dere" => "there", "dese" => "these", "dey" => "they", "dis" => "this",
|
|
318
|
+
"dose" => "those", "frum" => "from", "hiz" => "his", "iz" => "is",
|
|
319
|
+
"mai" => "my", "mi" => "me", "sai" => "say", "sed" => "said",
|
|
320
|
+
"shud" => "should", "sum" => "some", "tu" => "to", "wat" => "what",
|
|
321
|
+
"wen" => "when", "wud" => "would", "wuz" => "was", "yu" => "you",
|
|
322
|
+
"yur" => "your",
|
|
323
|
+
}.freeze
|
|
324
|
+
|
|
325
|
+
# Distinct phonetic spellings a document must write in lower case before
|
|
326
|
+
# any of them is read as a word rather than a name. One is a coincidence —
|
|
327
|
+
# a friend called Mai — two different ones is a writer spelling by ear.
|
|
328
|
+
PHONETIC_REGISTER_MIN = 2
|
|
329
|
+
|
|
330
|
+
PHONETIC_TOKEN = Regexp.new(
|
|
331
|
+
"(?<![A-Za-z'’-])(?:" +
|
|
332
|
+
PHONETIC_FUNCTION_WORDS.keys.sort_by { |w| [-w.length, w] }.join("|") +
|
|
333
|
+
")(?![A-Za-z'’-])"
|
|
334
|
+
)
|
|
335
|
+
|
|
303
336
|
HONORIFIC_SET = Set.new(HONORIFICS.map(&:downcase)).freeze
|
|
304
337
|
|
|
305
338
|
# One capitalised word, hyphens and apostrophes included so
|
|
@@ -742,6 +775,20 @@ module Vicary
|
|
|
742
775
|
strip(without_clitic(strip(token.downcase, ".,")), "'’")
|
|
743
776
|
end
|
|
744
777
|
|
|
778
|
+
# The phonetic spellings this document uses as words, to be read as
|
|
779
|
+
# stops. Empty unless the document writes at least PHONETIC_REGISTER_MIN
|
|
780
|
+
# distinct spellings in lower case. When it does, the spellings it writes
|
|
781
|
+
# in lower case — the writer's own testimony that the token is a word to
|
|
782
|
+
# them — less any it also capitalises mid-sentence, which is the opposite
|
|
783
|
+
# testimony and wins.
|
|
784
|
+
def phonetic_function_words(text, written_as_a_capital = Set.new)
|
|
785
|
+
seen = Set.new
|
|
786
|
+
each_match(text, PHONETIC_TOKEN) { |m| seen << m[0] }
|
|
787
|
+
return Set.new if seen.size < PHONETIC_REGISTER_MIN
|
|
788
|
+
|
|
789
|
+
Set.new(seen.reject { |w| written_as_a_capital.include?(w) })
|
|
790
|
+
end
|
|
791
|
+
|
|
745
792
|
# Whether a capital on `token` mid-sentence is a mistake rather than a
|
|
746
793
|
# construction — the narrow half of the stoplist.
|
|
747
794
|
#
|
|
@@ -846,7 +893,11 @@ module Vicary
|
|
|
846
893
|
# the stoplist so that a bare "Mrs." cannot become a candidate on its own,
|
|
847
894
|
# but "Mrs. Okonkwo" has to stay whole: masking only the surname leaves the
|
|
848
895
|
# relationship and the surname's position in the text.
|
|
849
|
-
|
|
896
|
+
#
|
|
897
|
+
# `phonetic` is `phonetic_function_words` for the document: spellings read
|
|
898
|
+
# as stop words here. Except a particle *inside* a run — "Maria de Cruz"
|
|
899
|
+
# keeps its `de` however the rest of the document spells "the".
|
|
900
|
+
def trim(tokens, phonetic = Set.new)
|
|
850
901
|
runs = []
|
|
851
902
|
current = []
|
|
852
903
|
tokens.each_with_index do |token, index|
|
|
@@ -854,7 +905,10 @@ module Vicary
|
|
|
854
905
|
HONORIFIC_SET.include?(strip(token.downcase, ".,")) &&
|
|
855
906
|
index + 1 < tokens.length &&
|
|
856
907
|
!stop?(tokens[index + 1])
|
|
857
|
-
|
|
908
|
+
spelled_stop = !phonetic.empty? && phonetic.include?(fold(token)) &&
|
|
909
|
+
!(index.positive? && index < tokens.length - 1 &&
|
|
910
|
+
PARTICLES.include?(token))
|
|
911
|
+
if (stop?(token) || spelled_stop) && !introduces_a_name
|
|
858
912
|
unless current.empty?
|
|
859
913
|
runs << current
|
|
860
914
|
current = []
|
|
@@ -1849,7 +1903,7 @@ module Vicary
|
|
|
1849
1903
|
# capitalisation signal, and the seed stands on the given-name tier
|
|
1850
1904
|
# alone.
|
|
1851
1905
|
def find_lowercase_candidates(text, is_given, protected_span, corroborate = nil,
|
|
1852
|
-
settlement = nil)
|
|
1906
|
+
settlement = nil, phonetic = Set.new)
|
|
1853
1907
|
tokens = each_match(text, LOWER_TOKEN).map do |m|
|
|
1854
1908
|
[m[0], m.begin(0), m.begin(0) + m[0].length]
|
|
1855
1909
|
end
|
|
@@ -1857,7 +1911,10 @@ module Vicary
|
|
|
1857
1911
|
index = 0
|
|
1858
1912
|
while index < tokens.length
|
|
1859
1913
|
word, start, = tokens[index]
|
|
1860
|
-
|
|
1914
|
+
# A phonetic spelling may not SEED a span ("sai ai smel"), but may
|
|
1915
|
+
# still be the token a real seed reaches ("jeni sai") — see the
|
|
1916
|
+
# reference.
|
|
1917
|
+
if stop?(word) || phonetic.include?(word) || !is_given.call(word)
|
|
1861
1918
|
index += 1
|
|
1862
1919
|
next
|
|
1863
1920
|
end
|
|
@@ -1996,6 +2053,10 @@ module Vicary
|
|
|
1996
2053
|
)
|
|
1997
2054
|
written_as_a_capital = casing.written_as_a_capital
|
|
1998
2055
|
lower_cased = casing.written_in_lower_case
|
|
2056
|
+
# Read off the same casing pass, so a spelling the writer capitalises
|
|
2057
|
+
# mid-sentence is never one of them; and only where a given-name oracle
|
|
2058
|
+
# exists, because it only withdraws what the tier proposed or vouched for.
|
|
2059
|
+
phonetic = given_name.nil? ? Set.new : phonetic_function_words(text, written_as_a_capital)
|
|
1999
2060
|
stray_capitals = mid_sentence_corroboration && !given_name.nil? &&
|
|
2000
2061
|
capitalises_ordinary_words?(text, headings)
|
|
2001
2062
|
|
|
@@ -2007,7 +2068,7 @@ module Vicary
|
|
|
2007
2068
|
tokens = words(span)
|
|
2008
2069
|
# A long all-caps run means the capitalisation told us nothing, so the
|
|
2009
2070
|
# stoplist is carrying the whole decision.
|
|
2010
|
-
trim(tokens).each do |run|
|
|
2071
|
+
trim(tokens, phonetic).each do |run|
|
|
2011
2072
|
next if run.empty?
|
|
2012
2073
|
|
|
2013
2074
|
joined = run.join(" ")
|
|
@@ -2078,7 +2139,7 @@ module Vicary
|
|
|
2078
2139
|
# evidence to offer and is better served by it.
|
|
2079
2140
|
find_lowercase_candidates(
|
|
2080
2141
|
text, given_name, is_protected,
|
|
2081
|
-
habit == LOWERCASE ? nil : written_as_a_capital, settlement
|
|
2142
|
+
habit == LOWERCASE ? nil : written_as_a_capital, settlement, phonetic
|
|
2082
2143
|
).each do |candidate|
|
|
2083
2144
|
next if claimed.any? { |s, e| candidate.start < e && candidate.end > s }
|
|
2084
2145
|
|
data/lib/vicary/version.rb
CHANGED
|
@@ -6,5 +6,5 @@ module Vicary
|
|
|
6
6
|
# Shared across all three front doors on purpose: one detector, one number. A
|
|
7
7
|
# gem 0.3.0 that corresponds to nothing on PyPI cannot be reasoned about, and
|
|
8
8
|
# the parity claim is between *versions*, not between package names.
|
|
9
|
-
VERSION = "0.2.
|
|
9
|
+
VERSION = "0.2.17"
|
|
10
10
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: vicary
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.17
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Blake Thomas
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: |
|
|
14
14
|
Finds the names a student writes about — classmates, teachers, relatives — and
|