Skip to content

Commit

Permalink
Toc refresh (#310)
Browse files Browse the repository at this point in the history
* toc refresh #309

* track indent levels

* bump 4.9.1
  • Loading branch information
stevencohn authored Oct 15, 2021
1 parent 1f5cb0d commit b0417eb
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 13 deletions.
2 changes: 1 addition & 1 deletion OneMore/Commands/References/BiLinkCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ private void NormalizeCData(XElement element)
*/
element.DescendantNodes().OfType<XCData>().ToList().ForEach(c =>
{
var doc = new Hap.HtmlDocument()
var doc = new Hap.HtmlDocument
{
GlobalAttributeValueQuote = Hap.AttributeValueQuote.SingleQuote
};
Expand Down
10 changes: 6 additions & 4 deletions OneMore/Commands/Snippets/InsertTocCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private async Task<bool> RefreshToc()
var parts = meta.Attribute("content").Value.Split(';');
var options = parts.Select(p => p.Split('=')).ToDictionary(s => s[0], s => s[1]);
var addTopLinks = options.ContainsKey("addTopLinks") && options["addTopLinks"] == "True";
var rightAlignTopLinks= options.ContainsKey("rightAlignTopLinks") && options["rightAlignTopLinks"] == "True";
var rightAlignTopLinks = options.ContainsKey("rightAlignTopLinks") && options["rightAlignTopLinks"] == "True";

// remove the containing OE so it can be regenerated
meta.Parent.Remove();
Expand Down Expand Up @@ -167,13 +167,13 @@ private async Task InsertHeadingsTable(Page page, bool addTopLinks, bool rightAl
};

// use the minimum intent level
var minlevel = headings.Min(e => e.Style.Index);
var minlevel = headings.Min(e => e.Level);

foreach (var heading in headings)
{
var text = new StringBuilder();
var count = minlevel;
while (count < heading.Style.Index)
while (count < heading.Level)
{
text.Append("\t");
count++;
Expand All @@ -189,9 +189,11 @@ private async Task InsertHeadingsTable(Page page, bool addTopLinks, bool rightAl
text.Append(heading.Text);
}

//text.Append($"(count:{count}=level:{heading.Level})");

toc.Add(new Paragraph(text.ToString()).SetStyle($"color:{textColor}"));

if (addTopLinks)
if (addTopLinks && !heading.HasTopLink)
{
if (rightAlignTopLinks)
{
Expand Down
6 changes: 6 additions & 0 deletions OneMore/Models/Heading.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ internal class Heading
public string Text;


/// <summary>
/// True if the header is followed by the [Top of page] link from TOC
/// </summary>
public bool HasTopLink;


/// <summary>
/// True if the header is an internal OneNote hyperlink to another page;
/// used by Split and Merge
Expand Down
72 changes: 64 additions & 8 deletions OneMore/Models/PageHeadings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace River.OneMoreAddIn.Models
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;
using Hap = HtmlAgilityPack;
using Resx = River.OneMoreAddIn.Properties.Resources;


internal partial class Page
Expand Down Expand Up @@ -41,8 +43,10 @@ public List<Heading> GetHeadings(OneNote one)

var blocks =
from e in Root.Elements(Namespace + "Outline").Descendants(Namespace + "OE")
// get the first non-empty CDATA
let c = e.Elements(Namespace + "T").DescendantNodes()
.FirstOrDefault(p => p.NodeType == XmlNodeType.CDATA) as XCData
.FirstOrDefault(p =>
p.NodeType == XmlNodeType.CDATA && (((XCData)p).Value.Length > 0)) as XCData
where c?.Value.Length > 0 && !Regex.IsMatch(c.Value, @"[\s\b]+<span[\s\b]+style=") &&
(e.Attribute("quickStyleIndex") != null || e.Attribute("style") != null)
select e;
Expand Down Expand Up @@ -81,6 +85,7 @@ from e in Root.Elements(Namespace + "Outline").Descendants(Namespace + "OE")
Style = style
};

CheckTopLink(heading);
headings.Add(heading);
}
}
Expand All @@ -102,6 +107,7 @@ from e in Root.Elements(Namespace + "Outline").Descendants(Namespace + "OE")
Style = style
};

CheckTopLink(heading);
headings.Add(heading);
}
}
Expand All @@ -111,7 +117,7 @@ from e in Root.Elements(Namespace + "Outline").Descendants(Namespace + "OE")
// style.Index is used for TOC indenting, regardless of heading level
ResetHeadingStyleIndexes();

// Level is used as the intended Heading level, e.g. Heading4 level is 4
// Level is used as the indented Heading level, e.g. Heading4 level is 4
foreach (var heading in headings)
{
heading.Level = heading.Style.Index;
Expand All @@ -135,6 +141,47 @@ private void GetPageColor()
}


private void CheckTopLink(Heading heading)
{
// quick test if it's a left-aligned [Top of page] link with square brackets
if (heading.Text.Contains('['))
{
// remove [Top of Page] link from text
var doc = new Hap.HtmlDocument();
doc.LoadHtml(heading.Text);
var text = doc.DocumentNode.InnerText;

var topmatch = Regex.Match(text, $@"\[?{Resx.InsertTocCommand_Top}\]?");
if (topmatch.Success)
{
heading.Text = text.Substring(0, topmatch.Index - 1);
heading.HasTopLink = true;
return;
}
}

// test if header has a right-aligned Top of page neighbor cell
var cell = heading.Root.Parent.Parent;

if (cell.Name.LocalName == "Cell" &&
cell.NextNode is XElement next && next.Name.LocalName == "Cell")
{
var cdata = next.DescendantNodes().OfType<XCData>().FirstOrDefault();
if (cdata != null)
{
var doc = new Hap.HtmlDocument();
doc.LoadHtml(cdata.Value);
var text = doc.DocumentNode.InnerText;

if (text == Resx.InsertTocCommand_Top)
{
heading.HasTopLink = true;
}
}
}
}


private string GetHyperlink(XElement element, OneNote one)
{
var attr = element.Attribute("objectID");
Expand Down Expand Up @@ -187,25 +234,34 @@ private Style FindCustomStyle(XElement block)
/// </summary>
private void ResetHeadingStyleIndexes()
{
quickStyles = quickStyles.Where(s => Regex.IsMatch(s.Name, @"h(\d+)")).ToList();
// internal names are h1..h6
quickStyles = quickStyles.Where(s => Regex.IsMatch(s.Name, @"^h\d$")).ToList();

foreach (var style in quickStyles)
{
var match = Regex.Match(style.Name, @"h(\d+)");
var match = Regex.Match(style.Name, @"^h(\d)$");
if (match.Success && match.Captures.Count > 0)
{
if (int.TryParse(match.Captures[0].Value, out var index))
{
style.Index = index;
style.Index = index - 1;
}
}
}

quickStyles = quickStyles.OrderBy(s => s.Index).ToList();
quickStyles = quickStyles.OrderBy(s => s.Name).ToList();

for (int i = 0; i < quickStyles.Count; i++)
string name = null;
for (int i = 0, j = 0; i < quickStyles.Count; i++)
{
quickStyles[i].Index = i;
// there are cases where OneNote will duplicate quick styles
if (quickStyles[i].Name != name)
{
name = quickStyles[i].Name;
j++;
}

quickStyles[i].Index = j;
}

for (int i = 0; i < customStyles.Count; i++)
Expand Down
Binary file modified OneMore/Properties/AssemblyInfo.cs
Binary file not shown.
Binary file modified OneMoreProtocolHandler/Properties/AssemblyInfo.cs
Binary file not shown.
Binary file modified OneMoreSetup/OneMoreSetup.vdproj
Binary file not shown.

0 comments on commit b0417eb

Please sign in to comment.