User:DemocraticLuntz/cenparse.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// <nowiki>
/**
 * Formats a Census page query. 
 * top_list is an array of a line in the files, 0th element is place name, 
 * 1st element is place type, 2nd element is county,
 * 3rd element is state
 * 
 * curr_geo is place 
 * 
 * 
 * Now changed to 0th element is est_column, then decennial begins at 4th
 */
CenPop.est_column=0;
CenPop.begin_decennial=4;
CenPop.removed_refs={};

CenPop.format_page_query = function(top_list,curr_geo,show_type,show_county)
{
    var place_name=top_list[0], place_type=top_list[1], county_name=top_list[2];
    var state_name=top_list[3], full_name=top_list[0];
    if(show_type && place_type === 'township') full_name+=' township';
    else if(show_type) full_name+=' ('+place_type+')';
    if(show_county) full_name+=', '+county_name; 
    /* Regardless of flag, we want county at beginning if we're doing counties */
    if(curr_geo==='county') { full_name = county_name; } 
    full_name+=', '+state_name;
    return full_name;
};
/**
 * Returns a string containing the US Census Population template as it currently
 * exists in the given page prior to any modifications we may make. We use this 
 * so that we can replace it later with our (possibly) different and updated 
 * data. 
 */
CenPop.get_pop_str = function(input) {
    var ret_str='',begin_re = new RegExp('\{\{USCensusPop|\{\{US[ \n\r]*Census[ \n\r]*population');
    var brace_depth=2,begin_pos=input.search(begin_re), curr_pos=0,in_len=input.length,curr_char;
    if(begin_pos===-1 && ($('#noMatch').html(+$('#noMatch').html() + 1)||true)) return '';
    curr_pos=begin_pos+2;
    while(brace_depth>0 && curr_pos < in_len) brace_depth+=(curr_char=input.charAt(curr_pos++))&&curr_char==='{'?1:(curr_char==='}'?-1:0);
    if(curr_pos<in_len && brace_depth===0 && input.charAt(curr_pos)==='\n') return input.slice(begin_pos,curr_pos+1);
    else if(curr_pos<in_len && brace_depth===0) return input.slice(begin_pos,curr_pos);
    else return '';
};

CenPop.get_last_unclosed_begin_ref = function(str_to_check) {
	/* Get last unclosed begin ref */
    var unclosed_name_re=/<ref[^\/\>]*>/g;
    const array = [...str_to_check.matchAll(unclosed_name_re)];
    if(array.length==0) return -1;
    return str_to_check.lastIndexOf(array[array.length-1][0]);
};

CenPop.parse_USCensusPop=function(match,p1,p2,p3) {
	var temp_removed_refs=[];
    var term_map = new Map(),results={},re1=new RegExp('\|');
    var begin_year=parseInt($('.beginYearText').val());
    var bar_list = match.slice(0,match.lastIndexOf('}}')).split('\|'); // slice off ending }}
    var temp_str='Split data\n',eq_list,depth={'bracket':0,'brace':0},curr;
    var footnote_str='',in_footnote=false,in_ref=false,i,j,last_beginref,last_endref;
    var last_closed_name_ref;
    var match_all_name_ref;
    var new_in_ref=false;
    var y, x;
    
    var closed_name_re=/ref name\=[^\/\>]*\/\>/;
    var in_other=false,other_name="";
    var char_str={'\\[\\[':['bracket',1],'\\]\\]':['bracket',-1],'\{\{':['brace',1],'\}\}':['brace',-1]},x;
    for (var elem in bar_list) {
    	new_in_ref=false;
		if(in_footnote && !in_ref && depth['brace']<=0 && depth['bracket']<=0) in_footnote=false;
		if(in_other && !in_ref && depth['brace']<=0 && depth['bracket']<=0) in_other=false;
		eq_list=bar_list[elem].split('\=');
		if(in_footnote) {
		    footnote_str+='|';
		    //last_beginref=bar_list[elem].lastIndexOf('<ref');
		    last_beginref = CenPop.get_last_unclosed_begin_ref(bar_list[elem]);
		    last_endref=bar_list[elem].lastIndexOf('</ref>');
		    if(last_beginref !== -1 && (last_endref === -1 || last_endref < last_beginref)) in_ref=true;
		    else if(last_endref !== -1) in_ref=false;
		    for(x in char_str) if((curr=bar_list[elem].match(x))) depth[char_str[x][0]]+=char_str[x][1]*curr.length;
		    footnote_str+=bar_list[elem].trim();
		}
		else if(in_other) {
		    results[other_name]+='|';
//		    last_beginref=bar_list[elem].lastIndexOf('<ref');
		    last_beginref = CenPop.get_last_unclosed_begin_ref(bar_list[elem]);

		    last_endref=bar_list[elem].lastIndexOf('</ref>');
		    if(last_beginref !== -1 && (last_endref === -1 || last_endref < last_beginref)) in_ref=true;
		    else if(last_endref !== -1) in_ref=false;
		    for(x in char_str) if((curr=bar_list[elem].match(x))) depth[char_str[x][0]]+=char_str[x][1]*curr.length;
		    results[other_name]+=bar_list[elem].trim();
		}
		else if(eq_list.length>=2) {
		    var first_str=eq_list[0].trim(),second_str=eq_list[1].trim();
		    if(first_str.match('footnote')!== null && (in_footnote=true)) {
				for(var j=1; j < eq_list.length; j++) {
				    if(j>1) footnote_str+='=';
				    //last_beginref=eq_list[j].lastIndexOf('<ref');
	    		    last_beginref = CenPop.get_last_unclosed_begin_ref(eq_list[j]);

				    last_endref=eq_list[j].lastIndexOf('</ref>');
				    if(last_beginref !== -1 &&  (last_endref === -1 || last_endref < last_beginref)) in_ref=true;
				    else if(last_endref !== -1) in_ref=false;
				    for(x in char_str) {
					if((curr=eq_list[j].match(x))) depth[char_str[x][0]]+=char_str[x][1]*curr.length; }
				    if(depth['bracket']<0) depth['bracket']=0;
				    footnote_str+=eq_list[j];
				}
		    }
		    else if(first_str.match('[0-9]+') !== null)
		    {
				second_int=parseInt(second_str);
				if(!isNaN(second_int) && second_int!==0) term_map.set(parseInt(first_str),second_int);
				else term_map.set(first_str,second_str);
		    }
		    else if(first_str.match('align')) term_map.set(first_str.trim(),second_str.trim());
		    else if(first_str.match('[0-9]+n')) term_map.set(first_str.trim(),second_str.trim());
		    else {
		    	in_other=true;
		    	other_name=first_str;
		    	results[first_str]=''
		    	for(var j=1; j < eq_list.length; j++) {
				    if(j>1) results[first_str]+='=';
				    //last_beginref=eq_list[j].lastIndexOf('<ref');
	    		    last_beginref = CenPop.get_last_unclosed_begin_ref(eq_list[j]);

				    last_endref=eq_list[j].lastIndexOf('</ref>');
				    if(last_beginref !== -1 &&  (last_endref === -1 || last_endref < last_beginref)) in_ref=true;
				    else if(last_endref !== -1) in_ref=false;
				    for(x in char_str) {
					if((curr=eq_list[j].match(x))) depth[char_str[x][0]]+=char_str[x][1]*curr.length; }
				    if(depth['bracket']<0) depth['bracket']=0;
				    results[first_str]+=eq_list[j];
				    //if(in_ref) results[first_str]+="=";
				}
		    
		    }
		}
    }
    results.term_map=term_map;
    results.footnote_str=footnote_str.trim();
    if(depth['brace']>=0) return results;
    return null;
};

/* Add to a US Census Population template */
CenPop.add_to_template= function(input, estorcensus) {
	CenPop.most_recent_census=CenPop.most_recent_census_pop=0; //TODO should maybe be nulll?
    var result=CenPop.get_pop_str(input);
    if(!result) return '';
    CenPop.debug("result="+result,"global");
    // If the template already exists, add our data 
    var ret = input.replace(result,function(match,p1,p2,p3) {
	var parse_results=CenPop.parse_USCensusPop(match,p1,p2,p3);
	if(!parse_results) return '';
	console.log("USCensusPop parse_results="+JSON.stringify(parse_results));
	var term_map=parse_results.term_map,footnote_str=parse_results.footnote_str.trim();
	if(parse_results['estref']!==undefined) {
		var refname_regexp=new RegExp(/<ref\s+name\s*=\s*"?([^">\/]*)"?\s*>.*<\/ref>/),estref_match;
		if((estref_match=parse_results['estref'].match(refname_regexp)))
		{
			CenPop.removed_refs[estref_match[1]]=estref_match[0];
			
		}
		
	}
	else {
		parse_results.estref='';
	}
	var temp_estyear=parseInt($('.estYearText').val()),temp_lastcen=temp_estyear-(temp_estyear % 10);
	var pop_stuff='{{US Census population\n';
	if(term_map.has('align')) pop_stuff+='|align='+term_map.get('align')+'\n';
	/* Add terms from before our begin year if they exist
	 */
	real_begin_year = temp_lastcen-(10*(CenPop.pop_page.curr_place.length-1-CenPop.begin_decennial));
	console.log('real_begin_year='+real_begin_year);
	console.log('term_map=',term_map)
	CenPop.debug(`term_map=${JSON.stringify(term_map)}`)
	for(my_year=1790; my_year < real_begin_year; my_year+=10) {
	    if(!term_map.has(my_year) || term_map.get(my_year)===0) continue;
	    /* Update global variable with current maximum official Census year */
	    CenPop.most_recent_census=my_year;
	    CenPop.most_recent_census_pop=term_map.get(my_year);
	    pop_stuff+='|'+my_year+"= "+term_map.get(my_year);
	    console.log(my_year+": "+term_map.has(my_year));
	    //	console.log(my_year+": "+term_map.has(my_year+'n'));
	    if(term_map.has(my_year+'n') && term_map.get(my_year+'n')!==0) pop_stuff+='|'+my_year+"n= "+term_map.get(my_year+'n');
	    pop_stuff+="\n";
	}
	if(CenPop.pop_page.curr_place.length > CenPop.begin_decennial) {
	    CenPop.most_recent_census = temp_lastcen;
	    CenPop.most_recent_census_pop = CenPop.pop_page.curr_place[CenPop.begin_decennial];
	}			
	for(i=CenPop.pop_page.curr_place.length-1;i>=CenPop.begin_decennial; i--)
	{
	    CenPop.debug('CenPop.begin_decennial='+CenPop.begin_decennial+', CenPop.pop_page.curr_place['+i+']='+CenPop.pop_page.curr_place[i]);
	    var year_pop=parseInt(CenPop.pop_page.curr_place[i]),curr_year=temp_lastcen-(i-CenPop.begin_decennial)*10
	    if(!($('#overwrite').prop('checked') && year_pop!==0) &&
	       (term_map.has(curr_year)||term_map.has(parseInt(curr_year))) && term_map.get(curr_year)!==0)  pop_stuff+='|'+curr_year+"= "+term_map.get(curr_year)+"\n";
	    else if(year_pop!==0&&!term_map.has(curr_year)) pop_stuff+='|'+curr_year+"= "+CenPop.pop_page.curr_place[i]+"\n"; 
	}
	console.log("* estorcensus="+estorcensus)
	if(estorcensus!='Estimate') {
		/* Add final decennial */
		CenPop.debug(`Adding decennial for `+$('.estYearText').val())
		if(!term_map.has(parseInt($('.estYearText').val()))) {
			pop_stuff+='|'+$('.estYearText').val()+"= "+CenPop.pop_page.curr_place[CenPop.est_column]+'\n'; }
		if(parse_results['estyear'] && parse_results['estimate'] && parseInt(parse_results['estyear'].trim())>parseInt($('.estYearText').val())) {
			pop_stuff+='|estyear='+parse_results['estyear'].trim()+'\n'; // Todo: add field to put it in 
		    pop_stuff+='|estimate='+parse_results['estimate'].trim()+'\n';
		    pop_stuff=pop_stuff+'|estref='+parse_results['estref'].trim()+'\n';
		}
	}
	else if(CenPop.pop_page.curr_place[CenPop.est_column] >= 0 && 
	   CenPop.pop_page.curr_place[CenPop.est_column] !== 'N/A') {
	    pop_stuff+='|estyear='+$('.estYearText').val()+'\n'; // Todo: add field to put it in 
	    pop_stuff+='|estimate='+CenPop.pop_page.curr_place[CenPop.est_column]+'\n';
	    pop_stuff=pop_stuff+'|estref='+$('.estRefText').val()+'\n';
	}
	if(term_map.has('align-fn')) pop_stuff+='|align-fn='+term_map.get('align-fn')+'\n';
	if(footnote_str!==''&&!$('#overwrite').prop('checked')) {
		pop_stuff=pop_stuff+'|footnote='+footnote_str+'\n';
		CenPop.debug("added old footnote_str="+footnote_str,'global');	
	}
	else {
		CenPop.debug("adding standard footnote ="+$('.footnoteText').val(),"global");	

		pop_stuff=pop_stuff+'|footnote='+$('.footnoteText').val()+'\n'; /* Overwrite with a new footnote too */
	}
	pop_stuff+='}}\n';
	return pop_stuff;
    });
    CenPop.debug('Finished add_to_template','global');
    return ret;
};

CenPop.get_histpop_str = function(input, estorcensus) {
    var ret_str='';
    var begin_re = new RegExp('\{\{HistPop|\{\{Historical[ \n\r]*[pP]opulations');
    var brace_depth=2;
    var begin_pos=input.search(begin_re);
    var curr_pos=begin_pos+2,in_len=input.length;
    if(begin_pos===-1 &&($('#noMatch').html(+$('#noMatch').html() + 1)||true)) return;
    while(brace_depth>0 && curr_pos < in_len) brace_depth+=(curr_char=input.charAt(curr_pos++))&&curr_char==='{'?1:(curr_char==='}'?-1:0);
    if(curr_pos<in_len && brace_depth===0 && input.charAt(curr_pos)==='\n') return input.slice(begin_pos,curr_pos+1);
    else if(curr_pos<in_len && brace_depth===0) return input.slice(begin_pos,curr_pos);
    else return '';
};

CenPop.parse_histpop=function(match,p1,p2,p3) {
	var estorcensus=$('input[name="estorcensus"]:checked').val();
    var copy_list = ['title','type','align','width','state','shading','pop_name','percentages'];
    var term_map = new Map(),results={};
    var begin_year=parseInt($('.beginYearText').val());
    var re1=new RegExp('\|');
    var last_right_braces=match.lastIndexOf('}}');
    var bar_list = match.slice(0,last_right_braces).split('\|'),eq_list;
    var temp_str='Split data\n';
    var footnote_str='',source_str='';
    var depth={'bracket':0,'brace':0}
    var char_str={'\\[\\[':['bracket',1],'\\]\\]':['bracket',-1],'\{\{':['brace',1],'\}\}':['brace',-1]},x;
    var in_footnote=false, in_source=false;
    var in_footnote_ref=false, in_source_ref=false;
    var in_other_ref=false;
    var bar_iter=0;
    for (bar_iter=0; bar_iter< bar_list.length; bar_iter++) {
	elem = bar_iter;
	if(!in_footnote_ref && depth['brace']<=0 && depth['bracket'] <=0) in_footnote=false;
	if(!in_source_ref && depth['brace']<=0 && depth['bracket'] <= 0) in_source=false;
	eq_list=bar_list[elem].split('\=');
	if(in_footnote) {
	    footnote_str+='|';
	    if(bar_list[elem].match('<ref') !== null 
	       && bar_list[elem].match('<ref[^]*</ref>') === null) in_footnote_ref=true;
	    else if(bar_list[elem].match('</ref>') !== null) in_footnote_ref=false;
	    for(x in char_str) if((curr=bar_list[elem].match(x))) depth[char_str[x][0]]+=char_str[x][1]*curr.length;
	    footnote_str+=bar_list[elem].trim();
	}
	else if(in_source) {
	    source_str+='|';
	    if(bar_list[elem].match('<ref') && !bar_list[elem].match('<ref[^]*</ref>')) in_source_ref=true;
	    else if(bar_list[elem].match('</ref>')) in_source_ref=false;
	    for(x in char_str) if((curr=bar_list[elem].match(x))) depth[char_str[x][0]]+=char_str[x][1]*curr.length;
	    source_str+=bar_list[elem].trim();
	}
	else if(eq_list.length>=2) {
	    var first_str=eq_list[0].trim(),second_str=eq_list[1].trim();
	    if(first_str.match('footnote')!== null && (in_footnote=true)) {
		for(var j=1; j < eq_list.length; j++) {
		    if(j>1) footnote_str+='='; // Add the removed = if we're not right after footnote
		    if(eq_list[j].match('<ref')  && !eq_list[j].match('<ref[^]*</ref>')) in_footnote_ref=true;
		    else if(eq_list[j].match('</ref>') !== null) in_footnote_ref=false;
		    for(x in char_str) {
			if((curr=eq_list[j].match(x))) depth[char_str[x][0]]+=char_str[x][1]*curr.length; }
		    if(depth['bracket']<0) depth['bracket']=0;
		    footnote_str+=eq_list[j];
		}
	    }
	    else if(first_str.match('source')!== null && (in_source=true)) {
		for(var j=1; j < eq_list.length; j++) {
		    if(j>1) source_str+='=';
		    if(eq_list[j].match('<ref')  && !eq_list[j].match('<ref[^]*</ref>')) in_source_ref=true;	
		    else if(eq_list[j].match('</ref>') !== null) in_source_ref=false;
		    for(x in char_str) {
			if((curr=eq_list[j].match(x))) depth[char_str[x][0]]+=char_str[x][1]*curr.length; }
		    for(x in depth) if(depth[x]<0) depth[x]=0;
		    source_str+=eq_list[j];
		}
	    }
	    else term_map.set(first_str.trim(),second_str.trim());
	}
	else if(eq_list.length==1) {
	    var first_str1=eq_list[0].trim(),second_num;
	    if(first_str1.match('[0-9]+') !== null && bar_iter+1 < bar_list.length && (bar_iter+=1) &&
	       (second_num=parseInt(bar_list[bar_iter])) &&
	       !isNaN(second_num) && second_num!==0) term_map.set(parseInt(first_str1),second_num);
	}
    }
    results.term_map=term_map;
    results.footnote_str=footnote_str.trim();
    results.source_str=source_str.trim();
    if(depth['brace']>=0) return CenPop.remake_histpop_template(results, estorcensus);
    return null;
};

CenPop.remake_histpop_template=function(results, estorcensus) {
    var term_map=results.term_map,source_str=results.source_str,footnote_str=results.footnote_str;
    var pop_stuff='{{Historical populations\n';
    var added_est=false,temp_estyear,temp_lastcen;
    for (var my_key of term_map.keys()) {
	key_term=my_key.toString();
	if(key_term.match('[0-9]+') === null) pop_stuff+='|'+key_term+'= '+term_map.get(my_key)+'\n';
	else {
	    /* Don't re-add recent estimates */    
	    temp_estyear=parseInt($('.estYearText').val());
	    /* Get most recent number for adding to infobox */
	    if((temp_lastcen=temp_estyear-(temp_estyear % 10)) && term_map.has(temp_lastcen)) {
		CenPop.most_recent_census=temp_lastcen;
		CenPop.most_recent_census_pop=term_map.get(temp_lastcen);
	    }
	    else {
		CenPop.most_recent_census=0;
		CenPop.most_recent_census_pop=0;
	    }
	    /* TODO: FIX FOR FUTURE */
	    if(!(parseInt(key_term)>temp_lastcen && parseInt(key_term) < temp_estyear)) {
		if(key_term===$('.estYearText').val()) added_est=true;
		pop_stuff+='|'+key_term+'|'+term_map.get(my_key)+'\n';
	    }
	}
    }
    for(i=CenPop.pop_page.curr_place.length-1;i>=CenPop.begin_decennial; i--) {
	var year_pop=parseInt(CenPop.pop_page.curr_place[i]);	
	var curr_year=begin_year+(CenPop.pop_page.curr_place.length-1-i)*10;
	if(term_map.has(curr_year) && term_map.get(curr_year)!==0) pop_stuff+='';
	else if(year_pop!==0) pop_stuff+='|'+curr_year+"|"+CenPop.pop_page.curr_place[i]+"\n";
    }
    if(!added_est && CenPop.pop_page.curr_place[CenPop.est_column] >= 0 && 
       CenPop.pop_page.curr_place[CenPop.est_column] !== 'N/A') pop_stuff+='|'+$('.estYearText').val()+'|'+CenPop.pop_page.curr_place[CenPop.est_column]+'\n'; 
    if(source_str!=='')	pop_stuff=pop_stuff+'|source='+source_str+'\n';
    else pop_stuff=pop_stuff+'|source='+$('.footnoteText').val()+'\n';
    if(footnote_str!=='') pop_stuff=pop_stuff+'|footnote='+footnote_str+'\n';
    pop_stuff+='}}\n';
    return pop_stuff;
};
  

CenPop.add_to_histpop_template = function(input, estorcensus) {
    var result=CenPop.get_histpop_str(input, estorcensus),ret;
    if(result && (ret = input.replace(result,CenPop.parse_histpop))) return ret;
    else return '';
};


/** Add a new population template */
CenPop.add_pop = function(input, estorcensus) {
    //	console.log("input="+input);
    console.warn("Adding new population template!")
    var demo_re = new RegExp('(\=\=Demographics\=\=|\=\= Demographics \=\=)\n');
    var geo_re = new RegExp('(\=\=Geography\=\=|\=\= Geography \=\=)\n'),sec_re = /==[\s\w]+==\n/;
    var pop_stuff='{{US Census population\n', my_iter=0;
    var begin_year=parseInt($('.beginYearText').val());
    var sec_match,geo_pos=0,year_pop,curr_year,page_place_len=CenPop.pop_page.curr_place.length;
    if(page_place_len-1 < CenPop.begin_decennial && CenPop.pop_page.curr_place[CenPop.est_column] === 'N/A' &&
       (CenPop.debug('No population data found, not adding','global')||true)) return '';
    for(i=page_place_len-1;i>=CenPop.begin_decennial; i--) {
	if(((year_pop=parseInt(CenPop.pop_page.curr_place[i]))!==0)&&
	   (curr_year=begin_year+(page_place_len-1-i)*10)) pop_stuff+='|'+curr_year+"= "+CenPop.pop_page.curr_place[i]+"\n";
    }
	if(estorcensus!='Estimate') {
		pop_stuff+='|'+$('.estYearText').val()+"= "+CenPop.pop_page.curr_place[CenPop.est_column]+'\n';
	}
    else if(CenPop.pop_page.curr_place[CenPop.est_column] >= 0 &&  CenPop.pop_page.curr_place[CenPop.est_column] !== 'N/A') {
	pop_stuff+='|estyear='+$('.estYearText').val()+'\n'; // Todo: add field to put it in 
	pop_stuff+='|estimate='+CenPop.pop_page.curr_place[CenPop.est_column]+'\n';
	pop_stuff=pop_stuff+'|estref='+$('.estRefText').val()+'\n';
    }
    pop_stuff=pop_stuff+'|footnote='+$('.footnoteText').val()+'\n'+'}}\n';
    if(input.search(demo_re)!=-1) return input.replace(demo_re,function(match) {  return match+pop_stuff; });
    else if((geo_pos=input.search(geo_re)) !== -1 && ((sec_match=input.substr(geo_pos+2).match(sec_re))||1)) {
	console.log('sec_match='+JSON.stringify(sec_match));
	if(sec_match) return input.replace(sec_match[0],function(match) { return '==Demographics==\n'+pop_stuff+match; });
	else return '';
    }
    else if((sec_match=input.match(sec_re))) return input.replace(sec_match[0],'==Demographics==\n'+pop_stuff+sec_match[0]);
    else return '';
};
/**
 * Add FIPS code to place it's missing from, and return new content, empty if fail
 */
CenPop.add_FIPS = function(content,fips_code) 
{
    regexp1='/{{Infobox settlement.*\|blank_name\s*=\s*([[Federal Information Processing Standards|FIPS code]]|\s*)\s*\|blank_info\s*=\s*\|';
    regexp2='/{{Infobox settlement.*\|blank_name\s*=.*\|blank_info\s*=\s*\|';
};

/**
 * Update top-level templates in a wiki document, returning the new document (TODO)
 * 
 * @param content the raw text of the document (unparsed)
 * @param templates_to_update an object containing each template to update  
 * @return the updated content, null if a failure happens
 */


/** 
 * Return the entire template specified by the template regexp to return 
 * @param input the input to search
 * @param temp_regexp the regular expression object for the beginning of the template 
 */

CenPop.get_template = function(input, temp_regexp) {
    var ret_str='';
    var brace_depth=1;
    var begin_pos=input.search(temp_regexp), curr_pos=input.search(temp_regexp)+2;
    var in_len=input.length, in_nowiki=false;
    CenPop.in_comment=false;
    if(begin_pos===-1) {
	CenPop.debug('Failed to match template with "'+temp_regexp+' in '+input,'global');
	return '';
    }
    curr_pos=begin_pos+2;
    while(brace_depth>0 && curr_pos < in_len) {
	if(!in_nowiki && !CenPop.in_comment && curr_pos + 2 <= in_len && 
	   input.slice(curr_pos,curr_pos+2)==='{{' && ((++brace_depth)||1)) curr_pos+=2;
	else if(!in_nowiki && !CenPop.in_comment && curr_pos+2 <= in_len && 
		input.slice(curr_pos,curr_pos+2)==='}}' && ((brace_depth--)||1)) curr_pos+=2;
	else if(curr_pos+8<=in_len && input.slice(curr_pos,curr_pos+8)==='<nowiki>'&&(in_nowiki=true)) curr_pos+=8;
	else if(in_nowiki&&curr_pos+9<=in_len && input.slice(curr_pos,curr_pos+9)==='</nowiki>' && !(in_nowiki=false)) curr_pos+=9;
	else if(curr_pos+4<=in_len && input.slice(curr_pos,curr_pos+4) === '<!--' && (CenPop.in_comment=true)) curr_pos+=4;
	else if(CenPop.in_comment && curr_pos+3<=in_len && input.slice(curr_pos,curr_pos+3)==='-->' &&
		!(CenPop.in_comment=false)) curr_pos+=3;
	else curr_pos+=1;
    }
    if(curr_pos<in_len && brace_depth===0 && input.charAt(curr_pos)==='\n') return input.slice(begin_pos,curr_pos+1);
    else if(curr_pos<in_len && brace_depth===0) return input.slice(begin_pos,curr_pos);
    else return null;
};

/**
 * Update a template, used primarily for infobox settlement but potentially/probably works elsewhere  
 * @param content content of the template 
 * @param fields_to_update a javascript object with the fields to update and the 
 * @param fields_no_overwrite fields to add only if they were previously blank
 * @return      new values
 */
CenPop.update_template=function(input,fields_to_update, fields_no_overwrite, fields_to_remove) {
	console.warn("fields_to_remove=",fields_to_remove)
    var in_field=false, in_ref=false, in_nowiki=false,  in_brackets=false;
    var in_len=input.length,x,next_equals;
    var new_field_obj={};
    var refname_regexp=new RegExp(/^<ref\s+name\s*=\s*"?([^">\/]*)"?\s*(\/)?>/);
    var ref_ret;
    var updates={'ret_str':'',brace_depth:0,curr_pos:0,in_comment:false,curr_field_name:'',old_field_val:'',
		 curr_ref:'',curr_ref_name:'',curr_comments:'',curr_pos:2,brace_depth:1,ret_str:'{{',curr_ref:''};
    for(x in updates) CenPop[x]=updates[x];
    /* We already know it begins with '{{' */
    while(CenPop.brace_depth>0 && CenPop.curr_pos < in_len) {
		if(!in_nowiki && !CenPop.in_comment && 
		   input.slice(CenPop.curr_pos,CenPop.curr_pos+4)==='<ref')
		{
		    ref_ret=refname_regexp.exec(input.substr(CenPop.curr_pos));
		    
		    if(ref_ret!== null) {
				CenPop.curr_ref_name=ref_ret[1];
				if(ref_ret.length<=2 || ref_ret[2] !== '/') {
				    CenPop.debug("***in_ref with name",'update');
				    in_ref=true;
				}
				else {
				    CenPop.debug("***parsed ref with name, no inner part,length="+ref_ret.length,'update');
				    in_ref=false;
				    CenPop.curr_ref=ref_ret[0];
				}
				/* TODO: this is taking way too much!!! (fixed 07/29/2020?) */
				CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+ref_ret[0].length),in_field,in_ref);
		    }
		    else {
				/* Not a named and defined ref, can ignore */
				if((temp_val=input.substr(CenPop.curr_pos).search('>'))==-1) {
				    in_ref=false;
				    CenPop.debug("Badly formed ref tag!",'global');
				    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+4),in_field,in_ref);
				}
				else {
				    CenPop.debug("***in_ref without name,"+input.slice(CenPop.curr_pos,CenPop.curr_pos+temp_val+1),'update');
				    in_ref=true;
				    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+temp_val+1),in_field,in_ref);
				}
		    }
		}
		else if(!in_nowiki && !CenPop.in_comment && CenPop.curr_pos+6 <= in_len &&
			input.slice(CenPop.curr_pos,CenPop.curr_pos+6)==='</ref>') {
		    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+6),in_field,in_ref);
		    CenPop.add_removed_reference(fields_to_update,fields_no_overwrite);
		    /* Update before leaving ref */
		    in_ref=false;
		    
		}
		else if(!in_nowiki && !CenPop.in_comment && CenPop.curr_pos + 2 <= in_len && 
			input.slice(CenPop.curr_pos,CenPop.curr_pos+2)==='{{') {
		    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+2), in_field, in_ref);
		    CenPop.brace_depth++;
		}
		else if(!in_nowiki && !CenPop.in_comment && CenPop.curr_pos+2 <= in_len && 
			input.slice(CenPop.curr_pos,CenPop.curr_pos+2)==='}}') {
		    CenPop.brace_depth--;
		    if(CenPop.brace_depth <= 0 && CenPop.curr_field_name !== '') {
				var added_new_field=CenPop.add_last_field(fields_to_update,in_field, fields_no_overwrite,new_field_obj, fields_to_remove);
				// We updated this field, delete it
				if(added_new_field) delete fields_to_update[CenPop.curr_field_name.trim()];
				in_field=false;
				// Add any new fields not yet updated
				CenPop.add_remaining_fields(fields_to_update);
		    }
		    /* Brace depth decrement needs to be before, so in_field set to false */
		    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+2), in_field, in_ref);
		    
		}
		else if(CenPop.curr_pos+8<=in_len && 
			input.slice(CenPop.curr_pos,CenPop.curr_pos+8)==='<nowiki>') {
		    in_nowiki=true;
		    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+8), in_field, in_ref);
		}
		else if(in_nowiki&&CenPop.curr_pos+9<=in_len && 
			input.slice(CenPop.curr_pos,CenPop.curr_pos+9)==='</nowiki>') {
		    in_nowiki=false;
		    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+9), in_field, in_ref);
		}
		else if(CenPop.curr_pos+4<=in_len && 
			input.slice(CenPop.curr_pos,CenPop.curr_pos+4) === '<!--') {
		    CenPop.in_comment=true;
		    my_iter=CenPop.curr_pos-1;
		    /* Add pre-comment whitespace to curr_comment */
		    while(my_iter>=0 
		    && input.charAt(my_iter).toString().search('\n')!==-1) my_iter--;
		    /* Why did I need my_iter+2 */
		    CenPop.debug('begin space"'+input.slice(my_iter+2,CenPop.curr_pos)+'"','update');
		    CenPop.curr_comment+=input.slice(my_iter+2,CenPop.curr_pos);
		    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+4), in_field, in_ref);
		}
		else if(CenPop.in_comment && CenPop.curr_pos+3<=in_len && 
		input.slice(CenPop.curr_pos,CenPop.curr_pos+3)==='-->') {
		    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+3), in_field, in_ref);
		    my_iter=CenPop.curr_pos;
		    while(my_iter<input.length && 
		    input.charAt(my_iter).toString().search('\n')!==-1) my_iter++;
		    CenPop.debug('end space"'+input.slice(CenPop.curr_pos,my_iter)+'"','update');
		    CenPop.curr_comment+=input.slice(CenPop.curr_pos,my_iter);
		    CenPop.in_comment=false;
		}
		else if(!CenPop.in_comment && !in_nowiki && CenPop.curr_pos+2<=in_len &&
			input.slice(CenPop.curr_pos,CenPop.curr_pos+2) === '[[') {
		    in_brackets=true;
		    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+2), in_field, in_ref);
		}
		else if(!CenPop.in_comment && !in_nowiki &&  CenPop.curr_pos+2<=in_len &&
			input.slice(CenPop.curr_pos,CenPop.curr_pos+2) === ']]') {
		    in_brackets=false;
		    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+2), in_field, in_ref);
		}
		else if(!in_nowiki && !CenPop.in_comment && !in_ref && !in_brackets &&
			CenPop.brace_depth === 1 && input.charAt(CenPop.curr_pos) === '|') {
		    /* Deal with last field */
		    var added_new_field=CenPop.add_last_field(fields_to_update,in_field, fields_no_overwrite,new_field_obj, fields_to_remove);
		    if(added_new_field) {
				/* We updated this field */
				if(CenPop.curr_field_name.trim() in fields_to_update) {
				    CenPop.debug('Add and found "'+CenPop.curr_field_name.trim()+'"','update');
				    delete fields_to_update[CenPop.curr_field_name.trim()];
				}
				else  CenPop.debug("Failed to find the trimmed field name",'update');
		    }
		    else {
				/* Delete it anyway if it wasn't updated, becaue of no overwrite policy */
				if(CenPop.curr_field_name.trim() in fields_to_update) {
				    delete fields_to_update[CenPop.curr_field_name.trim()];
				    CenPop.debug("No write, but deleting "+CenPop.curr_field_name.trim(),'update');
				}
		    }
		    CenPop.old_field_val='';
		    next_equals=input.substr(CenPop.curr_pos).search('=');
		    next_bar=input.substr(CenPop.curr_pos+1).search(/\|/);
		    if(next_equals == -1 || (next_bar >= 0 && next_equals > next_bar)) {
				CenPop.debug("Either next bar found before next equals or no next equals",'update');
				in_field=false;
				if(next_equals > next_bar) {
					CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+1), in_field, in_ref);
				}
				else {
				    /* Just move onto the next character */
				    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+1), in_field, in_ref);
				}
		    }
		    else {
				/* Get the field name, update to go past the equals */
				in_field=false;
				CenPop.curr_field_name = input.slice(CenPop.curr_pos+1,CenPop.curr_pos+next_equals);
				in_field=true;
				CenPop.curr_pos+=next_equals+1;
		    }
		}
		else
		{
		    /* Normal character, just move up one */
		    CenPop.update_fields(input.slice(CenPop.curr_pos,CenPop.curr_pos+1),in_field,in_ref);
		}
    }
    if(CenPop.curr_pos< in_len && CenPop.brace_depth===0) {
		if(input.charAt(CenPop.curr_pos)==='\n') return {'text':CenPop.ret_str+'\n','fields':new_field_obj};
		else return {'text':CenPop.ret_str,'fields':new_field_obj};
    }
    else if(CenPop.brace_depth==0) {
		/* No newline, weird */
		return {'text':CenPop.ret_str+'\n','fields':new_field_obj};
    }
    else {
		CenPop.debug('CenPop.curr_pos='+CenPop.curr_pos+', in_len='+in_len+', brace_depth='+CenPop.brace_depth+'\nUnknown brace parsing error in update_template','update');
		return {'text':'','fields':{}};
    }
};
/**
 * Deals with each possible terminal in update 
 */
CenPop.update_fields = function(terminal, in_field, in_ref) {
    if(!in_field) CenPop.ret_str+=terminal;
    else CenPop.old_field_val+=terminal;
    if(in_ref) CenPop.curr_ref+=terminal;
    if(CenPop.in_comment) CenPop.curr_comment+=terminal;
    CenPop.curr_pos+=terminal.length;
};
/**
 * Add the previously added field, return true if it was updated */

CenPop.add_last_field = function(fields_to_update, in_field, fields_no_overwrite,return_field_objs, fields_to_remove) {
    /* Fixed to have set of fields not to overwrite, so we only write to them if they are 
       empty or missing entirely 
       
       POTENTIAL BUG: those pages that have something in blank_name nothing in blank_info
    */
    
    /* Work around in thing bug */
    var is_no_overwrite=false;
    for(i=0; i < fields_no_overwrite.length; i++) {
		if(fields_no_overwrite[i]===CenPop.curr_field_name.trim()) {
		    is_no_overwrite=true;
		    break;
		}
    }
    if(CenPop.curr_field_name.trim() in fields_to_remove) {
    	CenPop.debug("Removing field "+CenPop.curr_field_name.trim(),'update');
    	return false;
    }
    if(in_field && CenPop.curr_field_name.trim() in fields_to_update
       && (!is_no_overwrite || CenPop.old_field_val.toString().trim().length===0)) {
		CenPop.debug('curr_field_name.trim()='+CenPop.curr_field_name.trim()+',CenPop.old_field_val.toString().trim()='+CenPop.old_field_val.toString().trim()+' is_no_overwrite='+is_no_overwrite,'update');
		CenPop.ret_str+=CenPop.new_field_vals(CenPop.curr_field_name,
						      fields_to_update[CenPop.curr_field_name.trim()]);
		return_field_objs[CenPop.curr_field_name.trim()]=fields_to_update[CenPop.curr_field_name.trim()];
		if(CenPop.curr_comment.toString().length > 0) {
		    /* Has comments, add at the end */
		    CenPop.ret_str+=CenPop.curr_comment.toString();
		}
		if(CenPop.curr_ref_name !== '') {
		    CenPop.curr_ref_name='';
		    CenPop.curr_ref='';
		}
		else CenPop.debug("blank, CenPop.curr_ref_name="+CenPop.curr_ref_name,'update');
		//CenPop.curr_field_name='';
		CenPop.old_field_val='';
		//	CenPop.debug('removed_refs='+JSON.stringify(CenPop.removed_refs),'update');
		CenPop.curr_comment='';
		return true;
    }
    else if(in_field) {
		CenPop.debug("old val but in field, "+CenPop.curr_field_name+", old_field_val="+CenPop.old_field_val,'update');
		/* add the old_val */
		if(CenPop.curr_ref_name !== '') {
		    CenPop.curr_ref_name='';
		    CenPop.curr_ref='';
		}
		CenPop.ret_str+=CenPop.new_field_vals(CenPop.curr_field_name, CenPop.old_field_val);
		return_field_objs[CenPop.curr_field_name.trim()]=CenPop.old_field_val;

		//CenPop.curr_field_name='';
		CenPop.old_field_val='';
		CenPop.curr_comment='';
		if(is_no_overwrite)	return true;
		else return false;
    }	
};
/* Add the fields that were not yet put into the file, i.e. the new fields
   The rest of the fields should have already been deleted from fields_to_update */
CenPop.add_remaining_fields = function(fields_to_update)
{
    var field_name;
    for(field_name in fields_to_update) {
	 	CenPop.debug('adding remaining field '+field_name,'update');
	 	CenPop.ret_str+=CenPop.new_field_vals(field_name,fields_to_update[field_name]);
    }
};
/* Add a removed reference */
CenPop.add_removed_reference = function(fields_to_update,fields_no_overwrite) {
    /* Only add it if it's gonna be ditched. Oops we probably have a problem 
       now where we add one back if it's equivalent to what we're adding in our replacement 
       
       Hopefully checking for it in the replacement of the current field prevents putting it in removed_refs
    */
    if(fields_to_update[CenPop.curr_field_name.trim()]!==undefined && !fields_no_overwrite.includes(CenPop.curr_field_name.trim())
       && fields_to_update[CenPop.curr_field_name.trim()].toString().search('<ref\\s+name\\s*=\\s*"?'+CenPop.curr_ref_name+'"?\\s*>')===-1)
    {
    	console.log("fields_to_update="+JSON.stringify(fields_to_update)+", fields_no_overwrite="+JSON.stringify(fields_no_overwrite));
    	console.log("CenPop.curr_ref_name="+CenPop.curr_ref_name+", CenPop.curr_ref="+CenPop.curr_ref)
    	console.log("CenPop.curr_field_name="+CenPop.curr_field_name.trim());
		CenPop.removed_refs[CenPop.curr_ref_name]=CenPop.curr_ref;	
    }
    else {
    	console.log("Nothing found in add_removed_reference with CenPop.curr_ref_name="+CenPop.curr_ref_name+", CenPop.curr_ref"+CenPop.curr_ref);
    }
    CenPop.curr_ref_name='';
    CenPop.curr_ref='';
};

/* Deals with new fields val */
CenPop.new_field_vals = function(curr_field_name,curr_val)
{
    if(!curr_val)
    {
 	CenPop.debug('curr_field_name='+curr_field_name+' has no curr_val');
 	return;
    }
    var ret_val='|'+curr_field_name;
    if(curr_field_name.charAt(curr_field_name.length-1)!== ' ')
    {
 	ret_val+=' ';
    }
    ret_val+='=';
    if(curr_val.toString().charAt(0) !== ' ')
    {
 	ret_val+=' ';
    }
    ret_val+= curr_val.toString();
    if(ret_val.charAt(ret_val.length-1)!=='\n')
    {
 	ret_val+='\n';
    }
    return ret_val;
};

/**
 * Returns an object with the fields and values
 */
CenPop.convert.parse_template=function(input)
{
    CenPop.convert.ret_obj={}; // the object to return
    CenPop.convert.ret_str='';
    //	var begin_re = new RegExp(temp_regexp);
    CenPop.convert.brace_depth=0;
    CenPop.convert.curr_pos=0;
    in_len=input.length;
    var in_field=false, in_ref=false, in_nowiki=false,  in_brackets=false;
    CenPop.convert.in_comment=false,
    CenPop.convert.curr_field_name='';
    CenPop.convert.old_field_val='';
    var next_equals;
    CenPop.convert.curr_ref='', CenPop.convert.curr_ref_name='';
    CenPop.convert.curr_comments=''; // Holds any comments from this field, to insert at end of line 
    var refname_regexp=new RegExp(/^<ref\s+name\s*=\s*"?([^">\/]*)"?\s*(\/)?>/);
    var ref_ret;
    // We already know it begins with '{{' 
    CenPop.convert.curr_pos=2;
    CenPop.convert.brace_depth=1;
    CenPop.convert.ret_str='{{';
    CenPop.convert.curr_ref='';
    while(CenPop.convert.brace_depth>0 && CenPop.convert.curr_pos < in_len)
    {
	if(!in_nowiki && !CenPop.convert.in_comment && 
	   input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+4)==='<ref')
	{
	    ref_ret=refname_regexp.exec(input.substr(CenPop.convert.curr_pos));
	    
	    if(ref_ret!== null)
	    {
		CenPop.convert.curr_ref_name=ref_ret[1];
		if(ref_ret.length<=2 || ref_ret[2] !== '/')
		{
		    //	CenPop.debug("***in_ref with name",'update');
		    in_ref=true;
		}
		else
		{
		    //	CenPop.debug("***parsed ref with name, no inner part,length="+ref_ret.length,'update');
		    in_ref=false;
		    CenPop.convert.curr_ref=ref_ret[0];
		}
		// TODO: this is taking way too much!!! 
		CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+ref_ret[0].length),in_field,in_ref);
	    }
	    else
	    {
		// Not a named and defined ref, can ignore 
		temp_val=input.substr(CenPop.convert.curr_pos).search('>');
		if(temp_val==-1)
		{
		    in_ref=false;
		    CenPop.debug("Badly formed ref tag!",'global');
		    CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+4),in_field,in_ref);
		}
		else
		{
		    CenPop.debug("***in_ref without name,"+input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+temp_val+1),'update');

		    in_ref=true;
		    CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+temp_val+1),in_field,in_ref);
		}
	    }
	}
	else if(!in_nowiki && !CenPop.convert.in_comment && CenPop.convert.curr_pos+6 <= in_len &&
		input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+6)==='</ref>')
	{
	    
	    CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+6),in_field,in_ref);
	    // Update before leaving ref 
	    in_ref=false;
	    
	}
	else if(!in_nowiki && !CenPop.convert.in_comment && CenPop.convert.curr_pos + 2 <= in_len && 
		input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+2)==='{{')
	{
	    CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+2), in_field, in_ref);
	    CenPop.convert.brace_depth++;

	}
	else if(!in_nowiki && !CenPop.convert.in_comment && CenPop.convert.curr_pos+2 <= in_len && 
		input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+2)==='}}')
	{
	    CenPop.convert.brace_depth--;
	    //	console.log("*Brace depth down to"+CenPop.convert.brace_depth);
	    if(CenPop.convert.brace_depth <= 0 && CenPop.convert.curr_field_name !== '')
	    {
		CenPop.convert.add_last_field(in_field);
	    }
	    // Brace depth decrement needs to be before, so in_field set to false 
	    CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+2), in_field, in_ref);
	    
	}
	else if(CenPop.convert.curr_pos+8<=in_len && 
		input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+8)==='<nowiki>')
	{
	    in_nowiki=true;
	    CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+8), in_field, in_ref);
	}
	else if(in_nowiki&&CenPop.convert.curr_pos+9<=in_len && 
		input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+9)==='</nowiki>')
	{
	    in_nowiki=false;
	    CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+9), in_field, in_ref);

	}
	else if(CenPop.convert.curr_pos+4<=in_len && 
		input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+4) === '<!--')
	{
	    CenPop.convert.in_comment=true;
	    my_iter=CenPop.convert.curr_pos-1;
	    // Add pre-comment whitespace to curr_comment 
	    while(my_iter>=0 && input.charAt(my_iter).toString().search('\n')!==-1)
	    {
		my_iter--;
	    }
	    // Why did I need my_iter+2 
	    //CenPop.debug('begin space"'+input.slice(my_iter+2,CenPop.convert.curr_pos)+'"','update');

	    CenPop.convert.curr_comment+=input.slice(my_iter+2,CenPop.convert.curr_pos);
	    CenPop.convert.curr_pos+=4 /* Don't write the comments */
	    //CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+4), in_field, in_ref);

	}
	else if(CenPop.convert.in_comment && CenPop.convert.curr_pos+3<=in_len && input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+3)==='-->')
	{

	    //CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+3), in_field, in_ref);
	    CenPop.convert.curr_pos+=3;
	    my_iter=CenPop.convert.curr_pos;
	    while(my_iter<input.length && input.charAt(my_iter).toString().search('\n')!==-1)
	    {
		my_iter++;
	    }
	    //	CenPop.debug('end space"'+input.slice(CenPop.convert.curr_pos,my_iter)+'"','update');
	    CenPop.convert.curr_comment+=input.slice(CenPop.convert.curr_pos,my_iter);
	    CenPop.convert.in_comment=false;

	}
	else if(!CenPop.convert.in_comment && !in_nowiki && CenPop.convert.curr_pos+2<=in_len &&
		input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+2) === '[[')
	{
	    in_brackets=true;
	    CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+2), in_field, in_ref);
	}
	else if(!CenPop.convert.in_comment && !in_nowiki &&  CenPop.convert.curr_pos+2<=in_len &&
		input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+2) === ']]')
	{
	    in_brackets=false;
	    CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+2), in_field, in_ref);
	}
	
	else if(!in_nowiki && !CenPop.convert.in_comment && !in_ref && !in_brackets &&
		CenPop.convert.brace_depth === 1 && input.charAt(CenPop.convert.curr_pos) === '|')
	{
	    // Deal with last field 
	    CenPop.convert.add_last_field(in_field);

	    CenPop.convert.old_field_val='';
	    next_equals=input.substr(CenPop.convert.curr_pos).search('=');
	    next_bar=input.substr(CenPop.convert.curr_pos+1).search(/\|/);
	    //	CenPop.debug('next_equals='+next_equals+'\tnext_bar='+next_bar,'update');
	    if(next_equals == -1 || (next_bar >= 0 && next_equals > next_bar))
	    {
		//CenPop.debug("Can't find next equals ",'global');
		in_field=false;
		// Just move onto the next field 
		if(next_equals > next_bar)
		{
		    // Don't save anything, just go to next_bar 
		    CenPop.convert.curr_pos+=next_bar;
		    //CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,next_bar), in_field, in_ref);

		}
		else
		    CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+1), in_field, in_ref);
	    }
	    else
	    {
		// Get the field name, update to go past the equals 
		in_field=false;
		CenPop.convert.curr_field_name = input.slice(CenPop.convert.curr_pos+1,CenPop.convert.curr_pos+next_equals);
		in_field=true;
		
		CenPop.convert.curr_pos+=next_equals+1;

	    }
	}
	else
	{
	    // Normal character, just move up one 
	    if(!CenPop.convert.in_comment)
		CenPop.convert.update_fields(input.slice(CenPop.convert.curr_pos,CenPop.convert.curr_pos+1),in_field,in_ref);
	    else
		CenPop.convert.curr_pos+=1
	}
    }
    if(CenPop.convert.brace_depth==0)
    {
	return CenPop.convert.ret_obj;
    }
    else
    {
	CenPop.debug('CenPop.curr_pos='+CenPop.convert.curr_pos+', in_len='+in_len+', brace_depth='+CenPop.convert.brace_depth+'\nUnknown brace parsing error in update_template','update');
	return CenPop.convert.ret_obj;
    }
};

// Deals with each possible terminal in update 
CenPop.convert.update_fields = function(terminal, in_field, in_ref) {
    if(!in_field) CenPop.convert.ret_str+=terminal;
    else CenPop.convert.old_field_val+=terminal;
    if(in_ref) CenPop.convert.curr_ref+=terminal;
    if(CenPop.convert.in_comment) CenPop.convert.curr_comment+=terminal;
    CenPop.convert.curr_pos+=terminal.length;
};
// Add the previously added field, return true if it was updated 
CenPop.convert.add_last_field = function(in_field) {
    CenPop.convert.ret_obj[CenPop.convert.curr_field_name.toString().trim()]=CenPop.convert.old_field_val.toString().trim();
};
// </nowiki>