AutoWikiBrowser (spesso abbreviato AWB) è un editor MediaWiki semi-automatico per Windows XP e versioni successive, progettato per effettuare le operazioni ripetitive e noiose in modo più semplice e veloce. Per l'installazione su sistemi Linux vedi la guida in inglese su questa pagina Ogni modifica fatta con AWB deve essere riesaminata manualmente prima di essere salvata, e (se necessario) bisogna applicare manualmente le correzioni necessarie. Per una guida più estesa vedi la relativa pagina su Wikipedia
Uso
[modifica]Le seguenti operazioni consentono l'uso di AWB su una macchina Windows con impostazioni per Wikivoyage.
Installare AWB
[modifica]- scarica l'ultima versione da qui
- Estrai il contenuto
- Doppio click su AutoWikiBrowser.exe per avviare AWB
Configurare AWB
[modifica]Configurare di AWB richiede l'impostazione di alcuni parametri e il caricamento di un set di impostazioni standard di AWB che sono stati adattati per Wikivoyage. Per la documentazione tecnica dettagliata vedi questa pagina
- Configura AWB per Wikivoyage. Seleziona
Options → Preferences → Site → Project → Wikivoyage
. e poi scegli la lingua. Nel nostro caso 'it' - Imposta il login: Seleziona
File → Log in/Profiles → Add → Login
. Scrivi il tuo username e password in modo che le modifiche di AWB appaiano fatte dal tuo account. - Importa la configurazione specifica per Wikivoyage. Copia il testo XML qui sotto e salvalo in un file con estensione
.xml
. Poi da AWB selezionaFile → Log in/Profiles → Add → Login
e premiEdit
sul login da te salvato. Metti la spunta a "Select default settings" e inserisci il percorso del file xml. Una volta fatto il login potrai iniziare ad usare AWB per Wikivoyage.
<?xml version="1.0" encoding="utf-8"?> <AutoWikiBrowserPreferences xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xml:space="preserve" Version="5.5.6.0"> <Project>wikivoyage</Project> <LanguageCode>it</LanguageCode> <CustomProject /> <Protocol>http://</Protocol> <LoginDomain /> <List> <ListSource /> <SelectedProvider>CategoryListProvider</SelectedProvider> <ArticleList /> </List> <FindAndReplace> <Enabled>true</Enabled> <IgnoreSomeText>false</IgnoreSomeText> <IgnoreMoreText>false</IgnoreMoreText> <AppendSummary>true</AppendSummary> <Replacements> <Replacement> <Find>\|thumbnail\|</Find> <Replace>|thumb|</Replace> <Comment /> <IsRegex>false</IsRegex> <Enabled>true</Enabled> <Minor>true</Minor> <BeforeOrAfter>false</BeforeOrAfter> <RegularExpressionOptions>IgnoreCase</RegularExpressionOptions> </Replacement> </Replacements> <AdvancedReps /> <SubstTemplates /> <IncludeComments>false</IncludeComments> <ExpandRecursively>true</ExpandRecursively> <IgnoreUnformatted>false</IgnoreUnformatted> </FindAndReplace> <Editprefs> <GeneralFixes>true</GeneralFixes> <Tagger>false</Tagger> <Unicodify>true</Unicodify> <Recategorisation>0</Recategorisation> <NewCategory /> <NewCategory2 /> <ReImage>0</ReImage> <ImageFind /> <Replace /> <SkipIfNoCatChange>false</SkipIfNoCatChange> <RemoveSortKey>false</RemoveSortKey> <SkipIfNoImgChange>false</SkipIfNoImgChange> <AppendText>false</AppendText> <AppendTextMetaDataSort>false</AppendTextMetaDataSort> <Append>true</Append> <Text /> <Newlines>2</Newlines> <AutoDelay>10</AutoDelay> <BotMaxEdits>0</BotMaxEdits> <SupressTag>false</SupressTag> <RegexTypoFix>true</RegexTypoFix> </Editprefs> <General> <AutoSaveEdit> <Enabled>false</Enabled> <SavePeriod>30</SavePeriod> <SaveFile /> </AutoSaveEdit> <SelectedSummary>correzioni</SelectedSummary> <Summaries> <string>correzioni</string> <string>typo</string> <string>fix vari</string> <string>sistemo</string> </Summaries> <PasteMore> <string /> <string /> <string /> <string /> <string /> <string /> <string /> <string /> <string /> <string /> </PasteMore> <FindText /> <FindRegex>false</FindRegex> <FindCaseSensitive>false</FindCaseSensitive> <WordWrap>true</WordWrap> <ToolBarEnabled>true</ToolBarEnabled> <BypassRedirect>true</BypassRedirect> <AutoSaveSettings>true</AutoSaveSettings> <noSectionEditSummary>false</noSectionEditSummary> <restrictDefaultsortAddition>true</restrictDefaultsortAddition> <restrictOrphanTagging>true</restrictOrphanTagging> <noMOSComplianceFixes>true</noMOSComplianceFixes> <syntaxHighlightEditBox>false</syntaxHighlightEditBox> <highlightAllFind>false</highlightAllFind> <PreParseMode>false</PreParseMode> <NoAutoChanges>false</NoAutoChanges> <OnLoadAction>0</OnLoadAction> <DiffInBotMode>false</DiffInBotMode> <Minor>true</Minor> <AddToWatchlist>2</AddToWatchlist> <TimerEnabled>false</TimerEnabled> <SortListAlphabetically>true</SortListAlphabetically> <AddIgnoredToLog>false</AddIgnoredToLog> <EditToolbarEnabled>true</EditToolbarEnabled> <filterNonMainSpace>false</filterNonMainSpace> <AutoFilterDuplicates>true</AutoFilterDuplicates> <FocusAtEndOfEditBox>false</FocusAtEndOfEditBox> <scrollToUnbalancedBrackets>false</scrollToUnbalancedBrackets> <TextBoxSize>9</TextBoxSize> <TextBoxFont>Courier New</TextBoxFont> <LowThreadPriority>false</LowThreadPriority> <Beep>false</Beep> <Flash>false</Flash> <Minimize>false</Minimize> <LockSummary>false</LockSummary> <SaveArticleList>true</SaveArticleList> <SuppressUsingAWB>false</SuppressUsingAWB> <AddUsingAWBToActionSummaries>false</AddUsingAWBToActionSummaries> <IgnoreNoBots>false</IgnoreNoBots> <ClearPageListOnProjectChange>false</ClearPageListOnProjectChange> <SortInterWikiOrder>true</SortInterWikiOrder> <ReplaceReferenceTags>true</ReplaceReferenceTags> <LoggingEnabled>true</LoggingEnabled> <AlertPreferences> <int>1</int> <int>2</int> <int>3</int> <int>4</int> <int>5</int> <int>6</int> <int>7</int> <int>8</int> <int>9</int> <int>10</int> <int>11</int> <int>12</int> <int>13</int> <int>14</int> <int>15</int> <int>16</int> <int>17</int> <int>18</int> <int>19</int> <int>20</int> <int>21</int> </AlertPreferences> </General> <SkipOptions> <SkipNonexistent>true</SkipNonexistent> <Skipexistent>false</Skipexistent> <SkipWhenNoChanges>true</SkipWhenNoChanges> <SkipSpamFilterBlocked>false</SkipSpamFilterBlocked> <SkipInuse>false</SkipInuse> <SkipWhenOnlyWhitespaceChanged>true</SkipWhenOnlyWhitespaceChanged> <SkipOnlyGeneralFixChanges>true</SkipOnlyGeneralFixChanges> <SkipOnlyMinorGeneralFixChanges>false</SkipOnlyMinorGeneralFixChanges> <SkipOnlyCosmetic>false</SkipOnlyCosmetic> <SkipOnlyCasingChanged>false</SkipOnlyCasingChanged> <SkipIfRedirect>false</SkipIfRedirect> <SkipIfNoAlerts>false</SkipIfNoAlerts> <SkipDoes>false</SkipDoes> <SkipDoesNot>false</SkipDoesNot> <SkipDoesText /> <SkipDoesNotText /> <Regex>false</Regex> <CaseSensitive>false</CaseSensitive> <AfterProcessing>false</AfterProcessing> <SkipNoFindAndReplace>false</SkipNoFindAndReplace> <SkipMinorFindAndReplace>false</SkipMinorFindAndReplace> <SkipNoRegexTypoFix>false</SkipNoRegexTypoFix> <SkipNoDisambiguation>false</SkipNoDisambiguation> <SkipNoLinksOnPage>false</SkipNoLinksOnPage> <GeneralSkipList /> </SkipOptions> <Module> <Enabled>true</Enabled> <Language>C# 3.5</Language> <Code>// implementing the "aggressive" rules is more likely to produce false positives private static readonly bool AGGRESSIVE = true; private static readonly Regex ListingTemplateNamesRegex = Tools.NestedTemplateRegex(new List<string>("listing,see,do,buy,eat,drink,sleep".Split(','))); private static readonly string[] ListingTemplateParamNames = {"type","nome","alt","sito","email","indirizzo","lat","long","indicazioni","tel","numero verde","fax","orari","checkin","checkout","prezzo","descrizione"}; private static readonly string[] ListingPhoneParamNames = {"tel","fax","numero verde"}; private static readonly Regex PhoneNumberRegex = new Regex(@"'*[\d\+\(][\s\d\(\)\-\.'\+]+[\d\)]'*"); private static readonly Regex MailtoRegex = new Regex(@"mailto:[/]*", RegexOptions.IgnoreCase); private static readonly Regex ExcessWhitespaceRegex = new Regex(@"\s\s+", RegexOptions.Singleline); // "http://www.example.com" private static readonly string ValidUrlPattern = @"((http(s)?:)//)?(([a-z]+\.)+)([a-z]+)"; private static readonly Regex ValidUrlRegex = new Regex(ValidUrlPattern, RegexOptions.Singleline | RegexOptions.IgnoreCase); // "[http://www.example.com]" private static readonly Regex FootnoteUrlRegex = new Regex(@"\[(" + ValidUrlPattern + @"([^\]\s]+))\]", RegexOptions.Singleline); // "Foo (disambiguation)" private static readonly Regex CityNameWithDisambiguationRegex = new Regex(@"([^\(]+) \([^\)]+\)", RegexOptions.Singleline); // "blah, CA 99999", "blah CA", etc private static readonly Regex AddressWithStateOrZipRegex = new Regex(@"(.+)[\.,\-]+\s*(AL|alabama|AK|alaska|AZ|arizona|AR|arkansas|CA|california|CO|colorado|CT|connecticut|DC|DE|delaware|FL|florida|GA|georgia|HI|hawaii|ID|idaho|IL|illinois|IN|indiana|IA|iowa|KS|kansas|KY|kentucky|LA|louisiana|ME|maine|MD|maryland|MA|massachusetts|MI|michigan|MN|minnesota|MS|mississippi|MO|missouri|MT|montana|NE|nebraska|NV|nevada|NH|new hampshire|NJ|new jersey|NM|new mexico|NY|new york|NC|north carolina|ND|north dakota|OH|ohio|OK|oklahoma|OR|oregon|PA|pennsylvania|RI|rhode island|SC|south carolina|SD|south dakota|TN|tennessee|TX|texas|UT|utah|VT|vermont|VA|virginia|WA|washington|WV|west virginia|WI|wisconsin|WY|wyoming)([\s,\-]*[0-9]{5})?$", RegexOptions.Singleline | RegexOptions.IgnoreCase); // "* ", "** ", etc private static readonly Regex EmptyListItemRegex = new Regex(@"^\*+\s*\n", RegexOptions.Multiline); private static readonly Regex FootnoteToFrontLinkRegex = new Regex(@"('*)((?!The )\p{Lu}[\w\-'/]*[\w]( (e|del|di|da|&|il|lo|la|le|per|\p{Lu}[\w\-'/]*[\w]))*)('*)[, ]*\[(http[^ ]+)( )*\]"); private static readonly Regex TimeValuesShouldUseColonAsSeperator = new Regex(@"\b([1-9]|10|11|12)\.([0-5][0-9])([ ]*)((a|p)\.?\s*m\.|(a|p)\.?\s*m\b)", RegexOptions.IgnoreCase); private static readonly Regex TimeValuesSuffixAM = new Regex(@"\b([1-9]|10|11|12)(:[0-5][0-9])*[ ]*(a\.\s*m\.|a\s*m\b)", RegexOptions.IgnoreCase); private static readonly Regex TimeValuesSuffixPM = new Regex(@"\b([1-9]|10|11|12)(:[0-5][0-9])*[ ]*(p\.\s*m\.|p\s*m\b)", RegexOptions.IgnoreCase); private static readonly Regex ExternalToInternalLinkWikipedia = new Regex(@"\[http[s]?://it.wikipedia.org/wiki/([^\] ]+)[ ]+([^\]]+)]", RegexOptions.IgnoreCase); private static readonly Regex ExternalToInternalLinkWikipediaNoText = new Regex(@"\[http[s]?://it.wikipedia.org/wiki/([^\] ]+)[ ]*]", RegexOptions.IgnoreCase); private static readonly Regex ExternalToInternalLinkWikivoyage = new Regex(@"\[http[s]?://it.wikivoyage.org/wiki/([^\] ]+)[ ]+([^\]]+)]", RegexOptions.IgnoreCase); private static readonly Regex ExternalToInternalLinkWikivoyageNoText = new Regex(@"\[http[s]?://it.wikivoyage.org/wiki/([^\] ]+)[ ]*]", RegexOptions.IgnoreCase); // "* blah blah blah", "** blah blah blah", etc private static readonly Regex CandidateListingItemRegex = new Regex(@"^\*+\s*([^\{]{2}.+)$", RegexOptions.Multiline); private static readonly Regex ListingNameRegex = new Regex(@"(il\s+)*'''(.{3,}?)'''", RegexOptions.IgnoreCase); // "[http://www.example.com/ Example Text]" private static readonly Regex ExternalLinkWithTextRegex = new Regex(@"\[(http[^\]\s]+)\s+([^\]]+)\]", RegexOptions.IgnoreCase); // "123-456-7890" private static readonly string ListingPhoneNumber = @"((''|\+|\()*\d+(''|\)*)[\s\-]+)+(''|\+|\()*\d+(''|\)*)( ext\.? \d+)?"; private static readonly Regex ListingPhoneNumberRegex = new Regex(ListingPhoneNumber, RegexOptions.IgnoreCase); // "fax: 123-456-7890" private static readonly string ListingFaxNumber = @"(\(''|''\(|\()?fax(:)?(\s)*(" + ListingPhoneNumber + @")(''\)|\)''|\))?"; private static readonly Regex ListingFaxNumberRegex = new Regex(ListingFaxNumber, RegexOptions.IgnoreCase); // "tele: 123-456-7890" and similar private static readonly string ListingPhoneNumberWithLabel = @"(\(''|''\(|\()?(\u260e|chiama|call:telefono:|telephone|tel:|tel\.:|tel\.|tel|tel:|tel|ph:|ph\.:|ph\.|ph|\u260E)(\s)*(" + ListingPhoneNumber + @")(''\)|\)''|\))?"; private static readonly Regex ListingPhoneNumberWithLabelRegex = new Regex(ListingPhoneNumberWithLabel, RegexOptions.IgnoreCase); // "toll-free: 123-456-7890" and similar private static readonly string ListingTollfreeNumber = @"(\(''|''\(|\()?(toll[ \-]?free)(:)?(\s)*(" + ListingPhoneNumber + @")(''\)|\)''|\))?"; private static readonly Regex ListingTollfreeNumberRegex = new Regex(ListingTollfreeNumber, RegexOptions.IgnoreCase); private static readonly string InvalidLeadingOrTrailingPunctuation = @",|\-|\*|\:|\–"; private static readonly string InvalidLeadingPunctuation = @"\.|!|\?|\)|\]|\}|&mdash;"; private static readonly string InvalidTrailingPunctuation = @"\(|\[|\{"; private static readonly string InvalidDuplicatePunctuation = @"\.|!|\?|" + InvalidLeadingOrTrailingPunctuation; private static readonly Regex InvalidLeadingPunctuationRegex = new Regex(@"^(\s|" + InvalidLeadingPunctuation + "|" + InvalidLeadingOrTrailingPunctuation + @")+", RegexOptions.Multiline); private static readonly Regex InvalidTrailingPunctuationRegex = new Regex(@"(\s|" + InvalidTrailingPunctuation + "|" + InvalidLeadingOrTrailingPunctuation + @")+$", RegexOptions.Multiline); private static readonly Regex InvalidDuplicatePunctuationRegex = new Regex(@"(" + InvalidDuplicatePunctuation + @"|\s)+(" + InvalidDuplicatePunctuation + @")"); // "email: [email protected]" OR "mailto:[email protected]" OR "[email protected]" private static readonly string ListingEmail = @"(mailto:|e-mail:)?\s*(\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b)"; private static readonly Regex ListingEmailRegex = new Regex(ListingEmail, RegexOptions.IgnoreCase); // "1234 First St" private static readonly string ListingAddress = @"([\d]+([/\-][\d]+)? ([nesw]\.? )?([\p{L}\d]+[ \.\-]*){1,3} (avenue|ave|av|boulevard|blvd|court|ct|drive|dr|expressway|expwy|freeway|fwy|highway( \d{1,3})?|hwy( \d{1,3})?|lane|ln|loop|parkway|pkwy|place|pl|road|rd|row|street|st|way|via|viale|piazza|gåta|väg|Straße|Strasse|parcheggio|statale|ulica|ulitsa|uliza|vicolo)\b(\.? (#(\s)*[\d]+|nord|nordest|Nord|Est|NO|N|Est|E|Sud|SE|SO|S|Ovest|O)\b)?)[\. , ]*"; private static readonly Regex ListingAddressRegex = new Regex(ListingAddress, RegexOptions.IgnoreCase); // the above pattern will match things like "25 km by road", so add a pattern to catch those private static readonly string ListingAddressFalsePositives = @"\b(km|kilometer|kilometers|mi|mile|miles)\b"; private static readonly Regex ListingAddressFalsePositivesRegex = new Regex(ListingAddressFalsePositives, RegexOptions.IgnoreCase); // "Calle Ricardo Montalban, 452" private static readonly string ListingAddressInternational = @"(avenida|ave|av|calle|estrada|est|rua)(\.)? ([\p{L}\d]+[ \.\-]*){1,3}, [\d]+([/\-][\d]+)?"; private static readonly Regex ListingAddressInternationalRegex = new Regex(ListingAddressInternational, RegexOptions.IgnoreCase); private static readonly Regex ListingAddressIsDirectionsRegex = new Regex(@"^(between|corner|end|next|on|)\s", RegexOptions.Multiline); //private static readonly Regex CityStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List<string>("outlinecity,usablecity,guidecity,starcity".Split(','))); //private static readonly Regex CountryStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List<string>("outlinecountry,usablecountry,guidecountry,starcountry".Split(','))); //private static readonly Regex DiveguideStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List<string>("outlinediveguide,usablediveguide,guidediveguide,stardiveguide".Split(','))); //private static readonly Regex DistrictStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List<string>/("outlinedistrict,usabledistrict,guidedistrict,stardistrict".Split(','))); //private static readonly Regex ItineraryStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List<string>("outlineitinerary,usableitinerary,guideitinerary,staritinerary".Split(','))); //private static readonly Regex ParkStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List<string>("outlinepark,usablepark,guidepark,starpark".Split(','))); //private static readonly Regex PhrasebookStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List<string>("outlinephrasebook,usablephrasebook,guidephrasebook,starphrasebook".Split(','))); //private static readonly Regex RegionStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List<string>("outlineregion,usableregion,guideregion,starregion".Split(','))); //private static readonly Regex TopicStatusTemplateNamesRegex = Tools.NestedTemplateRegex(new List<string>("outlinetopic,usabletopic,guidetopic,startopic".Split(','))); //private static readonly Regex ListingAltParamRegex = new Regex(@"\|\s*alt\s*=", RegexOptions.Singleline); // "()", "[]", "{}" private static readonly Regex EmptyPunctuationRegex = new Regex(@"(\(\s*\)|\[\s*\]|\{\s*\})"); private static readonly Regex OnlyPunctuationRegex = new Regex(@"^['\-\(\)\[\]\{\}\*\.\?!\s]+$", RegexOptions.Singleline); // match a single digit private static readonly Regex DigitRegex = new Regex(@"\d"); private static readonly Regex DoubleSpaceRegex = new Regex(@"\s{2,}"); private static readonly Regex InvalidGetInHeadingRegex = new Regex(@"^(get in|Arrivare|come arrivare|getting in|getting there)", RegexOptions.IgnoreCase); private static readonly Regex InvalidGetAroundHeadingRegex = new Regex(@"^(get around|getting around)", RegexOptions.IgnoreCase); private static readonly Regex InvalidSeeHeadingRegex = new Regex(@"^(Monumenti|monumenti|Vedere|Attrazioni|attrazioni)", RegexOptions.IgnoreCase); private static readonly Regex InvalidDoHeadingRegex = new Regex(@"^(Attività|Tempo libero)", RegexOptions.IgnoreCase); private static readonly Regex InvalidBuyHeadingRegex = new Regex(@"^(shopping|negozi)", RegexOptions.IgnoreCase); private static readonly Regex InvalidEatHeadingRegex = new Regex(@"^(ristoranti|a pranzo|Mangiare)", RegexOptions.IgnoreCase); private static readonly Regex InvalidDrinkHeadingRegex = new Regex(@"^(bars|nightlife)", RegexOptions.IgnoreCase); private static readonly Regex InvalidSleepHeadingRegex = new Regex(@"^(accommodation|hotels)", RegexOptions.IgnoreCase); private static readonly Regex InvalidGoNextHeadingRegex = new Regex(@"^(nei dintorni|Uscire)", RegexOptions.IgnoreCase); private static readonly Regex MidrangeHeadingRegex = new Regex(@"^prezzi[ \-]*modici", RegexOptions.IgnoreCase); private static readonly Regex ByOnHeadingRegex = new Regex(@"^(presso|su) (.+)", RegexOptions.IgnoreCase); public string ProcessArticle(string articleText, string articleTitle, int wikiNamespace, out string summary, out bool skip) { string originalText = articleText; summary = ""; skip = false; articleText = UpdateHeadings(articleText, articleTitle, wikiNamespace, ref summary, ref skip); articleText = ExternalToInternalLink(articleText, articleTitle, wikiNamespace, ref summary, ref skip); articleText = FootnoteToFrontlink(articleText, articleTitle, wikiNamespace, ref summary, ref skip); articleText = FormatTimeValues(articleText, articleTitle, wikiNamespace, ref summary, ref skip); if (AGGRESSIVE) { articleText = ConvertTextToListings(articleText, articleTitle, wikiNamespace, ref summary, ref skip); } articleText = FormatListings(articleText, articleTitle, wikiNamespace, ref summary, ref skip); if (articleText.Equals(originalText)) { skip = true; } return articleText; } // ensure that headings match the article templates public string UpdateHeadings(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) { foreach(Match m in WikiRegexes.Headings.Matches(articleText)) { string originalHeading = m.Value; string originalTitle = m.Groups[1].Value; string newTitle = originalTitle; string lowerTitle = originalTitle.ToLower().Trim(); int headingLevel = 1; while (originalHeading[headingLevel] == '=') { headingLevel++; } Match match = null; if (headingLevel == 2) { if (MatchText(lowerTitle, InvalidGetInHeadingRegex, ref match)) { newTitle = "Come arrivare"; } else if (MatchText(lowerTitle, InvalidGetAroundHeadingRegex, ref match)) { newTitle = "Come spostarsi"; } else if (MatchText(lowerTitle, InvalidSeeHeadingRegex, ref match)) { newTitle = "Cosa vedere"; } else if (MatchText(lowerTitle, InvalidDoHeadingRegex, ref match)) { newTitle = "Cosa fare"; } else if (MatchText(lowerTitle, InvalidBuyHeadingRegex, ref match)) { newTitle = "Acquisti"; } else if (MatchText(lowerTitle, InvalidEatHeadingRegex, ref match)) { newTitle = "Dove mangiare"; } else if (MatchText(lowerTitle, InvalidDrinkHeadingRegex, ref match)) { newTitle = "Come divertirsi"; } else if (MatchText(lowerTitle, InvalidSleepHeadingRegex, ref match)) { newTitle = "Dove alloggiare"; } else if (MatchText(lowerTitle, InvalidGoNextHeadingRegex, ref match)) { newTitle = "Nei dintorni"; } } else { if (MatchText(lowerTitle, MidrangeHeadingRegex, ref match)) { newTitle = "Prezzi modici"; } else if (MatchText(lowerTitle, ByOnHeadingRegex, ref match)) { newTitle = Capitalize(match.Groups[1].Value) + " " + match.Groups[2].Value.ToLower(); } } if (!newTitle.Equals(originalTitle)) { string headingBars = originalHeading.Substring(0, headingLevel); articleText = articleText.Replace(originalHeading, headingBars + newTitle + headingBars); summary = UpdateEditSummary(summary, "sistemo sezioni"); } } return articleText; } // convert footnote links to frontlinks public string FootnoteToFrontlink(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) { string originalText = articleText; articleText = FootnoteToFrontLinkRegex.Replace(articleText, "$1[$6 $2]$5"); if (!articleText.Equals(originalText)) { summary = UpdateEditSummary(summary, "sistemo note"); } return articleText; } // convert external links to interwiki/internal links public string ExternalToInternalLink(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) { string originalText = articleText; articleText = ExternalToInternalLinkWikipedia.Replace(articleText, "[[w:$1|$2]]"); articleText = ExternalToInternalLinkWikipediaNoText.Replace(articleText, "[[w:$1]]"); articleText = ExternalToInternalLinkWikivoyage.Replace(articleText, "[[$1|$2]]"); articleText = ExternalToInternalLinkWikivoyageNoText.Replace(articleText, "[[$1]]"); if (!articleText.Equals(originalText)) { summary = UpdateEditSummary(summary, "fix link"); } return articleText; } public string FormatTimeValues(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) { string originalText = articleText; articleText = TimeValuesShouldUseColonAsSeperator.Replace(articleText, "$1:$2$3$4"); articleText = TimeValuesSuffixAM.Replace(articleText, "$1$2AM"); articleText = TimeValuesSuffixPM.Replace(articleText, "$1$2PM"); if (!articleText.Equals(originalText)) { summary = UpdateEditSummary(summary, "sistemo date"); } return articleText; } public string ConvertTextToListings(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) { //if (!IsCityArticle(articleText) && !IsDistrictArticle(articleText) && !IsParkArticle(articleText)) { // do not try to convert text to listings for non-city or park articles //return articleText; //} string originalText = articleText; // loop through all sections foreach(KeyValuePair<string, string> sectionData in SplitToSecondLevelSections(articleText)) { string sectionName = sectionData.Key; if (!sectionName.ToLower().Equals("see") && !sectionName.ToLower().Equals("do") && !sectionName.ToLower().Equals("buy") && !sectionName.ToLower().Equals("eat") && !sectionName.ToLower().Equals("drink") && !sectionName.ToLower().Equals("sleep")) { // only convert text that's in a section that supports non-generic listings continue; } string listingType = GetValidListingTypeForSection(sectionName); string sectionText = sectionData.Value; // get all list items within the section foreach(Match m in CandidateListingItemRegex.Matches(sectionText)) { string listItemText = m.Groups[1].Value; string templateCall = ConvertListingItemtoTemplatedListing(listItemText, listingType, ref summary); if (templateCall != "") { articleText = articleText.Replace(listItemText, templateCall); summary = UpdateEditSummary(summary, "converto in listing"); } } } return articleText; } public string ConvertListingItemtoTemplatedListing(string listItemText, string listingType, ref string summary) { string templateCall = "{{" + listingType + "}}"; if (!ProcessListingNameInListItem(ref listItemText, ref templateCall)) { // if we don't have a listing name don't bother trying to convert anything else return ""; } ProcessListingPhoneInListItem(ref listItemText, ref templateCall); ProcessListingEmailInListItem(ref listItemText, ref templateCall); ProcessListingUrlInListItem(ref listItemText, ref templateCall); ProcessListingAddressInListItem(ref listItemText, ref templateCall); ProcessListingContentInListItem(ref listItemText, ref templateCall); return templateCall; } private bool ProcessListingNameInListItem(ref string listItemText, ref string templateCall) { Match m = ListingNameRegex.Match(listItemText); if (!m.Success || m.Index != 0) { // if there isn't a name at the beginning of the listing, don't convert return false; } string nome = m.Groups[2].Value; templateCall = Tools.SetTemplateParameterValue(templateCall, "nome", nome); // see if the nome is front-linked Match sitoMatch = ExternalLinkWithTextRegex.Match(nome); if (sitoMatch.Success && sitoMatch.Index == 0) { // split the nome & sito fields string sito = sitoMatch.Groups[1].Value; templateCall = Tools.SetTemplateParameterValue(templateCall, "sito", sito); nome = sitoMatch.Groups[2].Value; templateCall = Tools.SetTemplateParameterValue(templateCall, "nome", nome); } // remove nome from list item text listItemText = RemoveValueFromListItemText(listItemText, m.Value); return true; } private void ProcessListingPhoneInListItem(ref string listItemText, ref string templateCall) { Match telMatch = ListingPhoneNumberWithLabelRegex.Match(listItemText); if (telMatch.Success) { string tel = telMatch.Groups[4].Value; templateCall = Tools.SetTemplateParameterValue(templateCall, "tel", tel); listItemText = RemoveValueFromListItemText(listItemText, telMatch.Value); } Match faxMatch = ListingFaxNumberRegex.Match(listItemText); if (faxMatch.Success) { string fax = faxMatch.Groups[4].Value; templateCall = Tools.SetTemplateParameterValue(templateCall, "fax", fax); listItemText = RemoveValueFromListItemText(listItemText, faxMatch.Value); } Match tollfreeMatch = ListingTollfreeNumberRegex.Match(listItemText); if (tollfreeMatch.Success) { string tollfree = tollfreeMatch.Groups[5].Value; templateCall = Tools.SetTemplateParameterValue(templateCall, "tollfree", "numero verde"); listItemText = RemoveValueFromListItemText(listItemText, tollfreeMatch.Value); } if (!telMatch.Success) { // try to find a tel number without a label telMatch = ListingPhoneNumberRegex.Match(listItemText); if (telMatch.Success) { string tel = telMatch.Value; if (DigitRegex.Matches(tel).Count > 6) { // only consider a tel number valid if it contains more than six digits templateCall = Tools.SetTemplateParameterValue(templateCall, "tel", tel); listItemText = RemoveValueFromListItemText(listItemText, telMatch.Value); } } } } private void ProcessListingEmailInListItem(ref string listItemText, ref string templateCall) { Match emailMatch = ListingEmailRegex.Match(listItemText); if (emailMatch.Success) { string email = emailMatch.Groups[2].Value; templateCall = Tools.SetTemplateParameterValue(templateCall, "email", email); listItemText = RemoveValueFromListItemText(listItemText, emailMatch.Value); } } private void ProcessListingUrlInListItem(ref string listItemText, ref string templateCall) { if (Tools.GetTemplateParameterValue(templateCall, "sito") != "") { // sito was already set when processing listing nome return; } Match sitoMatch = FootnoteUrlRegex.Match(listItemText); if (sitoMatch.Success) { string sito = sitoMatch.Groups[1].Value; templateCall = Tools.SetTemplateParameterValue(templateCall, "sito", sito); listItemText = RemoveValueFromListItemText(listItemText, sitoMatch.Value); } } private void ProcessListingAddressInListItem(ref string listItemText, ref string templateCall) { Match indirizzoMatch = ListingAddressRegex.Match(listItemText); if (indirizzoMatch.Success) { string indirizzo = indirizzoMatch.Groups[1].Value; Match falsePositiveMatch = ListingAddressFalsePositivesRegex.Match(indirizzo); if (!falsePositiveMatch.Success) { templateCall = Tools.SetTemplateParameterValue(templateCall, "indirizzo", indirizzo); listItemText = RemoveValueFromListItemText(listItemText, indirizzoMatch.Value); } } else { indirizzoMatch = ListingAddressInternationalRegex.Match(listItemText); if (indirizzoMatch.Success) { string indirizzo = indirizzoMatch.Groups[1].Value; templateCall = Tools.SetTemplateParameterValue(templateCall, "indirizzo", indirizzo); listItemText = RemoveValueFromListItemText(listItemText, indirizzoMatch.Value); } } } private void ProcessListingContentInListItem(ref string listItemText, ref string templateCall) { if (String.IsNullOrEmpty(listItemText)) { return; } // strip empty punctuation listItemText = EmptyPunctuationRegex.Replace(listItemText, ""); // strip sentence fragments left over from removing the listing nome if (listItemText.ToLower().StartsWith("is ")) { listItemText = listItemText.Substring("is ".Length); } // make sure first character is capitalized listItemText = Capitalize(listItemText); // if only punctuation is left, remove everything if (OnlyPunctuationRegex.IsMatch(listItemText)) { listItemText = ""; } templateCall = Tools.SetTemplateParameterValue(templateCall, "descrizione", listItemText); } private string RemoveValueFromListItemText(string listItemText, string value) { listItemText = listItemText.Replace(value, "").Trim(); listItemText = InvalidDuplicatePunctuationRegex.Replace(listItemText, "$1"); listItemText = StripLeadingPunctuation(listItemText).Trim(); return listItemText; } // Perform various tasks on listings to ensure params and other values // are formatted correctly. public string FormatListings(string articleText, string articleTitle, int wikiNamespace, ref string summary, ref bool skip) { string originalText = articleText; // loop through all sections foreach(KeyValuePair<string, string> sectionData in SplitToSecondLevelSections(articleText)) { string sectionName = sectionData.Key; string sectionText = sectionData.Value; // get all listing tags within the section foreach(Match m in ListingTemplateNamesRegex.Matches(sectionText)) { string templateCall = m.Value; string originalTemplateCall = m.Value; templateCall = ConvertGenericListingToSpecificType(templateCall, ref summary); templateCall = MatchListingTypeToSection(templateCall, sectionName, ref summary); templateCall = FormatListingParams(templateCall, ref summary); templateCall = SanitizeListingPhoneNumbers(templateCall, ref summary); templateCall = SanitizeListingEmail(templateCall, ref summary); templateCall = SanitizeListingUrl(templateCall, ref summary); if (AGGRESSIVE) { templateCall = SanitizeListingAddress(templateCall, articleTitle, ref summary); } if (!templateCall.Equals(originalTemplateCall)) { articleText = articleText.Replace(originalTemplateCall, templateCall); } } } return articleText; } // change "{{listing|type=xyz|...}}" to "{{xyz|...}}" public string ConvertGenericListingToSpecificType(string templateCall, ref string summary) { string originalTemplateCall = templateCall; string listingType = Tools.GetTemplateName(templateCall); if (listingType.Equals("listing")) { string templateType = Tools.GetTemplateParameterValue(templateCall, "type"); if (templateType.Equals("see") || templateType.Equals("do") || templateType.Equals("buy") || templateType.Equals("eat") || templateType.Equals("drink") || templateType.Equals("sleep")) { templateCall = Tools.RenameTemplate(templateCall, templateType); templateCall = Tools.RemoveTemplateParameter(templateCall, "type"); } } if (!templateCall.Equals(originalTemplateCall)) { summary = UpdateEditSummary(summary, "listing appropriato"); } return templateCall; } // make sure listings are formatted according to the style guidelines in // Wikivoyage:Listings public string FormatListingParams(string templateCall, ref string summary) { string originalTemplateCall = templateCall; string listingType = Tools.GetTemplateName(templateCall); string formattedValue = "{{" + listingType + "\n"; // loop through expected template arguments and format appropriately foreach(string param in ListingTemplateParamNames) { if (param.Equals("descrizione")) { continue; } string paramValue = Tools.GetTemplateParameterValue(templateCall, param); if (param.Equals("type") && (paramValue == "" || !listingType.Equals("listing"))) { // only listing uses the "type" attribute if (paramValue == "") { templateCall = Tools.RemoveTemplateParameter(templateCall, param); } continue; } if ((param.Equals("image") || param.Equals("lastedit")) && paramValue == "") { // empty image & lastedit attributes are unnecessary continue; } if (listingType.Equals("sleep") && param.Equals("orari") && paramValue == "") { // sleep listings don't use the "orari" attribute if (paramValue == "") { templateCall = Tools.RemoveTemplateParameter(templateCall, param); } continue; } if (!listingType.Equals("sleep") && (param.Equals("checkin") || param.Equals("checkout"))) { // only sleep listings use the "checkin" and "checkout" attributes if (paramValue == "") { templateCall = Tools.RemoveTemplateParameter(templateCall, param); } continue; } //if (param.Equals("alt") && paramValue == "" && !ListingAltParamRegex.IsMatch(templateCall)) { // do not add an alt tag if it isn't already present //continue; //} // replace excess whitespace with single spaces paramValue = DoubleSpaceRegex.Replace(paramValue, " "); formattedValue += "| " + param + "=" + paramValue; // add either a newline or a space after the param value, depending on param and template type if (param.Equals("email") || param.Equals("indicazioni") || param.Equals("fax") || param.Equals("prezzo") || param.Equals("image") || param.Equals("lastedit")) { formattedValue += "\n"; } else { formattedValue += " "; } templateCall = Tools.RemoveTemplateParameter(templateCall, param); } // loop through any unexpected template args and format on their own lines int remainingTemplateArgs = Tools.GetTemplateArgumentCount(templateCall); foreach(KeyValuePair<string, string> templateParameter in Tools.GetTemplateParameterValues(templateCall)) { string param = templateParameter.Key; if (param.Equals("descrizione")) { continue; } string paramValue = templateParameter.Value; if (paramValue == "") { // any empty, unrecognized listing params can be removed continue; } formattedValue += "| " + param + "=" + paramValue + "\n"; } // now add template descrizione on its own line formattedValue += "| descrizione=" + Tools.GetTemplateParameterValue(templateCall, "descrizione") + "\n"; formattedValue += "}}"; if (!originalTemplateCall.Equals(formattedValue)) { // suppress edit summary for now - it is being applied to any article with listings // whether they are updated or not // summary = UpdateEditSummary(summary, "formato listing"); } return formattedValue; } // update the listing tel number fields as much as possible to match // Wikivoyage:Phone numbers public string SanitizeListingPhoneNumbers(string templateCall, ref string summary) { string originalTemplateCall = templateCall; // loop through expected template arguments and format appropriately foreach(string param in ListingPhoneParamNames) { string paramValue = Tools.GetTemplateParameterValue(templateCall, param); paramValue = SanitizePhoneNumber(paramValue); templateCall = Tools.UpdateTemplateParameterValue(templateCall, param, paramValue); } if (!templateCall.Equals(originalTemplateCall)) { summary = UpdateEditSummary(summary, "formato phone"); } return templateCall; } // update the listing email field to ensure it is valid public string SanitizeListingEmail(string templateCall, ref string summary) { string originalTemplateCall = templateCall; string email = Tools.GetTemplateParameterValue(templateCall, "email"); email = MailtoRegex.Replace(email, "").Trim(); templateCall = Tools.UpdateTemplateParameterValue(templateCall, "email", email); if (!templateCall.Equals(originalTemplateCall)) { summary = UpdateEditSummary(summary, "fix e-mail"); } return templateCall; } // update the listing URL field to ensure it is valid public string SanitizeListingUrl(string templateCall, ref string summary) { string originalTemplateCall = templateCall; string sito = Tools.GetTemplateParameterValue(templateCall, "sito"); Match match = FootnoteUrlRegex.Match(sito); if (match.Success) { sito = match.Groups[1].Value; } match = ValidUrlRegex.Match(sito); if (match.Success && !sito.ToLower().StartsWith("http://") && !sito.ToLower().StartsWith("https://") && !sito.ToLower().StartsWith("//")) { sito = "http://" + sito; } templateCall = Tools.UpdateTemplateParameterValue(templateCall, "sito", sito); if (!templateCall.Equals(originalTemplateCall)) { summary = UpdateEditSummary(summary, "sistemo indirizzo web"); } return templateCall; } // update the listing indirizzo field to ensure it is valid public string SanitizeListingAddress(string templateCall, string articleName, ref string summary) { string originalTemplateCall = templateCall; string indirizzo = Tools.GetTemplateParameterValue(templateCall, "indirizzo"); if (String.IsNullOrEmpty(indirizzo)) { return templateCall; } Match m = ListingAddressIsDirectionsRegex.Match(indirizzo); if (m.Success) { // the indirizzo field belongs in the indicazioni field string indicazioni = Tools.GetTemplateParameterValue(templateCall, "indicazioni"); if (String.IsNullOrEmpty(indicazioni)) { templateCall = Tools.UpdateTemplateParameterValue(templateCall, "indicazioni", indirizzo); templateCall = Tools.UpdateTemplateParameterValue(templateCall, "indirizzo", ""); summary = UpdateEditSummary(summary, "indicazioni"); return templateCall; } } // strip out state and zip code if present m = AddressWithStateOrZipRegex.Match(indirizzo); if (m.Success) { indirizzo = m.Groups[1].Value.Trim(); } indirizzo = StripStrayPunctuation(indirizzo); // strip out the city if it is present string city = GetCityFromArticleName(articleName); if (indirizzo.ToLower().EndsWith(city.ToLower())) { int pos = indirizzo.ToLower().LastIndexOf(city.ToLower()); indirizzo = indirizzo.Substring(0, pos).Trim(); } indirizzo = StripStrayPunctuation(indirizzo); // properly abbreviate street name indirizzo = AbbreviateStreeType(indirizzo, "via", "Via"); indirizzo = AbbreviateStreeType(indirizzo, "Piazza", "Pz"); indirizzo = AbbreviateStreeType(indirizzo, "Viale", "V.le"); indirizzo = AbbreviateStreeType(indirizzo, "Ulica", "Ul"); indirizzo = AbbreviateStreeType(indirizzo, "Ulitsa", "Ul"); indirizzo = AbbreviateStreeType(indirizzo, "Uliza", "Ul."); indirizzo = AbbreviateStreeType(indirizzo, "Prospekt", "Pr"); indirizzo = AbbreviateStreeType(indirizzo, "Strasse", "Str"); indirizzo = AbbreviateStreeType(indirizzo, "Straße", "Str"); templateCall = Tools.UpdateTemplateParameterValue(templateCall, "indirizzo", indirizzo); if (!templateCall.Equals(originalTemplateCall)) { summary = UpdateEditSummary(summary, "indirizzi"); } return templateCall; } // make sure that the listing type matches the section in which the listing // is found (example: "see" listings in the "See" section) public string MatchListingTypeToSection(string templateCall, string sectionName, ref string summary) { string originalTemplateCall = templateCall; if (sectionName.ToLower() == "eat and drink" || sectionName.ToLower() == "see and do") { // skip these "combined" sections return templateCall; } string expectedListingType = GetValidListingTypeForSection(sectionName); string listingType = Tools.GetTemplateName(templateCall); if (!listingType.Equals(expectedListingType)) { templateCall = Tools.RenameTemplate(templateCall, expectedListingType); } if (!templateCall.Equals(originalTemplateCall)) { summary = UpdateEditSummary(summary, "aggiorno listing"); } return templateCall; } // return a map of section name-section descrizione for all second level headings. // the opening text of the article is returned without a section name private static List<KeyValuePair<string, string>> SplitToSecondLevelSections(string articleText) { List<KeyValuePair<string, string>> sections = new List<KeyValuePair<string, string>>(); int lastmatchpos = 0; Match lastMatch = null; foreach(Match m in WikiRegexes.HeadingLevelTwo.Matches(articleText)) { if (m.Index > 0) { // Don't add empty first section if page starts with heading string sectionContent = articleText.Substring(lastmatchpos, m.Index-lastmatchpos); string sectionName = (lastMatch != null) ? lastMatch.Groups[1].Value.Trim() : ""; sections.Add(new KeyValuePair<string, string>(sectionName, sectionContent)); } lastmatchpos = m.Index; lastMatch = m; } // Add text of final section string sectionContentLast = articleText.Substring(lastmatchpos); string sectionNameLast = (lastMatch != null) ? lastMatch.Groups[1].Value : ""; sections.Add(new KeyValuePair<string, string>(sectionNameLast, sectionContentLast)); return sections; } // return the expected listing type for the given section name ("See" returns "see"). private static string GetValidListingTypeForSection(string sectionName) { if (sectionName == "Cosa vedere") { return "see"; } if (sectionName == "Cosa fare") { return "do"; } if (sectionName == "Acquisti") { return "buy"; } if (sectionName == "Dove mangiare" || sectionName.ToLower() == "Mangiare") { return "eat"; } if (sectionName == "Come divertirsi") { return "drink"; } if (sectionName == "Dove alloggiare") { return "sleep"; } else { return "listing"; } } private static string SanitizePhoneNumber(string telNumberText) { // strip out the tel number, in case it is contained within other text // such as "888-888-8888 (front office)" Match match = PhoneNumberRegex.Match(telNumberText); if (match.Success) { string telNumber = match.Value; string originalPhoneNumber = match.Value; // remove invalid characters telNumber = telNumber.Replace("'", ""); telNumber = telNumber.Replace("(", " ").Trim(); telNumber = telNumber.Replace(")", " ").Trim(); // convert periods to dashes telNumber = telNumber.Replace(".", "-"); telNumber = ExcessWhitespaceRegex.Replace(telNumber, " "); // if there is a pattern like " -", "- ", "+ " left, replace the space telNumber = telNumber.Replace(" -", "-"); telNumber = telNumber.Replace("- ", "-"); telNumber = telNumber.Replace("+ ", "+"); // if the tel number starts with a 1, change it to +1 if (telNumber.StartsWith("1 ") || telNumber.StartsWith("1-")) { telNumber = "+" + telNumber; } telNumberText = telNumberText.Replace(originalPhoneNumber, telNumber); } return telNumberText; } // return the city from the article name. if the article name is "Foo (Disambiguation)" // then this method returns "Foo". private static string GetCityFromArticleName(string articleName) { string basePageName = Tools.BasePageName(articleName); Match match = CityNameWithDisambiguationRegex.Match(basePageName); return (match.Success) ? match.Groups[1].Value : basePageName; } // if the indirizzo ends in a full street type value, convert to the abbreviated value private static string AbbreviateStreeType(string indirizzo, string invalidStreetType, string validStreetType) { if (indirizzo.ToLower().EndsWith(" " + invalidStreetType.ToLower())) { int pos = indirizzo.ToLower().LastIndexOf(invalidStreetType.ToLower()); if (pos > 0) { indirizzo = indirizzo.Substring(0, pos) + validStreetType; } } return indirizzo; } // remove any leading or trailing punctuation private static string StripStrayPunctuation(string text) { return StripPunctuation(text, true, true); } // remove any leading punctuation private static string StripLeadingPunctuation(string text) { return StripPunctuation(text, true, false); } // remove any trailing punctuation private static string StripTrailingPunctuation(string text) { return StripPunctuation(text, false, true); } // remove any leading punctuation private static string StripPunctuation(string text, bool stripLeading, bool stripTrailing) { if (stripTrailing) { text = InvalidTrailingPunctuationRegex.Replace(text, ""); } if (stripLeading) { text = InvalidLeadingPunctuationRegex.Replace(text, ""); } return text; } // return true if the text matches the pattern, otherwise return null, the "match" // param will be populated with the match object private static bool MatchText(string matchText, Regex regex, ref Match match) { match = regex.Match(matchText); return (match.Success); } private static string Capitalize(string text) { if (String.IsNullOrEmpty(text)) { return text; } // make sure first character is capitalized return (text.Length == 1) ? Char.ToUpper(text[0]) + "" : Char.ToUpper(text[0]) + text.Substring(1); } // add the value to the edit summary if it is not already present private static string UpdateEditSummary(string summary, string textToAdd) { if (summary == "") { return textToAdd; } foreach(string summaryField in summary.Split(',')) { if (summaryField.Trim().Equals(textToAdd)) { // text already present in edit summary return summary; } } return summary += ", " + textToAdd; } // return true if the article contains a city status template //public static bool IsCityArticle(string articleText) { // return CityStatusTemplateNamesRegex.IsMatch(articleText); //} // return true if the article contains a country status template //public static bool IsCountryArticle(string articleText) { // return CountryStatusTemplateNamesRegex.IsMatch(articleText); //} // return true if the article contains a dive guide status template //public static bool IsDiveguideArticle(string articleText) { // return DiveguideStatusTemplateNamesRegex.IsMatch(articleText); //} // return true if the article contains a district status template //public static bool IsDistrictArticle(string articleText) { // return DistrictStatusTemplateNamesRegex.IsMatch(articleText); //} // return true if the article contains an itinerary status template //public static bool IsItineraryArticle(string articleText) { // return ItineraryStatusTemplateNamesRegex.IsMatch(articleText); //} // return true if the article contains a park status template //public static bool IsParkArticle(string articleText) { // return ParkStatusTemplateNamesRegex.IsMatch(articleText); //} // return true if the article contains a phrasebook status template //public static bool IsPhrasebookArticle(string articleText) { // return PhrasebookStatusTemplateNamesRegex.IsMatch(articleText); //} // return true if the article contains a region status template //public static bool IsRegionArticle(string articleText) { // return RegionStatusTemplateNamesRegex.IsMatch(articleText); //} // return true if the article contains a topic status template //public static bool IsTopicArticle(string articleText) { // return TopicStatusTemplateNamesRegex.IsMatch(articleText); //} // TODO: // - clean up frontlink conversion logic // - move tollfree numbers to tollfree in listings // - don't allow "otheruses" to be moved above the page banner</Code> </Module> <ExternalProgram> <Enabled>false</Enabled> <Skip>false</Skip> <Program /> <Parameters /> <PassAsFile>true</PassAsFile> <OutputFile /> </ExternalProgram> <Disambiguation> <Enabled>false</Enabled> <Link /> <Variants /> <ContextChars>20</ContextChars> </Disambiguation> <Special> <namespaceValues> <int>0</int> <int>1</int> <int>2</int> <int>3</int> <int>4</int> <int>5</int> <int>6</int> <int>7</int> <int>10</int> <int>11</int> <int>14</int> <int>15</int> </namespaceValues> <remDupes>true</remDupes> <sortAZ>true</sortAZ> <filterTitlesThatContain>false</filterTitlesThatContain> <filterTitlesThatContainText /> <filterTitlesThatDontContain>false</filterTitlesThatDontContain> <filterTitlesThatDontContainText /> <areRegex>false</areRegex> <opType>-1</opType> <remove /> </Special> <Tool> <ListComparerUseCurrentArticleList>0</ListComparerUseCurrentArticleList> <ListSplitterUseCurrentArticleList>0</ListSplitterUseCurrentArticleList> <DatabaseScannerUseCurrentArticleList>0</DatabaseScannerUseCurrentArticleList> </Tool> <Plugin /> </AutoWikiBrowserPreferences>
Eseguire modifiche con AWB
[modifica]Per operare modifiche con AWB è necessario innanzitutto individuare un elenco di articoli da editare. Una volta fatto, AWB creerà una lista in un riquadro al lato sinistro della sua interfaccia e di volta in volta mostrerà il Diff di ogni modifica. Per iniziare ad operare con AWB clicca su Start (ultima linguetta del riquadro centrale) e poi ancora sul pulsante Start. AWB visualizzerà il testo con le modifiche che intende apportare e un riquadro con diverse opzioni, comprese quelle di modifica manuale. Per non effettuare alcuna modifica premi Skip
, per salvarla fai clic su Save
.
- Attenzione: AWB potrebbe apportare modifiche diverse da quelle attese, in quanto si basa su espressioni regolari, e spetta a voi per rivedere le modifiche proposte e correggere eventuali errori prima di salvare. La responsabilità di ogni modifica è solo vostra.
Modifiche manuali possono essere effettuate modificando il contenuto della scheda "Edit". Una volta salvata una modifica questa apparirà nella cronologia della relativa pagina. In ogni caso, appena salvato o saltato un diff, AWB procederà con le successive pagine nella lista.
Creare la lista
[modifica]Vai nel riquadro "Source" e digitare il nome dell'articolo da modificare o una modalità di creazione della lista, quindi utilizza "Make list" per le diverse opzioni o per generare la lista pronta all'utilizzo.
Mi sembra di aver capito, ma...
![]() | Se non riesci ad afferrare qualche concetto o non capisci il perché di tale procedura, ci metti cinque secondi a chiederlo e avere risposta. Se pensi invece di avere una proposta, piccola o grande che sia, siamo tutti pronti ad ascoltarti. |
L'elenco di tutte le pagine riguardanti Wikivoyage si trova nella pagina Aiuto:Aiuto. |