//Version 3.0: complete overhaul, script considers different output for placehoder citations and bibliography citations //Version 2.0: script can be attached to both date/time field element as well as text field element public IEnumerable <ITextUnit> GetTextUnits(ComponentPart componentPart, Template template, Citation citation, out bool handled) { //enter the culture the date info has been formatted and entered in, e.g. 12/05/2017 would be December, 12th in en-UK and May, 5th in en-US CultureInfo targetCulture = CultureInfo.CreateSpecificCulture("en-US"); //list all possible date formats for this script to check; the scripts tries to parse the date beginning from left to right string[] formats = new string[] { "yyyy-MM-dd", "yyyy/MM/dd", "dd/MM/yyyy", "yyyy/dd/MM", "dd.MM.yyyy", "d.M.yyyy", "d.MM.yyyy", "dd.M.yyyy", "dd.MM.yy", "d.M.yy", "d.MM.yy", "dd.M.yy" }; bool usePeriodAfterAbbreviatedMonthName = true; //if true, month names will be: Jan. Feb. Mar. Apr. May (!) Jun. Jul. Aug. Sept. Oct. Nov. Dec. ///IMPORTANT: Use the following indexed placeholders {n} and format strings xxxx as in {n:xxxx} for the templates. ///You can ommit placeholders and/or place them freely inside the templates below. Yet, it is not recommended to use the same placeholder more than once, ///because this script is not optimized for this. /// ///{0}: letter for ambiguity resolving ///{1}: year of start or single date ///{2}: month of start or single date ///{3}: day of start or single date ///{4}: year of end date ///{5}: month of end date ///{6}: day of end date ///use the following formatting for "6 June 2018" ///YEAR: yyyy = 2018, yy = 18 ///MONTH: MMMM = June, MMM = Jun, MM = 06, %M = 6 ///DAY: dd = 06, %d = 6, %do = 6th //SINGLE DATE - output format templates string outputFormatSingleDatePlaceholder = "{1:yyyy}{0}"; //e.g. 2013a string outputFormatSingleDateBibliography = "{1:yyyy}{0}, {2:MMMM} {3:%do}"; //e.g. 2013a, January 6th //DATE RANGE - output format templates //same year, same month string outputFormatDateRangeSameYearSameMonthPlaceholder = "{1:yyyy}{0}"; //e.g. 2013a string outputFormatDateRangeSameYearSameMonthBibliography = "{1:yyyy}{0}, {2:MMMM} {3:%do} - {6:%do}"; //e.g. 2013a, January 6th - 9th //same year, different month string outputFormatDateRangeSameYearDifferentMonthPlaceholder = "{1:yyyy}{0}"; //e.g. 2013a string outputFormatDateRangeSameYearDifferentMonthBibliography = "{1:yyyy}{0}, {2:MMMM} {3:%do} - {5:MMMM} {6:%do}"; //e.g. 2013a, September 28th - October 3rd //different years string outputFormatDateRangeDifferentYearsPlaceholder = "{1:yyyy}/{4:yyyy}{0}"; //e.g. 2013/2014a string outputFormatDateRangeDifferentYearsBibliography = "{1:yyyy}/{4:yyyy}{0}; {1:yyyy}, {2:MMMM} {3:%do} - {4:yyyy}, {5:MMMM} {6:%do}"; //e.g. 2013/2014a; 2013, December 29th - 2014, January 4th handled = false; if (citation == null) { return(null); } Reference referenceInScope = GetReferenceInScope(componentPart, citation); if (referenceInScope == null) { return(null); } FieldElement dateFieldElement = GetDateFieldElement(componentPart); if (dateFieldElement == null) { return(null); } ReferencePropertyId referencePropertyId = dateFieldElement.PropertyId; string dateString = referenceInScope.GetValue(referencePropertyId) as string; if (string.IsNullOrEmpty(dateString)) { return(null); } TextUnitCollection output = null; PlaceholderCitation placeholderCitation = citation as PlaceholderCitation; bool isPlaceholderCitation = placeholderCitation != null; PreviewCitation previewCitation = citation as PreviewCitation; bool isPreviewBibliographyCitation = previewCitation != null && citation.CitationType == CitationType.Bibliography; BibliographyCitation bibliographyCitation = citation as BibliographyCitation; bool isBibliographyCitation = bibliographyCitation != null; if (bibliographyCitation == null && placeholderCitation != null) { bibliographyCitation = placeholderCitation.CorrespondingBibliographyCitation; } if (bibliographyCitation == null && !isPreviewBibliographyCitation) { return(null); } string identifyingLetter = bibliographyCitation != null ? bibliographyCitation.IdentifyingLetter : string.Empty; LiteralTextUnit identifyingLetterTextUnit = new LiteralTextUnit(identifyingLetter, Drawing.FontStyle.Neutral); bool hasIdentifyingLetter = !string.IsNullOrEmpty(identifyingLetter); #region Tread n.d. + letter for disambiguation ("IdentifyingLetter") if (hasIdentifyingLetter && ContainsND(dateString)) { //we make sure the IdentifyingLetter is separated from n.d. by a space char or hyphen: Smith n.d.-a, Smith n.d.-b //go to method SeparateIdentifyingLetterFromND below to customize output = componentPart.GetTextUnitsUnfiltered(citation, template); if (output == null || !output.Any()) { return(null); } handled = true; return(SeparateIdentifyingLetterFromND(output, identifyingLetter)); } #endregion FontStyle fontStyle = dateFieldElement is DateTimeFieldElement ? ((DateTimeFieldElement)dateFieldElement).FontStyle : ((TextFieldElement)dateFieldElement).FontStyle; DateTime dateSingle; DateTime dateStart; DateTime dateEnd; string outputText = string.Empty; #region Check for Single Date if (TryParseSingleDate(dateString, formats, targetCulture, out dateSingle)) { #region BibliographyCitation if (isBibliographyCitation || isPreviewBibliographyCitation) { outputText = FormatDate(dateSingle, outputFormatSingleDateBibliography, targetCulture, identifyingLetter, usePeriodAfterAbbreviatedMonthName); } #endregion #region PlaceholderCitation else if (isPlaceholderCitation) { outputText = FormatDate(dateSingle, outputFormatSingleDatePlaceholder, targetCulture, identifyingLetter, usePeriodAfterAbbreviatedMonthName); } #endregion #region Other else { handled = false; return(null); } #endregion } #endregion #region Check for Date Range else if (TryParseDateRange(dateString, formats, targetCulture, out dateStart, out dateEnd)) { #region BibliographyCitation if (isBibliographyCitation || isPreviewBibliographyCitation) { #region same year, same month if (dateStart.Year == dateEnd.Year && dateStart.Month == dateEnd.Month && dateStart.Day != dateEnd.Day) { outputText = FormatDateRange(dateStart, dateEnd, outputFormatDateRangeSameYearSameMonthBibliography, targetCulture, identifyingLetter, usePeriodAfterAbbreviatedMonthName); } #endregion #region same year, different months else if (dateStart.Year == dateEnd.Year && dateStart.Month != dateEnd.Month) { outputText = FormatDateRange(dateStart, dateEnd, outputFormatDateRangeSameYearDifferentMonthBibliography, targetCulture, identifyingLetter, usePeriodAfterAbbreviatedMonthName); } #endregion #region different years else { outputText = FormatDateRange(dateStart, dateEnd, outputFormatDateRangeDifferentYearsBibliography, targetCulture, identifyingLetter, usePeriodAfterAbbreviatedMonthName); } #endregion } #endregion #region PlaceholderCitation else if (isPlaceholderCitation) { #region same year, same month if (dateStart.Year == dateEnd.Year && dateStart.Month == dateEnd.Month && dateStart.Day != dateEnd.Day) { outputText = FormatDateRange(dateStart, dateEnd, outputFormatDateRangeSameYearSameMonthPlaceholder, targetCulture, identifyingLetter, usePeriodAfterAbbreviatedMonthName); } #endregion #region same year, different months else if (dateStart.Year == dateEnd.Year && dateStart.Month != dateEnd.Month) { outputText = FormatDateRange(dateStart, dateEnd, outputFormatDateRangeSameYearDifferentMonthPlaceholder, targetCulture, identifyingLetter, usePeriodAfterAbbreviatedMonthName); } #endregion #region different years else { outputText = FormatDateRange(dateStart, dateEnd, outputFormatDateRangeDifferentYearsPlaceholder, targetCulture, identifyingLetter, usePeriodAfterAbbreviatedMonthName); } #endregion } #endregion #region Other else { handled = false; return(null); } #endregion } #endregion #region Do the output if (!string.IsNullOrEmpty(outputText)) { var outputTextUnits = new TextUnitCollection(); outputTextUnits = TextUnitCollectionUtility.TaggedTextToTextUnits(dateFieldElement, outputText, fontStyle); if (outputTextUnits.Any()) { List <ITextUnit> componentPartOutput = new List <ITextUnit>(); foreach (IElement element in componentPart.Elements) { if (element == dateFieldElement) { componentPartOutput.AddRange(outputTextUnits); } else { componentPartOutput.AddRange(element.GetTextUnits(citation, template)); } } handled = true; return(componentPartOutput); } } #endregion handled = false; return(null); }
public IEnumerable <ITextUnit> GetTextUnits(ComponentPart componentPart, Template template, Citation citation, out bool handled) { handled = false; if (citation == null) { return(null); } Reference reference = citation.Reference; if (reference == null) { return(null); } if (componentPart == null) { return(null); } if (componentPart.Elements == null || !componentPart.Elements.Any() || componentPart.Elements.Count != 1) { return(null); } TextFieldElement firstTextFieldElement = componentPart.Elements.OfType <TextFieldElement>().FirstOrDefault() as TextFieldElement; if (firstTextFieldElement == null) { return(null); } ComponentPartScope scope = componentPart.Scope; Reference referenceInScope = null; if (scope == ComponentPartScope.Reference) { referenceInScope = reference; } else { referenceInScope = reference.ParentReference; } if (referenceInScope == null) { return(null); } ReferencePropertyId propertyTagged = ReferencePropertyId.None; switch (firstTextFieldElement.PropertyId) { case ReferencePropertyId.Title: { propertyTagged = ReferencePropertyId.TitleTagged; } break; case ReferencePropertyId.Subtitle: { propertyTagged = ReferencePropertyId.SubtitleTagged; } break; case ReferencePropertyId.TitleSupplement: { propertyTagged = ReferencePropertyId.TitleSupplementTagged; } break; } if (propertyTagged == ReferencePropertyId.None) { return(null); } string stringTagged = referenceInScope.GetValue(propertyTagged) as string; if (string.IsNullOrEmpty(stringTagged)) { return(null); } if (!HasTags(stringTagged)) { return(null); } bool italicFound = false; TextUnitCollection textUnitCollection = TextUnitCollectionUtility.TaggedTextToTextUnits(firstTextFieldElement, stringTagged); foreach (ITextUnit textUnit in textUnitCollection) { //Flip bits where required if (firstTextFieldElement.FontStyle.HasFlag(FontStyle.Italic)) { textUnit.TemporaryFontStyle ^= FontStyle.Italic; } if (firstTextFieldElement.FontStyle.HasFlag(FontStyle.Bold)) { textUnit.TemporaryFontStyle ^= FontStyle.Bold; } } handled = true; return(textUnitCollection); }
public IEnumerable <ITextUnit> GetTextUnits(ComponentPart componentPart, Template template, Citation citation, out bool handled) { //return handled = true if this macro generates the output (as an IEnumerable<ITextUnit>); the standard output will be suppressed //return handled = false if you want Citavi to produce the standard output; handled = false; if (citation == null) { return(null); } if (citation.Reference == null) { return(null); } if (componentPart == null) { return(null); } if (componentPart.Elements == null || componentPart.Elements.Count == 0) { return(null); } Reference referenceInScope = null; if (componentPart.Scope == ComponentPartScope.Reference) { referenceInScope = citation.Reference; } else if (componentPart.Scope == ComponentPartScope.ParentReference) { referenceInScope = citation.Reference.ParentReference; } if (referenceInScope == null) { return(null); } DateTimeFieldElement dateTimeFieldElement = componentPart.Elements.OfType <DateTimeFieldElement>().FirstOrDefault(); if (dateTimeFieldElement == null) { return(null); } var propertyId = dateTimeFieldElement.PropertyId; var dateTimeStringValue = referenceInScope.GetValue(propertyId) as string; if (string.IsNullOrEmpty(dateTimeStringValue)) { return(null); } DateTime dateValue; if (!DateTimeInformation.TryParse(dateTimeStringValue, out dateValue)) { return(null); } var formattedDate = string.Format(new MyCustomDateProvider(), "{0}", dateValue); if (string.IsNullOrEmpty(formattedDate)) { return(null); } var formattedDateTextUnits = TextUnitCollectionUtility.TaggedTextToTextUnits(null, formattedDate); if (formattedDateTextUnits == null || !formattedDateTextUnits.Any()) { return(null); } if (dateTimeFieldElement.FontStyle != FontStyle.Neutral) { foreach (ITextUnit textUnit in formattedDateTextUnits) { textUnit.FontStyle |= dateTimeFieldElement.FontStyle; } } List <LiteralElement> outputDateLiteralElements = formattedDateTextUnits.TextUnitsToLiteralElements(componentPart); componentPart.Elements.ReplaceItem(dateTimeFieldElement, outputDateLiteralElements); foreach (LiteralElement literalElement in componentPart.Elements.OfType <LiteralElement>()) { literalElement.ApplyCondition = ElementApplyCondition.Always; } return(null); }