User:Ohconfucius/test/MOSNUM utils.js: Difference between revisions

Content deleted Content added
+ warning about false positives with date tokens
Blanked the page
Tag: Blanking
 
(2 intermediate revisions by one other user not shown)
Line 1:
/**
* TemplateScript adds configurable templates and scripts to the sidebar, and adds an example regex editor.
* @see https://meta.wikimedia.org/wiki/TemplateScript
* @update-token [[File:pathoschild/templatescript.js]]
*/
mw.loader.load('//tools-static.wmflabs.org/meta/scripts/pathoschild.templatescript.js');
 
var ohc = ohc || {};
 
/**
* Provides internal utilities for manipulating dates in wikitext.
*/
ohc.dateutil = {
/**
* Get the raw pattern from a regular expression object. For example, this
* function will convert /x+/ig into "x+".
* @param {object} s The regular expression to convert.
*/
regex_to_string: function(s) {
return s.toString()
.replace(/^\//, "")
.replace(/\/[^\/]*$/, "");
},
/**
* Show an alert containing an error message.
* @param {string} s The message to display.
* @param {object} reg The regular expression that caused the error.
*/
alert_error: function(s, reg) { //reg can be undefined
var message = "DATES SCRIPT:\n" + s;
if (reg !== undefined)
message += "\n\nRegex" + reg;
message += "\n\nPlease report the name of the article to [????]";
alert(message);
},
/**
* Replace regular expression patterns in the given text. The given regex
* and substitution strings can contain tokens that specify the date format
* to accept and the date format to convert the date to. Leading and
* trailing slashes are not needed for the regex.
*
* The tokens can be either capturing or non-capturing. The capturing
* tokens make their output available for later processing. Most of the
* capturing tokens can be used in the output with equivalent meaning.
*
* Internally, the routine maintains information about several dates, so
* the regex can contain more than one token specifying day, month or year.
* The first date will be assigned the first occurrences of tokens from
* each group, the second date will be assigned the second occurrences and
* so on. For example, if the regex is '@MM @DD @YYYY, @Month @ZM @Day',
* the first date will be assigned @MM as months, @DD as days and @YYYY as
* years. The second date will be assigned @Month as months and @Day as
* days. The third date will be assigned @ZM as months.
*
* If used in the replacement string, all tokens in the format @XX will
* output the data of the first date. To access the subsequent dates,
* tokens in the format @XX2, @XX3, and so on must be used. @XX1 is
* provided as alias to @XX for convenience.
*
* AVAILABLE REGEX TOKENS
* ======================
* Note: The capturing tokens start with an uppercase letter whereas the
* equivalent non-capturing tokens start with a lowercase letter.
*
* Warning: These tokens should only be used in patterns that contain the
* expected date pattern (like /@YYYY-@ZM-@ZD/), because they're not restricted
* to valid matches. For example, /@ZD/ (zero-padded day) will match the
* '20' and '14' in 2014.
*
* Days:
* • @SD : Matches a day in numeric format without leading zero (1..31).
* • @ZD : Matches a day in numeric format with leading zero (01..31).
* • @DD : Matches a day in numeric format with optional leading zero (@SD or @ZD).
* • @Day : Matches a day in numeric format with optional leading zero, with optional st, nd or th suffix. Equivalent to @DD@th?
* • @sd, @zd, ... : noncapturing equivalents.
* • @th : Matches st, nd, rd or th.
*
* Months:
* • @SM : Matches a month in numeric format without leading zero (1,2..12).
* • @ZM : Matches a month in numeric format with leading zero (01,02..12).
* • @MM : Matches a month in numeric format with optional leading zero (@SM or @ZM).
* • @FullMonth : Matches a full month name (January, February).
* • @Mon : Matches a short month name (Jan, Feb, ..). Also optionally matches dot (Jan., Feb., ..) and 'Sept', 'Sept.'.
* • @Month : Matches a full or short month name (@FullMonth or @Mon).
* • @sm, @zm, ... : noncapturing equivalents.
*
* Years:
* • @YYYY : Matches a 4-digit year.
* • @YY : Matches a 2-digit year. 50-99 are interpreted as 1950..1999, 0-49 are interpreted as 2000-2049.
* • @YYNN : Matches a 4 or 2-digit year (@YYYY or @YY).
* • @Year : Matches a 1 to 4 digit year.
* • @yyyy, @yy, ... : noncapturing equivalents.
*
* Special tokens:
* • @@ : Matches a literal @.
*
* AVAILABLE REPLACEMENT STRING TOKENS
* ===================================
* Days:
* • @SD : Outputs a day in numeric format without leading zero (1-31).
* • @ZD : Outputs a day in numeric format with leading zero (01-31).
* • @DD : Equivalent to @ZD.
* • @Day : Equivalent to @SD.
* • @LDay : Outputs the matched day string without any transformations.
* • @SDn, @ZDn, ... : Where n is integer, outputs the day of the nth date in the specified format.
*
* Months:
* • @SM : Outputs a month in numeric format without leading zero (1-12).
* • @ZM : Outputs a month in numeric format with leading zero (01-12).
* • @MM : Equivalent to @ZM.
* • @FullMonth : Outputs a full name of a month (January, February).
* • @Mon : Outputs a short name of a month (Jan, Feb).
* • @Month : Equivalent to @FullMonth.
* • @LMonth : Outputs the matched month string without any transformations.
* • @SMn, @ZMn, ... : Where n is integer, outputs the month of the nth date in the specified format.
*
* Years:
* • @YYYY Outputs 4-digit year. Valid only if the year was not captured by @Year.
* • @YY Outputs 2-digit year. Outputs the last two digits of a year. Valid only if the year was not captured by @Year.
* • @YYNN Equivalent to @YYYY
* • @Year Outputs 1 to 4 digit number identifying a year. Equivalent to @YYYY if the year is between 1000 and 9999.
* • @LYear Outputs the matched year string without any transformations.
* • @YYYYn, @YYn, ... : Where n is integer, outputs the year of the nth date in the specified format.
*
* Special tokens:
* • @@ : Outputs a literal @.
*
* All tokens in the replacement string which refer to data which isn't
* defined will be replaced with '@ERROR@'.
*
* An optional function defining whether to make the replacement in particular
* cases can be provided. The function is supplied a number of parameters, each
* of which is an object defining the nth date as parsed by the routine. Each
* object contains numeric values of days, months and years as 'd', 'm' and 'y'
* properties respectively. Each value can be -1 if a token for that date
* value was not specified in the regex, or an error occurs. The function
* should return true if the replacement should be done, false otherwise.
*
* @param {string} text The text to change.
* @param {object|string} rg The regular expression to search in the text.
* @param {string} sub The pattern to replace matches with.
* @param {function} func A callback passed the matching date information
* which returns whether to continue with the replacement.
*/
regex: function(text, rg, sub, func) {
var reg = ohc.dateutil.regex_to_string(rg);
var debug_reg = reg;
var month_names = new Array("January", "February", "March", "April", "May",
"June", "July", "August", "September", "October", "November", "December");
var month_names_short = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
var MAX_DATE = 4;
var ParamType = {
REGULAR : 1,
SD : 10,
ZD : 11,
DD : 12,
DAY : 13,
SM : 20,
ZM : 21,
MM : 22,
FMONTH : 23,
MONTH : 24,
MON : 25,
YYYY : 30,
YYNN : 31,
YY : 32,
YEAR : 33
};
var Group = {
DAY : 0,
MONTH : 1,
YEAR : 2
};
var Formats = [
{ type : ParamType.SD, group : Group.DAY, token : "@SD", match : /([1-9]|[1-2][0-9]|30|31)/ },
{ type : ParamType.ZD, group : Group.DAY, token : "@ZD", match : /(0[1-9]|[1-2][0-9]|30|31)/ },
{ type : ParamType.DD, group : Group.DAY, token : "@DD", match : /(0?[1-9]|[1-2][0-9]|30|31)/ },
{ type : ParamType.DAY,group : Group.DAY, token : "@Day",match : /((?:[012]?[1-9]|10|20|30|31)(?:st|nd|rd|th|)?)/ },
{ type : ParamType.SM, group : Group.MONTH,token : "@SM", match : /([1-9]|10|11|12)/ },
{ type : ParamType.ZM, group : Group.MONTH,token : "@ZM", match : /(0[1-9]|10|11|12)/ },
{ type : ParamType.MM, group : Group.MONTH,token : "@MM", match : /(0?[1-9]|10|11|12)/ },
{
type : ParamType.FMONTH, group : Group.MONTH, token : "@FullMonth",
match : /(January|February|March|April|May|June|July|August|September|October|November|December)/
},
{
type : ParamType.MONTH, group : Group.MONTH, token : "@Month",
match : /(January|February|March|April|May|June|July|August|September|October|November|December|Jan\.|Jan|Feb\.|Feb|Mar\.|Mar|Apr\.|Apr|May|Jun\.|Jun|Jul\.|Jul|Aug\.|Aug|Sep\.|Sept\.|Sept|Sep|Oct\.|Oct|Nov\.|Nov|Dec\.|Dec)/
},
{ //must be after month entry
type : ParamType.MON, group : Group.MONTH, token : "@Mon",
match : /(Jan\.|Jan|Feb\.|Feb|Mar\.|Mar|Apr\.|Apr|May|Jun\.|Jun|Jul\.|Jul|Aug\.|Aug|Sep\.|Sept\.|Sept|Sep|Oct\.|Oct|Nov\.|Nov|Dec\.|Dec)/
},
{ type : ParamType.YYYY, group : Group.YEAR, token : "@YYYY", match : "([1-2][0-9]{3})" },
{ type : ParamType.YYNN, group : Group.YEAR, token : "@YYNN", match : "([1-2][0-9]{3}|[0-9]{2})" },
{ type : ParamType.YY, group : Group.YEAR, token : "@YY", match : "([0-9]{2})" }, //must be after yyyy and yy24 entries
{ type : ParamType.YEAR, group : Group.YEAR, token : "@Year", match : "([1-2][0-9]{3}|[1-9][0-9]{0,2})" }
];
var NCFormats = [
{ token : "@sd", match : /(?:[1-9]|[1-2][0-9]|30|31)/ },
{ token : "@zd", match : /(?:0[1-9]|[1-2][0-9]|30|31)/ },
{ token : "@dd", match : /(?:0?[1-9]|[1-2][0-9]|30|31)/ },
{ token : "@day",match : /(?:(?:[012]?[1-9]|10|20|30|31)(?:st|nd|rd|th|)?)/ },
{ token : "@sm", match : /(?:[1-9]|10|11|12)/ },
{ token : "@zm", match : /(?:0[1-9]|10|11|12)/ },
{ token : "@mm", match : /(?:0?[1-9]|10|11|12)/ },
{
token : "@fullmonth",
match : /(?:January|February|March|April|May|June|July|August|September|October|November|December)/
},
{
token : "@month",
match : /(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan\.|Jan|Feb\.|Feb|Mar\.|Mar|Apr\.|Apr|May|Jun\.|Jun|Jul\.|Jul|Aug\.|Aug|Sep\.|Sept\.|Sept|Sep|Oct\.|Oct|Nov\.|Nov|Dec\.|Dec)/
},
{ //must be after month entry
token : "@mon",
match : /(?:Jan\.|Jan|Feb\.|Feb|Mar\.|Mar|Apr\.|Apr|May|Jun\.|Jun|Jul\.|Jul|Aug\.|Aug|Sep\.|Sept\.|Sept|Sep|Oct\.|Oct|Nov\.|Nov|Dec\.|Dec)/
},
{ token : "@yyyy", match : /(?:[1-2][0-9]{3})/ },
{ token : "@yynn", match : "(?:[1-2][0-9]{3}|[0-9]{2})" },
{ token : "@yy", match : "(?:[0-9]{2})" }, //must be after yyyy and yy24 entries
{ token : "@year", match : "(?:[1-2][0-9]{3}|[1-9][0-9]{0,2})" },
// misc
{ token : "@th", match : "(?:th|st|nd|rd)" }
];
// get positions of all capturing matches in the regex
var params_by_index = {};
var capt_regex = /(?:^|[^\\])\((?!(?:\?:|\?=|\?!))/g;
var match;
var pi = 0;
while (match = capt_regex.exec(reg)) {
var param = {};
param.index = match.index;
param.type = ParamType.REGULAR;
param.num = pi;
params_by_index[match.index] = param;
pi++;
}
// get positions of all capturing tokens in the regex
var token_per_group = [0,0,0];
for (var i = 0; i < Formats.length; i++) {
var index = -1;
while (1) {
index = reg.indexOf(Formats[i].token, index+1);
if (index == -1)
break;
if (params_by_index[index] === undefined) {
if (token_per_group[index] > MAX_DATE) {
alert("DATE SCRIPT: unsupported number of dates from the same group");
return;
}
var param = {};
param.index = index;
param.type = Formats[i].type;
param.num = token_per_group[Formats[i].group];
params_by_index[index] = param;
token_per_group[Formats[i].group]++;
}
}
}
// pack the resulting array and sort by index
var param_desc = [];
for (var i in params_by_index) {
param_desc.push(params_by_index[i]);
}
param_desc.sort(function(a,b) {return a.index - b.index;});
//replace tokens with proper matches
for (var i = 0; i < Formats.length; i++) {
reg = reg.split(Formats[i].token).join(ohc.dateutil.regex_to_string(Formats[i].match));
}
for (var i = 0; i < NCFormats.length; i++) {
reg = reg.split(NCFormats[i].token).join(ohc.dateutil.regex_to_string(NCFormats[i].match));
}
reg = reg.split("@@").join("@");
//inline function for month parsing
function parse_month(str) {
var imonth = str.toLowerCase();
for (var i = 0; i < month_names_short.length; i++) {
if (imonth.substr(0,3) == month_names_short[i].toLowerCase()) {
return i+1;
}
}
return -1;
}
//inline function for 2-digit year parsing
function parse_yy(str) {
var y = parseInt(str, 10);
if (y > 99) {
return -1;
}
else if (y >= 20) {
return y + 1900;
}
else {
return y + 2000;
}
}
//inline function which will do the replacement
function regex_worker(str, m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10,
m11, m12, m13, m14, m15, m16, m17, m18, m19) {
var MAX_REGEX = 20;
// computed numeric values
var day = [];
var month = [];
var year = [];
// string values to output
var raw_day = [];
var raw_month = [];
var raw_year = [];
var sday = [];
var zday = [];
var smonth = [];
var zmonth = [];
var full_month = [];
var short_month = [];
var year_yy = [];
var year_yyyy = [];
var regex_param = [];
//fill in the initial values
for (var i = 0; i < MAX_DATE; i++) {
raw_day[i] = raw_month[i] = raw_year[i] = "@ERROR@";
sday[i] = zday[i] = smonth[i] = zmonth[i] = full_month[i] = short_month[i] = "@ERROR@";
year_yy[i] = year_yyyy[i] = "@ERROR@";
day[i] = month[i] = year[i] = -1;
}
// save all arguments as an array
var params = [];
params.push(m0); params.push(m1); params.push(m2); params.push(m3);
params.push(m4); params.push(m5); params.push(m6); params.push(m7);
params.push(m8); params.push(m9); params.push(m10); params.push(m11);
params.push(m12); params.push(m13); params.push(m14); params.push(m15);
params.push(m16); params.push(m17); params.push(m18); params.push(m19);
// parse the arguments according to the specification given as param_desc
for (var i = 0; i < param_desc.length; i++) {
if (i > 19) {
alert("DATE SCRIPT: param id out of bounds");
return str;
}
var c_param = params[i]; //current param
var c_desc = param_desc[i]; //current param description
switch (c_desc.type) {
case ParamType.REGULAR:
regex_param[c_desc.num] = c_param;
break;
case ParamType.SD:
case ParamType.ZD:
case ParamType.DD:
day[c_desc.num] = parseInt(c_param, 10);
raw_day[c_desc.num] = c_param;
break;
case ParamType.DAY:
day[c_desc.num] = parseInt(c_param.replace(/[^0-9]/g, ''), 10);
raw_day[c_desc.num] = c_param;
break;
case ParamType.SM:
case ParamType.ZM:
case ParamType.MM:
month[c_desc.num] = parseInt(c_param, 10);
raw_month[c_desc.num] = c_param;
break;
case ParamType.FMONTH:
case ParamType.MONTH:
case ParamType.MON:
month[c_desc.num] = parse_month(c_param);
raw_month[c_desc.num] = c_param;
break;
case ParamType.YY:
year[c_desc.num] = parse_yy(c_param);
raw_year[c_desc.num] = c_param;
break;
case ParamType.YEAR:
case ParamType.YYYY:
year[c_desc.num] = parseInt(c_param, 10);
raw_year[c_desc.num] = c_param;
break;
case ParamType.YYNN:
var yy = parse_yy(c_param, 10);
if (yy == -1) {
yy = parseInt(c_param, 10);
}
year[c_desc.num] = yy;
raw_year[c_desc.num] = c_param;
break;
}
}
//catch errors, if any
for (var i = 0; i < MAX_DATE; i++) {
if (day[i] == 0 || day[i] < -1 || day[i] > 31) {
ohc.dateutil.alert_error("Invalid day [" + i + "]=" + day[i], debug_reg);
day[i] = -1;
}
if (month[i] == 0 || month[i] < -1 || month[i] > 12) {
ohc.dateutil.alert_error("Invalid month [" + i + "]=" + month[i], debug_reg);
month[i] = -1;
}
if (year[i] == 0 || year[i] < -1 || year[i] > 9999) {
ohc.dateutil.alert_error("Invalid year [" + i + "]=" + year[i], debug_reg);
year[i] = -1;
}
}
//check whether to make the replacement
if (func !== undefined) {
var d = [];
for (var i = 0; i < MAX_DATE; i++) {
var di = {};
di.d = day[i]; di.m = month[i]; di.y = year[i];
d.push(di);
}
if (func(d[0], d[1], d[2], d[3]) === false) {
return str;
}
}
//compute all needed formats
for (var i = 0; i < MAX_DATE; i++) {
if (day[i] != -1) {
zday[i] = sday[i] = day[i].toString();
if (day[i] < 10) {
zday[i] = "0" + zday[i];
}
}
if (month[i] != -1) {
zmonth[i] = smonth[i] = month[i].toString();
if (month[i] < 10) {
zmonth[i] = "0" + zmonth[i];
}
full_month[i] = month_names[month[i]-1];
short_month[i] = month_names_short[month[i]-1];
}
if (year[i] != -1) {
year_yyyy[i] = year[i].toString();
if (year[i] >= 1950 && year[i] < 2050) {
year_yy[i] = year_yyyy[i].charAt(2) + year_yyyy[i].charAt(3);
}
}
}
//replace
var csub = sub;
csub = csub.split("$1").join(regex_param[0]);
csub = csub.split("$2").join(regex_param[1]);
csub = csub.split("$3").join(regex_param[2]);
csub = csub.split("$4").join(regex_param[3]);
csub = csub.split("$5").join(regex_param[4]);
csub = csub.split("$6").join(regex_param[5]);
csub = csub.split("$7").join(regex_param[6]);
csub = csub.split("$8").join(regex_param[7]);
csub = csub.split("$9").join(regex_param[8]);
csub = csub.split("$10").join(regex_param[9]);
csub = csub.split("$11").join(regex_param[10]);
csub = csub.split("$12").join(regex_param[11]);
csub = csub.split("$13").join(regex_param[12]);
csub = csub.split("$14").join(regex_param[13]);
csub = csub.split("$15").join(regex_param[14]);
csub = csub.split("$16").join(regex_param[15]);
csub = csub.split("$17").join(regex_param[16]);
csub = csub.split("$18").join(regex_param[17]);
csub = csub.split("$19").join(regex_param[18]);
csub = csub.split("$20").join(regex_param[19]);
csub = csub.split("@SD4").join(sday[3]);
csub = csub.split("@ZD4").join(zday[3]);
csub = csub.split("@DD4").join(zday[3]);
csub = csub.split("@Day4").join(sday[3]);
csub = csub.split("@LDay4").join(raw_day[3]);
csub = csub.split("@SM4").join(smonth[3]);
csub = csub.split("@ZM4").join(zmonth[3]);
csub = csub.split("@MM4").join(zmonth[3]);
csub = csub.split("@FullMonth4").join(full_month[3]);
csub = csub.split("@Month4").join(full_month[3]);
csub = csub.split("@Mon4").join(short_month[3]);
csub = csub.split("@LMonth4").join(raw_month[3]);
csub = csub.split("@YYYY4").join(year_yyyy[3]);
csub = csub.split("@YYNN4").join(year_yyyy[3]);
csub = csub.split("@Year4").join(year_yyyy[3]);
csub = csub.split("@YY4").join(year_yy[3]);
csub = csub.split("@LYear4").join(raw_year[3]);
csub = csub.split("@SD3").join(sday[2]);
csub = csub.split("@ZD3").join(zday[2]);
csub = csub.split("@DD3").join(zday[2]);
csub = csub.split("@Day3").join(sday[2]);
csub = csub.split("@LDay3").join(raw_day[2]);
csub = csub.split("@SM3").join(smonth[2]);
csub = csub.split("@ZM3").join(zmonth[2]);
csub = csub.split("@MM3").join(zmonth[2]);
csub = csub.split("@FullMonth3").join(full_month[2]);
csub = csub.split("@Month3").join(full_month[2]);
csub = csub.split("@Mon3").join(short_month[2]);
csub = csub.split("@LMonth3").join(raw_month[2]);
csub = csub.split("@YYYY3").join(year_yyyy[2]);
csub = csub.split("@YYNN3").join(year_yyyy[2]);
csub = csub.split("@Year3").join(year_yyyy[2]);
csub = csub.split("@YY3").join(year_yy[2]);
csub = csub.split("@LYear3").join(raw_year[2]);
csub = csub.split("@SD2").join(sday[1]);
csub = csub.split("@ZD2").join(zday[1]);
csub = csub.split("@DD2").join(zday[1]);
csub = csub.split("@Day2").join(sday[1]);
csub = csub.split("@LDay2").join(raw_day[1]);
csub = csub.split("@SM2").join(smonth[1]);
csub = csub.split("@ZM2").join(zmonth[1]);
csub = csub.split("@MM2").join(zmonth[1]);
csub = csub.split("@FullMonth2").join(full_month[1]);
csub = csub.split("@Month2").join(full_month[1]);
csub = csub.split("@Mon2").join(short_month[1]);
csub = csub.split("@LMonth2").join(raw_month[1]);
csub = csub.split("@YYYY2").join(year_yyyy[1]);
csub = csub.split("@YYNN2").join(year_yyyy[1]);
csub = csub.split("@Year2").join(year_yyyy[1]);
csub = csub.split("@YY2").join(year_yy[1]);
csub = csub.split("@LYear2").join(raw_year[1]);
csub = csub.split("@SD1").join(sday[0]);
csub = csub.split("@ZD1").join(zday[0]);
csub = csub.split("@DD1").join(zday[0]);
csub = csub.split("@Day1").join(sday[0]);
csub = csub.split("@LDay1").join(raw_day[0]);
csub = csub.split("@SM1").join(smonth[0]);
csub = csub.split("@ZM1").join(zmonth[0]);
csub = csub.split("@MM1").join(zmonth[0]);
csub = csub.split("@FullMonth1").join(full_month[0]);
csub = csub.split("@Month1").join(full_month[0]);
csub = csub.split("@Mon1").join(short_month[0]);
csub = csub.split("@LMonth1").join(raw_month[0]);
csub = csub.split("@YYYY1").join(year_yyyy[0]);
csub = csub.split("@YYNN1").join(year_yyyy[0]);
csub = csub.split("@Year1").join(year_yyyy[0]);
csub = csub.split("@YY1").join(year_yy[0]);
csub = csub.split("@LYear1").join(raw_year[0]);
csub = csub.split("@SD").join(sday[0]);
csub = csub.split("@ZD").join(zday[0]);
csub = csub.split("@DD").join(zday[0]);
csub = csub.split("@Day").join(sday[0]);
csub = csub.split("@LDay").join(raw_day[0]);
csub = csub.split("@SM").join(smonth[0]);
csub = csub.split("@ZM").join(zmonth[0]);
csub = csub.split("@MM").join(zmonth[0]);
csub = csub.split("@FullMonth").join(full_month[0]);
csub = csub.split("@Month").join(full_month[0]); //this must be executed before the @Mon rule
csub = csub.split("@Mon").join(short_month[0]);
csub = csub.split("@LMonth").join(raw_month[0]);
csub = csub.split("@YYYY").join(year_yyyy[0]); //this must be executed before the @YY rule
csub = csub.split("@YYNN").join(year_yyyy[0]);
csub = csub.split("@Year").join(year_yyyy[0]);
csub = csub.split("@YY").join(year_yy[0]);
csub = csub.split("@LYear").join(raw_year[0]);
csub = csub.split("@@").join("@");
return csub;
}
//check whether a simple regex (i.e. without using regex_worker) would suffice
var simple_regex = true;
for (var i = 0; i < param_desc.length; i++) {
if (param_desc[i].type != ParamType.REGULAR) {
simple_regex = false;
break;
}
}
//do the replacement
try {
var rg = new RegExp(reg,'gi');
if (simple_regex == true)
text = text.replace(rg, sub);
else
text = text.replace(rg, regex_worker);
var aa_reg = debug_reg; //place for a breakpoint for debugging
}
catch(err) {
var message = "Error in regex execution\n" + "ERROR: " + err.message + "\n";
ohc.dateutil.alert_error(message, debug_reg);
}
return text;
}
};
 
/**
* Extends string objects with a chainable method to replace patterns containing
* special date tokens.
* @see ohc.dateutils.regex
*/
String.prototype.ohc_regex = function(rg, sub, func) {
return ohc.dateutil.regex(this.toString(), rg, sub, func);
};