-
-
Save totten/acff49e6dd77947349a1df26d5002003 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
## The script will walk through a series of filters, display a preview for each, | |
## and ask if you want to apply them. | |
## | |
## USAGE: php relnote.php release-notes/X.Y.Z.md | |
## | |
## REQUIRES: php, colordiff | |
## SEE: https://gist.github.com/totten/acff49e6dd77947349a1df26d5002003 | |
######################################################################## | |
## Config | |
$diffCommand = 'colordiff -u %s %s | less -R'; | |
######################################################################## | |
## Filters | |
$filters = [ | |
// Ex: "core#10" ==> "dev/core#10" | |
'Full lab ref' => function($l) { return preg_replace(';([^/])(core|report|wordpress|drupal)#(\d+);', '\1dev/\2#\3', $l); }, | |
// Ex: "[NFC] Foo" or "NFC - Foo" ==> "(NFC) Foo" | |
'(NFC)' => function($l) { return preg_replace(';[\[\(]NFC[\]\)]( -)?;i', '(NFC)', $l); }, | |
// Ex: "[REF] Foo" or "REF - Foo" ==> "(REF) Foo" | |
'(REF)' => function($l) { return preg_replace(';[\[\(]REF[\]\)]( -)?;i', '(REF)', $l); }, | |
// Ex: "**NFC Foo**" ==> "**(NFC) Foo*" | |
'(NFC|REF) leading parens' => function($l) { return preg_replace(';(- \*\*)(NFC|REF)( -)? ;i', '\1(\2) ', $l); }, | |
// Ex: "**dev/core#123 Foo**" ==> "**(dev/core#123) Foo**" | |
'(dev/foo) leading parens' => function($l) { return preg_replace(';(- \*\*)(' . labRef(). ')( -|:)? ;', '\1(\2) ', $l); }, | |
// Ex: **[dev/core#123] Foo**" ==> "**(dev/core#123) Foo**" | |
'(dev/foo) not [dev/foo]' => function($l) { return preg_replace(';(- \*\*)\[(' . labRef(). ')\]( -|:)? ;', '\1(\2) ', $l); }, | |
// Ex: "**fixes dev/core#123 foo**" ==> "**(dev/core#123) foo**" | |
'Skip leading "fixes"' => function($l) { return preg_replace(';(- \*\*)fixes (dev/\w+#\d+)( -|:)? ;', '\1(\2) ', $l); }, | |
// Ex: "(NFC) foo bar" ==> "(NFC) Foo bar" | |
'ucfirst' => function($l){ | |
return preg_replace_callback(';(- \*\*)\((' .tagLabHubRef() .')\) ([\w\-_\/:]+);', | |
function($m){ | |
if (!looksSymbolic($m[3])) { | |
$m[3] = ucfirst($m[3]); | |
} | |
return sprintf('%s(%s) %s', $m[1], $m[2], $m[3]); | |
}, | |
$l); | |
}, | |
// Normalize words: These filters apply standard capitalization+spacing for some phrases that may be written several ways. | |
'APIv3' => normalizeWord('APIv3', ['api3', 'api v3']), | |
'APIv4' => normalizeWord('APIv4', ['api4', 'api v4']), | |
'SearchKit' => normalizeWord('SearchKit', ['Search kit', 'search_kit']), | |
'Flexmailer' => normalizeWord('Flexmailer', ['flexmail']), | |
// Normalize words: These filters apply standard capitalization for a long list of names and abbreviations. | |
'Civi Abbreviations' => normalizeWords(['BAO', 'DAO', 'PCP']), | |
'Civi Components' => normalizeWords(['Afform', 'AuthX', 'CiviCampaign', 'CiviCase', 'CiviContribute', 'CiviEvent', 'CiviGrant', 'CiviMail', 'CiviMember', 'CiviReport', 'CiviSMS', 'civix', 'cv', 'Greenwich', 'Shoreditch']), | |
'Industry Abbreviations' => normalizeWords(['ACL', 'CLI', 'CMS', 'ID', 'SMS', 'SQL', 'UI', 'URL', 'URLs']), | |
'Platform Names' => normalizeWords(['Backdrop', 'Drupal', 'D7', 'D8', 'D9', 'Joomla', 'JS', 'Javascript', 'MySQL', 'PHP', 'WordPress', 'WP']), | |
'Tool Names' => normalizeWords(['Angular', 'CKEditor', 'composer', 'drush', 'jQuery', 'KCFinder', 'Mosaico', 'PHPUnit', 'Smarty', 'WP-CLI']), | |
// 'dev/foo move to end' => function($l) { | |
// $urlRef = 'https?:[/\w\?\.%]+'; | |
// $link = '\[(' . $hubRef . '|' . $labRef . ')\]('. $urlRef . ')'; | |
// $listReg = "($hubRef|$labRef|$link)"; | |
// | |
// return preg_replace_callback(';(- \*\*)(' . hubRef() . ')\s*(.*);', | |
// function($m) use ($listReg) { | |
// [$full, $bullet, $leadingRef, $tail] = $m; | |
// if (preg_match(';(.*)\(((' . $listReg .').*)$;', $tail, $tailm)) { | |
// return $bullet . $tailm[1] . '(' . $leadingRef .': ' . $tailm[2]; | |
// } | |
// else { | |
// return $bullet . $tail . "($leadingRef)"; | |
// } | |
// }, | |
// $l); | |
// }, | |
]; | |
######################################################################## | |
## Utils | |
function hubRef(): string { return '#\d+'; } | |
function labRef(): string { return 'dev/\w+#\d+'; } | |
function tagLabHubRef(): string { return 'REF|NFC|' . hubRef() . '|' . labRef(); } | |
function normalizeWord(string $word, $aliases = []) { | |
$wordQuoted = preg_quote($word, ';'); | |
$aliases = implode('|', array_map( | |
function($alias) { return preg_quote($alias,';'); }, | |
$aliases | |
)); | |
return function($content) use ($word, $wordQuoted, $aliases) { | |
// We don't treat '.' or '/' as word-breaks because they often appear in long symbols (file-extensions, URLs, rel-paths). | |
$lwb = '[\s\*\(\)\[\]]'; | |
$rwb = '[\s\*\(\)\[\],]'; | |
$content = preg_replace(";($lwb)($wordQuoted)($rwb);i", '\1' . $word . '\3', $content); | |
if ($aliases) { | |
$content = preg_replace(";$aliases;i", $word, $content); | |
} | |
return $content; | |
}; | |
} | |
function normalizeWords(array $words) { | |
return function($content) use ($words) { | |
foreach ($words as $word) { | |
$content = normalizeWord($word)($content); | |
} | |
return $content; | |
}; | |
} | |
/** | |
* Does $string look a symbol (eg 'fooBar' or 'foo_bar')? | |
* | |
* @param $string | |
* @return bool | |
*/ | |
function looksSymbolic(string $string): bool { | |
if (preg_match(';[^a-zA-Z0-9];', $string)) { | |
return TRUE; | |
} | |
if (preg_match(';^[a-z]+[A-Z]+;', $string)) { | |
return TRUE; | |
} | |
if (preg_match(';^[A-Z0-9]+$];', $string)) { | |
return TRUE; | |
} | |
return FALSE; | |
} | |
######################################################################## | |
## Main | |
$currentFile = $argv[1]; | |
$currentContent = file_get_contents($currentFile); | |
$tempFile = tempnam(sys_get_temp_dir(), 'relnote-preview-'); | |
foreach ($filters as $filterName => $filter) { | |
$tempContent = $filter($currentContent); | |
if ($tempContent === $currentContent) { | |
echo "NO CHANGE: $filterName\n"; | |
continue; | |
} | |
printf("\n\n\nPREVIEW: Apply filter: $filterName\n\n"); | |
file_put_contents($tempFile, $tempContent); | |
passthru(sprintf('colordiff -u %s %s | less -R', $currentFile, $tempFile)); | |
do { | |
echo "ENABLE ($filterName)? (Y/n) "; | |
$s = trim(fgets(STDIN)); | |
} while (!in_array($s, ['y', 'n', ''])); | |
if (in_array($s, ['y', ''])) { | |
file_put_contents($currentFile, $tempContent); | |
$currentContent = $tempContent; | |
echo "APPLIED: $filterName\n"; | |
} | |
} | |
unlink($tempFile); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment