/// <summary> /// Answer the formatted text for a given topic, formatted using a given OutputFormat and possibly showing diffs with the previous revision /// </summary> /// <param name="topic">The topic</param> /// <param name="format">What format</param> /// <param name="showDiffs">true to show diffs</param> /// <param name="accumulator">composite cache rule in which to accumulate cache rules</param> /// <returns></returns> public static string FormattedTopic(AbsoluteTopicName topic, OutputFormat format, bool showDiffs, Federation aFederation, LinkMaker lm, CompositeCacheRule accumulator) { // Show the current topic (including diffs if there is a previous version) AbsoluteTopicName previousVersion = null; ContentBase relativeToBase = aFederation.ContentBaseForNamespace(topic.Namespace); if (showDiffs) previousVersion = relativeToBase.VersionPreviousTo(topic.LocalName); return FormattedTopicWithSpecificDiffs(topic, format, previousVersion, aFederation, lm, accumulator); }
/// <summary> /// Format a string of wiki content in a given OutputFormat with references all being relative to a given namespace /// </summary> /// <param name="input">The input wiki text</param> /// <param name="format">The desired output format</param> /// <param name="relativeToContentBase">References will be relative to this namespace</param> /// <param name="lm">Link maker (unless no relativeTo content base is provide)</param> /// <param name="accumulator">composite cache rule in which to accumulate cache rules</param> /// <returns></returns> public static string FormattedString(string input, OutputFormat format, ContentBase relativeToContentBase, LinkMaker lm, CompositeCacheRule accumulator) { // TODO -- some of the cases in which this call happens actually *are* nested, even though the false arg // below says that they aren't. This causes scripts to be emitted multiple times -- should clean up. WikiOutput output = WikiOutput.ForFormat(format, null); Hashtable ew; if (relativeToContentBase != null) ew = relativeToContentBase.ExternalWikiHash(); else ew = new Hashtable(); Format(null, input, output, relativeToContentBase, lm, ew, 0, accumulator); return output.ToString(); }
static public IWikiToPresentation WikiToPresentation(AbsoluteTopicName topic, WikiOutput output, ContentBase contentBase, LinkMaker maker, Hashtable external, int headingLevelBase, CompositeCacheRule accumulator) { ArrayList lines = new ArrayList(); lines.Add(new StyledLine("", LineStyle.Unchanged)); return new Formatter(topic, lines, output, contentBase, maker, external, headingLevelBase, accumulator); }
/// <summary> /// Format a given input string to the given output /// </summary> /// <param name="source">Input wiki content as a list of StyledLines</param> /// <param name="output">Output object to which output is sent</param> /// <param name="contentBase">The ContentBase that contains the wiki string text</param> /// <param name="maker">A link maker </param> /// <param name="external">External wiki map</param> /// <param name="headingLevelBase">Relative heading level</param> /// <param name="accumulator">composite cache rule in which to accumulate cache rules</param> /// static public void Format(AbsoluteTopicName topic, IList source, WikiOutput output, ContentBase contentBase, LinkMaker maker, Hashtable external, int headingLevelBase, CompositeCacheRule accumulator) { Formatter f = new Formatter(topic, source, output, contentBase, maker, external, headingLevelBase, accumulator); f.Format(); }
private IBELObject BorderPropertyFromTopic(AbsoluteTopicName relativeToTopic, AbsoluteTopicName abs, Border border, CompositeCacheRule rule) { ContentBase cb = ContentBaseForTopic(abs); if (cb == null) { return null; } rule.Add(cb.CacheRuleForAllPossibleInstancesOfTopic(abs)); if (!cb.TopicExists(abs)) { return null; } // OK, looks like the topic exist -- let's see if the property is there string borderPropertyName = BorderPropertyName(border); string prop = GetTopicProperty(abs, borderPropertyName); if (prop == null || prop == "") { return null; } // Yup, so evaluate it! string code = "federation.GetTopic(\"" + abs.Fullname + "\")." + borderPropertyName + "(federation.GetTopicInfo(\"" + relativeToTopic + "\"))"; BehaviorInterpreter interpreter = new BehaviorInterpreter(code, this, this.WikiTalkVersion, null); if (!interpreter.Parse()) { throw new Exception("Border property expression failed to parse."); } TopicContext topicContext = new TopicContext(this, this.ContentBaseForTopic(abs), new TopicInfo(this, abs)); IBELObject obj = interpreter.EvaluateToObject(topicContext, null); if (interpreter.ErrorString != null) { obj = new BELString(interpreter.ErrorString); } foreach (CacheRule r in interpreter.CacheRules) { rule.Add(r); } return obj; }
public string GetTopicFormattedContent(AbsoluteTopicName name, AbsoluteTopicName withDiffsToThisTopic) { string answer = null; if (CacheManager != null) { answer = (string)CacheManager.GetCachedTopicFormattedContent(name, withDiffsToThisTopic); } if (answer != null) { return answer; } CompositeCacheRule rule = new CompositeCacheRule(); // If the content is blacklisted and this is a historical version, answer dummy content if (name.Version != null && IsBlacklisted(GetTopicUnformattedContent(name))) { answer = Formatter.FormattedString(name, @"%red big%This historical version of this topic contains content that has been banned by policy from appearing on this site.", Format, this.ContentBaseForTopic(name), LinkMaker, rule); } else { answer = Formatter.FormattedTopic(name, Format, withDiffsToThisTopic, this, LinkMaker, rule); } if (CacheManager != null) { CacheManager.PutCachedTopicFormattedContent(name, withDiffsToThisTopic, answer, rule); } return answer; }
public string GetTopicFormattedBorder(AbsoluteTopicName name, Border border) { string answer = null; if (CacheManager != null) { answer = (string)CacheManager.GetCachedTopicFormattedBorder(name, border); } if (answer != null) { return answer; } // OK, we need to figure it out. CompositeCacheRule rule = new CompositeCacheRule(); IEnumerable borderText = BorderText(name, border, rule); WikiOutput output = new HTMLWikiOutput(null); foreach (IBELObject borderComponent in borderText) { IOutputSequence seq = borderComponent.ToOutputSequence(); // output sequence -> pure presentation tree IWikiToPresentation presenter = Formatter.WikiToPresentation(name, output, ContentBaseForTopic(name), LinkMaker, null, 0, rule); IPresentation pres = seq.ToPresentation(presenter); pres.OutputTo(output); } answer = output.ToString(); if (CacheManager != null) { CacheManager.PutCachedTopicFormattedBorder(name, border, answer, rule); } return answer; }
/// <summary> /// A list of TopicChanges to a topic since a given date [sorted by date] /// </summary> /// <param name="topic">A given date</param> /// <param name="stamp">A non-null timestamp; changes before this time won't be included in the answer </param> /// <param name="rule">A composite cache rule to fill with rules that represented accumulated dependencies (or null)</param> /// <returns>Enumeration of TopicChanges</returns> public override IEnumerable AllChangesForTopicSince(LocalTopicName topic, DateTime stamp, CompositeCacheRule rule) { ArrayList answer = new ArrayList(); SqlInfoForTopic[] infos = SqlHelper.GetSqlTopicInfosForTopicSince(Namespace, topic.Name, stamp, ConnectionString); ArrayList sortable = new ArrayList(); foreach (SqlInfoForTopic each in infos) sortable.Add(new SqlInfoTopicData(each, Namespace)); BackingTopic back = GetBackingTopicNamed(topic); bool sortAgain = false; if (back != null) { sortAgain = true; sortable.Add(new BackingTopicTopicData(back)); } if( sortAgain ) sortable.Sort(new TimeSort()); TopicsCacheRule tcr = null; if (rule != null) { tcr = new TopicsCacheRule(Federation); tcr.AddTopic(topic.AsAbsoluteTopicName(Namespace)); rule.Add(tcr); } foreach (TopicData each in sortable) { if (each.LastModificationTime < stamp) continue; AbsoluteTopicName name = topic.AsAbsoluteTopicName(Namespace); name.Version = each.Version; TopicChange change = TopicChangeFromName(name); answer.Add(change); if (tcr != null) tcr.AddTopic(name.AsAbsoluteTopicName(Namespace)); } return answer; }
/// <summary> /// Answer the formatted text for a given topic, formatted using a given OutputFormat and possibly showing diffs with the previous revision /// </summary> /// <param name="topic">The topic</param> /// <param name="format">What format</param> /// <param name="showDiffs">true to show diffs</param> /// <param name="accumulator">composite cache rule in which to accumulate cache rules</param> /// <returns></returns> public static string FormattedTopic(AbsoluteTopicName topic, OutputFormat format, AbsoluteTopicName previousVersion, Federation aFederation, LinkMaker lm, CompositeCacheRule accumulator) { ContentBase relativeToBase = aFederation.ContentBaseForNamespace(topic.Namespace); return FormattedTopicWithSpecificDiffs(topic, format, previousVersion, aFederation, lm, accumulator); }
/// <summary> /// A list of TopicChanges to a topic since a given date [sorted by date] /// </summary> /// <param name="topic">A given date</param> /// <param name="stamp">A non-null timestamp; changes before this time won't be included in the answer </param> /// <returns>Enumeration of TopicChanges</returns> override public IEnumerable AllChangesForTopicSince(LocalTopicName topic, DateTime stamp, CompositeCacheRule rule) { ArrayList answer = new ArrayList(); FileInfo[] infos = FileInfosForTopic(topic); ArrayList sortable = new ArrayList(); foreach (FileInfo each in infos) sortable.Add(new FileInfoTopicData(each, Namespace)); BackingTopic back = GetBackingTopicNamed(topic); if (back != null) sortable.Add(new BackingTopicTopicData(back)); sortable.Sort(new TimeSort()); TopicsCacheRule tcr = null; if (rule != null) { tcr = new TopicsCacheRule(Federation); tcr.AddTopic(topic.AsAbsoluteTopicName(Namespace)); rule.Add(tcr); } foreach (TopicData each in sortable) { if (each.LastModificationTime < stamp) continue; AbsoluteTopicName name = topic.AsAbsoluteTopicName(Namespace); name.Version = each.Version; TopicChange change = TopicChangeFromName(name); answer.Add(change); if (tcr != null) tcr.AddTopic(name.AsAbsoluteTopicName(Namespace)); } return answer; }
public IEnumerable AllChangesForTopic(LocalTopicName topic, CompositeCacheRule rule) { return AllChangesForTopicSince(topic, DateTime.MinValue, rule); }
/// <summary> /// A list of TopicChanges to a topic since a given date [sorted by date] /// </summary> /// <param name="topic">A given date</param> /// <param name="stamp">A non-null timestamp; changes before this time won't be included in the answer </param> /// <param name="rule">A composite cache rule to fill with rules that represented accumulated dependencies (or null)</param> /// <returns>Enumeration of TopicChanges</returns> public abstract IEnumerable AllChangesForTopicSince(LocalTopicName topic, DateTime stamp, CompositeCacheRule rule);
public CacheRule CacheRuleForAllPossibleInstancesOfTopic(TopicName aName) { TopicsCacheRule rule = new TopicsCacheRule(Federation); foreach (AbsoluteTopicName possible in aName.AllAbsoluteTopicNamesFor(this)) rule.AddTopic(possible); CompositeCacheRule answer = new CompositeCacheRule(); answer.Add(rule); answer.Add(CacheRuleForDefinition); // Add the cache rule for the content base, too, since if that changes there might be a change in imports return answer; }
/// <summary> /// Create a new formatter for a string of input content. /// </summary> /// <param name="source">Input wiki string</param> /// <param name="output">Output object to which output is sent</param> /// <param name="contentBase">The ContentBase that contains the wiki string text</param> /// <param name="maker">A link maker </param> /// <param name="external">External wiki map</param> /// <param name="headingLevelBase">Relative heading level</param> /// <param name="accumulator">composite cache rule in which to accumulate cache rules</param> /// Formatter(AbsoluteTopicName topic, string source, WikiOutput output, ContentBase contentBase, LinkMaker maker, Hashtable external, int headingLevelBase, CompositeCacheRule accumulator) { _Topic = topic; _Source = SplitStringIntoStyledLines(source, LineStyle.Unchanged); _LinkMaker = maker; ContentBase = contentBase; _Output = output; _ExternalWikiMap = external; _HeadingLevelBase = headingLevelBase; _CacheRuleAccumulator = accumulator; }
/// <summary> /// Answer a list of the wikitext components (IBELObjects) of the given border. If nothing specifies any border; answer the system default /// </summary> /// <param name="name"></param> /// <param name="border"></param> /// <param name="rule"></param> /// <returns></returns> private IEnumerable BorderText(AbsoluteTopicName name, Border border, CompositeCacheRule rule) { ArrayList answer = new ArrayList(); ContentBase cb; string bordersTopicsProperty = "Borders"; ArrayList borderTopics = new ArrayList(); // Start with whatever the namespace defines if (Borders != null) { foreach (string at in ParseListPropertyValue(Borders)) { AbsoluteTopicName abs = new AbsoluteTopicName(at); cb = ContentBaseForTopic(abs); if (abs == null || cb == null) { throw new Exception("Unknown namespace listed in border topic (" + at +") listed in federation configuration Borders property."); } borderTopics.Add(at); } } // If the namespace, specifies border topics, get them cb = ContentBaseForTopic(name); if (cb != null) { borderTopics.AddRange(GetTopicListPropertyValue(cb.DefinitionTopicName, bordersTopicsProperty)); rule.Add(cb.CacheRuleForAllPossibleInstancesOfTopic(cb.DefinitionTopicName)); } // If there are no border topics specified for the federation or the namespace, add the default (_NormalBorders from the local namespace) if (borderTopics.Count == 0) { borderTopics.Add("_NormalBorders"); } // Finally, any border elements form the topic itself (skip the def topic so we don't get double borders!) if (cb == null || cb.DefinitionTopicName.ToString() != name.ToString()) { borderTopics.AddRange(GetTopicListPropertyValue(name, bordersTopicsProperty)); } Set done = new Set(); foreach (string borderTopicName in borderTopics) { // Figure out what the absolute topic name is that we're going to get this topic from RelativeTopicName rel = new RelativeTopicName(borderTopicName); if (rel.Namespace == null) { rel.Namespace = name.Namespace; } AbsoluteTopicName abs = new AbsoluteTopicName(rel.Name, rel.Namespace); if (done.Contains(abs)) { continue; } done.Add(abs); IBELObject s = BorderPropertyFromTopic(name, abs, border, rule); if (s != null) { answer.Add(s); } } return answer; }
/// <summary> /// Create a new formatter for an input list of StyledLines /// </summary> /// <param name="source">Input wiki content as a list of StyledLines</param> /// <param name="output">Output object to which output is sent</param> /// <param name="contentBase">The ContentBase that contains the wiki string text</param> /// <param name="maker">A link maker </param> /// <param name="external">External wiki map</param> /// <param name="headingLevelBase">Relative heading level</param> /// <param name="accumulator">composite cache rule in which to accumulate cache rules</param> /// Formatter(AbsoluteTopicName topic, IList source, WikiOutput output, ContentBase contentBase, LinkMaker maker, Hashtable external, int headingLevelBase, CompositeCacheRule accumulator) { _Topic = topic; _Source = source; _Output = output; _LinkMaker = maker; ContentBase = contentBase; _ExternalWikiMap = external; _HeadingLevelBase = headingLevelBase; _CacheRuleAccumulator = accumulator; }
private CachedTopic GetCachedTopic(AbsoluteTopicName name) { CachedTopic answer = null; if (CacheManager != null) { answer = (CachedTopic)CacheManager.GetCachedTopic(name); } if (answer != null) { return answer; } ContentBase cb = ContentBaseForTopic(name); if (cb ==null || !cb.TopicExists(name)) { return null; } answer = new CachedTopic(name); CompositeCacheRule rule = new CompositeCacheRule(); rule.Add(cb.CacheRuleForAllPossibleInstancesOfTopic(name)); answer.Changes = cb.AllChangesForTopic(name.LocalName, rule); answer.CreationTime = cb.GetTopicCreationTime(name.LocalName); answer.LastModified = cb.GetTopicLastWriteTime(name.LocalName); answer.LastModifiedBy = cb.GetTopicLastAuthor(name.LocalName); answer.UnformattedContent = cb.Read(name.LocalName); answer.Properties = ContentBase.ExtractExplicitFieldsFromTopicBody(answer.UnformattedContent); AddImplicitPropertiesToHash(answer.Properties, name, answer.LastModifiedBy, answer.CreationTime, answer.LastModified, answer.UnformattedContent); if (CacheManager != null) { CacheManager.PutCachedTopic(name, answer, rule); } return answer; }
/// <summary> /// Answer the formatted text for a given topic, formatted using a given OutputFormat and possibly showing diffs /// with a specified revision /// </summary> /// <param name="topic">The topic</param> /// <param name="format">What format</param> /// <param name="showDiffs">true to show diffs</param> /// <param name="accumulator">composite cache rule in which to accumulate cache rules (ignored for diffs)</param> /// <returns></returns> public static string FormattedTopicWithSpecificDiffs(AbsoluteTopicName topic, OutputFormat format, AbsoluteTopicName diffWithThisVersion, Federation aFederation, LinkMaker lm, CompositeCacheRule accumulator) { // Setup a special link maker that knows what to make the edit links return to LinkMaker linker = lm.Clone(); linker.ReturnToTopicForEditLinks = topic; ContentBase relativeToBase = aFederation.ContentBaseForNamespace(topic.Namespace); if (accumulator != null) accumulator.Add(relativeToBase.CacheRuleForAllPossibleInstancesOfTopic(topic)); WikiOutput output = WikiOutput.ForFormat(format, null); if (diffWithThisVersion != null) { ArrayList styledLines = new ArrayList(); IList leftLines; IList rightLines; using (TextReader srLeft = relativeToBase.TextReaderForTopic(topic.LocalName)) { leftLines = MergeBehaviorLines(srLeft.ReadToEnd().Replace("\r", "").Split('\n')); } using (TextReader srRight = relativeToBase.TextReaderForTopic(diffWithThisVersion.LocalName)) { rightLines = MergeBehaviorLines(srRight.ReadToEnd().Replace("\r", "").Split('\n')); } IEnumerable diffs = Diff.Compare(leftLines, rightLines); foreach (LineData ld in diffs) { LineStyle style = LineStyle.Unchanged; switch (ld.Type) { case LineType.Common: style = LineStyle.Unchanged; break; case LineType.LeftOnly: style = LineStyle.Add; break; case LineType.RightOnly: style = LineStyle.Delete; break; } styledLines.Add(new StyledLine(ld.Text, style)); } Format(topic, styledLines, output, relativeToBase, linker, relativeToBase.ExternalWikiHash(), 0, accumulator); } else { using (TextReader sr = relativeToBase.TextReaderForTopic(topic.LocalName)) { Format(topic, sr.ReadToEnd(), output, relativeToBase, linker, relativeToBase.ExternalWikiHash(), 0, accumulator); } } return output.ToString(); }
/// <summary> /// A list of TopicChanges to a topic since a given date [sorted by date] /// </summary> /// <param name="topic">A given date</param> /// <param name="stamp">A non-null timestamp; changes before this time won't be included in the answer </param> /// <returns>Enumeration of TopicChanges</returns> public override System.Collections.IEnumerable AllChangesForTopicSince(LocalTopicName topic, DateTime stamp, CompositeCacheRule rule) { ArrayList answer = new ArrayList(); foreach (AbsoluteTopicName each in AllVersionsForTopic(topic)) { DateTime when = GetTopicLastWriteTime(topic); if (when >= stamp) answer.Add(new TopicChange(each, when, GetTopicLastAuthor(each.LocalName))); } return answer; }