Image sets: a counter in the name ends the set; copy markers, resolutions, _00 go
Each image was a release of its own in: "Set 008 10of63 new0464.jpg", "202/430 princess-079-058.jpg", "( 098 /500) 002 148.jpg" (the counter is part of the name: the set is the text before it), "sexypattycake_0903040445[1].jpg" (a copy's marker), "092_081_2000x1500.jpg" (a resolution) and "KP0027_197_00.jpg" (a constant suffix). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e72a9b1ef5
commit
108d798d97
3 files changed
+35
-4
No files matched your search
+19
-2
@@ -417,7 +417,15 @@ static DOCUMENT: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)\.(pdf|epub|mobi|az
|
|||||||
/// imageSet (lib/release/identity.ts): the name up to the number that counts the images, digits kept.
|
/// imageSet (lib/release/identity.ts): the name up to the number that counts the images, digits kept.
|
||||||
pub fn image_set(stem: &str) -> String {
|
pub fn image_set(stem: &str) -> String {
|
||||||
// .replace(/(\d+)\s*of\s*\d+/gi, '$1')
|
// .replace(/(\d+)\s*of\s*\d+/gi, '$1')
|
||||||
let mut s = OF_TOTAL.replace_all(stem.as_bytes(), &b"$1"[..]).into_owned();
|
// Suffixes that number no image: a copy's ("…[1]"), a resolution ("…_2000x1500"), a constant one ("…_00").
|
||||||
|
let mut s = stem.as_bytes().to_vec();
|
||||||
|
for re in [&*COPY_MARK, &*RESOLUTION, &*ZERO_SUFFIX] {
|
||||||
|
s = re.replace(&s, &b""[..]).into_owned();
|
||||||
|
}
|
||||||
|
// A counter in the name counts the images: the set is the text before it ("Set 008 10of63 new0464").
|
||||||
|
if let Some(m) = NAME_COUNTER.find(&s) {
|
||||||
|
return String::from_utf8_lossy(&s[..m.start()]).into_owned();
|
||||||
|
}
|
||||||
// A camera's timestamp ("kurozo-2006-7-26-15-21"): the date and the time after it number no set.
|
// A camera's timestamp ("kurozo-2006-7-26-15-21"): the date and the time after it number no set.
|
||||||
let s_ts = TIMESTAMP.replace(&s, &b""[..]).into_owned();
|
let s_ts = TIMESTAMP.replace(&s, &b""[..]).into_owned();
|
||||||
s = s_ts;
|
s = s_ts;
|
||||||
@@ -461,7 +469,10 @@ fn trim_zeros(d: &[u8]) -> &[u8] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static TIMESTAMP: LazyLock<Regex> = LazyLock::new(|| re(r"[-_. ]?(?:19|20)[0-9]{2}[-._ ](?:0?[1-9]|1[0-2])[-._ ][0-9]{1,2}(?:[-._ ][0-9]{1,2})*$"));
|
static TIMESTAMP: LazyLock<Regex> = LazyLock::new(|| re(r"[-_. ]?(?:19|20)[0-9]{2}[-._ ](?:0?[1-9]|1[0-2])[-._ ][0-9]{1,2}(?:[-._ ][0-9]{1,2})*$"));
|
||||||
static OF_TOTAL: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)([0-9]+)SP*ofSP*[0-9]+"));
|
static COPY_MARK: LazyLock<Regex> = LazyLock::new(|| re(r"SP*[\[(][0-9]+[\])]$"));
|
||||||
|
static RESOLUTION: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)[_-][0-9]{3,4}x[0-9]{3,4}$"));
|
||||||
|
static ZERO_SUFFIX: LazyLock<Regex> = LazyLock::new(|| re(r"[_-]0+$"));
|
||||||
|
static NAME_COUNTER: LazyLock<Regex> = LazyLock::new(|| re(r"(?i)([0-9]+)SP*ofSP*[0-9]+|[\[(]?SP*[0-9]+SP*/SP*[0-9]+SP*[\])]?"));
|
||||||
|
|
||||||
fn image_prefix(stem: &str) -> String {
|
fn image_prefix(stem: &str) -> String {
|
||||||
let b = stem.as_bytes();
|
let b = stem.as_bytes();
|
||||||
@@ -1187,6 +1198,12 @@ mod image_set_tests {
|
|||||||
("108 - Schoolwall kate108lg029_28", "108 - Schoolwall kate108lg"),
|
("108 - Schoolwall kate108lg029_28", "108 - Schoolwall kate108lg"),
|
||||||
("kurozo-2006-7-26-15-21", ""),
|
("kurozo-2006-7-26-15-21", ""),
|
||||||
("bwp2_037_5", "bwp2_"),
|
("bwp2_037_5", "bwp2_"),
|
||||||
|
("Set 008 10of63 new0464", "Set 008 "),
|
||||||
|
("202/430 princess-079-058", ""),
|
||||||
|
("( 098 /500) 002 148", ""),
|
||||||
|
("New Folder (17) sexypattycake_0903040445[1]", "New Folder ("),
|
||||||
|
("092_081_2000x1500", "092_"),
|
||||||
|
("KP0027_197_00", "KP"),
|
||||||
("JimAndJoey Kindly Husband-to-Be", ""),
|
("JimAndJoey Kindly Husband-to-Be", ""),
|
||||||
] {
|
] {
|
||||||
assert_eq!(image_set(stem), want, "{stem}");
|
assert_eq!(image_set(stem), want, "{stem}");
|
||||||
|
|||||||
+10
-2
@@ -146,13 +146,21 @@ const DATES = /\b(?:(?:19|20)\d{2}[-._ ](?:0?[1-9]|1[0-2])[-._ ]\d{1,2}|\d{1,2}[
|
|||||||
* "stp250x", "cutie-071-032" → "cutie-071-"); empty for a name without numbers. Suffixes after it that don't
|
* "stp250x", "cutie-071-032" → "cutie-071-"); empty for a name without numbers. Suffixes after it that don't
|
||||||
* count the images go first: a repeat of the number before (katelg010_10), a year (hgrscans1097_2009), a
|
* count the images go first: a repeat of the number before (katelg010_10), a year (hgrscans1097_2009), a
|
||||||
* size of 4+ digits (…_24of40_1600), and an "of" total (24of40) (LOG.md 2026-10-12 (3)); also a renumbering
|
* size of 4+ digits (…_24of40_1600), and an "of" total (24of40) (LOG.md 2026-10-12 (3)); also a renumbering
|
||||||
* right after it (kate108lg029_28) and a camera's timestamp (kurozo-2006-7-26-15-21) (LOG.md 2026-10-12 (5)).
|
* right after it (kate108lg029_28) and a camera's timestamp (kurozo-2006-7-26-15-21) (LOG.md 2026-10-12 (5)); a
|
||||||
|
* counter in the name ends the set, and copy markers, resolutions and "_00" go first (LOG.md 2026-10-12 (6)).
|
||||||
*/
|
*/
|
||||||
const TIMESTAMP = /[-_. ]?(?:19|20)\d{2}[-._ ](?:0?[1-9]|1[0-2])[-._ ]\d{1,2}(?:[-._ ]\d{1,2})*$/
|
const TIMESTAMP = /[-_. ]?(?:19|20)\d{2}[-._ ](?:0?[1-9]|1[0-2])[-._ ]\d{1,2}(?:[-._ ]\d{1,2})*$/
|
||||||
|
|
||||||
export function imageSet(stem: string): string {
|
export function imageSet(stem: string): string {
|
||||||
|
// Suffixes that number no image: a copy's ("sexypattycake_0903040445[1]"), a resolution ("092_081_2000x1500"),
|
||||||
|
// a constant one ("KP0027_197_00").
|
||||||
|
const plain = stem.replace(/\s*[[(]\d+[\])]$/, '').replace(/[_-]\d{3,4}x\d{3,4}$/i, '').replace(/[_-]0+$/, '')
|
||||||
|
// A counter in the name counts the images: the set is the text before it ("Set 008 10of63 new0464",
|
||||||
|
// "202/430 princess-079-058", "( 098 /500) 002 148"; each image was a release of its own).
|
||||||
|
const counted = /(\d+)\s*of\s*\d+|[[(]?\s*\d+\s*\/\s*\d+\s*[\])]?/i.exec(plain)
|
||||||
|
if (counted) return plain.slice(0, counted.index)
|
||||||
// A camera's timestamp ("kurozo-2006-7-26-15-21"): the date and the time after it number no set.
|
// A camera's timestamp ("kurozo-2006-7-26-15-21"): the date and the time after it number no set.
|
||||||
let s = stem.replace(/(\d+)\s*of\s*\d+/gi, '$1').replace(TIMESTAMP, '')
|
let s = plain.replace(TIMESTAMP, '')
|
||||||
while (true) {
|
while (true) {
|
||||||
const m = /[_-](\d+)$/.exec(s)
|
const m = /[_-](\d+)$/.exec(s)
|
||||||
if (!m) break
|
if (!m) break
|
||||||
|
|||||||
@@ -238,6 +238,12 @@ test.group('release / par2 names', () => {
|
|||||||
['108 - Schoolwall kate108lg029_28', '108 - Schoolwall kate108lg'],
|
['108 - Schoolwall kate108lg029_28', '108 - Schoolwall kate108lg'],
|
||||||
['kurozo-2006-7-26-15-21', ''],
|
['kurozo-2006-7-26-15-21', ''],
|
||||||
['bwp2_037_5', 'bwp2_'],
|
['bwp2_037_5', 'bwp2_'],
|
||||||
|
['Set 008 10of63 new0464', 'Set 008 '],
|
||||||
|
['202/430 princess-079-058', ''],
|
||||||
|
['( 098 /500) 002 148', ''],
|
||||||
|
['New Folder (17) sexypattycake_0903040445[1]', 'New Folder ('],
|
||||||
|
['092_081_2000x1500', '092_'],
|
||||||
|
['KP0027_197_00', 'KP'],
|
||||||
['JimAndJoey Kindly Husband-to-Be', ''],
|
['JimAndJoey Kindly Husband-to-Be', ''],
|
||||||
]) assert.equal(imageSet(stem), set, stem)
|
]) assert.equal(imageSet(stem), set, stem)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in new issue
Block a user