// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Invoked by the ProgressDialog OnShown callback private async Task Execute(UI.ProgressDialog progress, CancellationToken token) { logger.Start(); logger.StartClock(); using (var one = new OneNote()) { var hierarchy = await GetHierarchy(one); var ns = one.GetNamespace(hierarchy); var pageList = hierarchy.Descendants(ns + "Page") .Where(e => e.Attribute("isInRecycleBin") == null); var pageCount = pageList.Count(); progress.SetMaximum(pageCount); progress.SetMessage($"Scanning {pageCount} pages"); // OneNote likes to inject \n\r before the href attribute so match any spaces var editor = new Regex( $"(<a\\s+href=[^>]+{keys}[^>]+>)([^<]*)(</a>)", RegexOptions.Compiled | RegexOptions.Multiline); foreach (var item in pageList) { progress.Increment(); progress.SetMessage(item.Attribute("name").Value); var xml = one.GetPageXml(item.Attribute("ID").Value, OneNote.PageDetail.Basic); // initial string scan before instantiating entire XElement DOM if (xml.Contains(keys)) { var page = new Page(XElement.Parse(xml)); var blocks = page.Root.DescendantNodes().OfType <XCData>() .Where(n => n.Value.Contains(keys)) .ToList(); foreach (var block in blocks) { block.Value = editor.Replace(block.Value, $"$1{title}$3"); } await one.Update(page); updates++; } if (token.IsCancellationRequested) { logger.WriteLine("cancelled"); break; } } } logger.WriteTime("refresh complete"); logger.End(); }
private void ExportMany(OneNote one, List <string> pageIDs) { OneNote.ExportFormat format; string path; using (var dialog = new ExportDialog(pageIDs.Count)) { if (dialog.ShowDialog(owner) != DialogResult.OK) { return; } path = dialog.FolderPath; format = dialog.Format; } string ext = null; switch (format) { case OneNote.ExportFormat.HTML: ext = ".htm"; break; case OneNote.ExportFormat.PDF: ext = ".pdf"; break; case OneNote.ExportFormat.Word: ext = ".docx"; break; case OneNote.ExportFormat.XML: ext = ".xml"; break; case OneNote.ExportFormat.OneNote: ext = ".one"; break; } string formatName = format.ToString(); using (var progress = new UI.ProgressDialog()) { progress.SetMaximum(pageIDs.Count); progress.Show(owner); foreach (var pageID in pageIDs) { var page = one.GetPage(pageID, OneNote.PageDetail.BinaryData); var filename = Path.Combine(path, page.Title.Replace(' ', '_') + ext); progress.SetMessage(filename); progress.Increment(); if (format == OneNote.ExportFormat.XML) { SaveAsXML(page.Root, filename); } else { SaveAs(one, page.PageId, filename, format, formatName); } } } UIHelper.ShowMessage(string.Format(Resx.SaveAsMany_Success, pageIDs.Count, path)); }
public override async Task Execute(params object[] args) { logger.StartClock(); using (var one = new OneNote()) { var section = one.GetSection(); if (section != null) { var ns = one.GetNamespace(section); var pageIds = section.Elements(ns + "Page") .Select(e => e.Attribute("ID").Value) .ToList(); using (var progress = new UI.ProgressDialog()) { progress.SetMaximum(pageIds.Count); progress.Show(owner); foreach (var pageId in pageIds) { var page = one.GetPage(pageId, OneNote.PageDetail.Basic); var name = page.Root.Attribute("name").Value; progress.SetMessage(string.Format( Properties.Resources.RemovingPageNumber_Message, name)); progress.Increment(); if (string.IsNullOrEmpty(name)) { continue; } if (RemoveNumbering(name, out string clean)) { page.Root .Element(ns + "Title") .Element(ns + "OE") .Element(ns + "T") .GetCData().Value = clean; await one.Update(page); } } } } } logger.StopClock(); logger.WriteTime("removed page numbering"); }
private async Task DownloadSelectedSubpages( UI.ProgressDialog progress, CancellationToken token) { var updated = false; foreach (var selection in selections) { progress.SetMessage(selection.Address); //logger.WriteLine($"fetching {selection.Address}"); var page = await importer .ImportSubpage(one, parentPage, new Uri(selection.Address), token); if (page != null) { var pageUri = one.GetHyperlink(page.PageId, string.Empty); // redirect primary reference on parent page to our new subpage PatchCData(selection.CData, selection.Address, selection.Text, pageUri); // redirect duplicate references on parent page if (selection.RefCount > 1) { var ns = parentPage.Namespace; var regex = new Regex($@"<a\s+href=""{Regex.Escape(selection.Address)}"""); var cdatas = parentPage.Root.Elements(ns + "Outline") .DescendantNodes().OfType <XCData>() .Where(d => d != selection.CData && regex.IsMatch(d.Value)); foreach (var cdata in cdatas) { PatchCData(cdata, selection.Address, selection.Text, pageUri); } } updated = true; } progress.Increment(); } if (updated) { await one.Update(parentPage); await one.NavigateTo(parentPage.PageId); } }
private Dictionary <string, string> GetHyperlinks( UI.ProgressDialog progress, CancellationToken token) { var catalog = fullCatalog ? OneNote.Scope.Notebooks : scope; return(one.BuildHyperlinkCache(catalog, token, (count) => { progress.SetMaximum(count); progress.SetMessage($"Scanning {count} page references"); }, () => { progress.Increment(); })); }
private async Task CopyPages(XElement root, XElement clone, OneNote one, XNamespace ns) { var cloneID = clone.Attribute("ID").Value; foreach (var element in root.Elements(ns + "Page")) { // get the page to copy var page = one.GetPage(element.Attribute("ID").Value); progress.SetMessage(page.Title); // create a new page to get a new ID one.CreatePage(cloneID, out var newPageId); // set the page ID to the new page's ID page.Root.Attribute("ID").Value = newPageId; // remove all objectID values and let OneNote generate new IDs page.Root.Descendants().Attributes("objectID").Remove(); await one.Update(page); progress.Increment(); } // recurse... // NOTE that these find target sections by name, so the names must be unique otherwise // this will copy all pages into the first occurance with a matching name! foreach (var section in root.Elements(ns + "SectionGroup").Elements(ns + "Section")) { var cloneSection = clone.Elements(ns + "SectionGroup").Elements(ns + "Section") .FirstOrDefault(e => e.Attribute("name").Value == section.Attribute("name").Value); await CopyPages(section, cloneSection, one, ns); } foreach (var section in root.Elements(ns + "Section")) { var cloneSection = clone.Elements(ns + "Section") .FirstOrDefault(e => e.Attribute("name").Value == section.Attribute("name").Value); await CopyPages(section, cloneSection, one, ns); } }
private async Task <Dictionary <string, OneNote.HyperlinkInfo> > GetHyperlinks( UI.ProgressDialog progress, CancellationToken token) { var catalog = fullCatalog ? OneNote.Scope.Notebooks : scope; return(await one.BuildHyperlinkMap(catalog, token, async (count) => { progress.SetMaximum(count); progress.SetMessage($"Scanning {count} page references"); await Task.Yield(); }, async() => { progress.Increment(); await Task.Yield(); })); }
public async Task IndexPages(List <string> pageIds) { string indexId = null; using (var progress = new UI.ProgressDialog()) { progress.SetMaximum(pageIds.Count); progress.Show(owner); // create a new page to get a new ID one.CreatePage(sectionId, out indexId); var indexPage = one.GetPage(indexId); indexPage.Title = "Page Index"; var container = indexPage.EnsureContentContainer(); foreach (var pageId in pageIds) { // get the page to copy var page = one.GetPage(pageId); var ns = page.Namespace; progress.SetMessage(page.Title); progress.Increment(); var link = one.GetHyperlink(page.PageId, string.Empty); container.Add(new XElement(ns + "OE", new XElement(ns + "T", new XCData($"<a href=\"{link}\">{page.Title}</a>")) )); } await one.Update(indexPage); } // navigate after progress dialog is closed otherwise it will hang! if (indexId != null) { await one.NavigateTo(indexId); } }
public async Task BuildHyperlinkMap( OneNote.Scope scope, UI.ProgressDialog progress, CancellationToken token) { logger.WriteLine("building hyperlink map"); map = await one.BuildHyperlinkMap( scope, token, async (count) => { progress.SetMaximum(count); progress.SetMessage($"Scanning {count} page references"); await Task.Yield(); }, async() => { progress.Increment(); await Task.Yield(); }); }
public async Task CopyPages(List <string> pageIds) { string lastId = null; using (var progress = new UI.ProgressDialog()) { progress.SetMaximum(pageIds.Count); progress.Show(owner); foreach (var pageId in pageIds) { if (one.GetParent(pageId) == sectionId) { continue; } // get the page to copy var page = one.GetPage(pageId); progress.SetMessage(page.Title); // create a new page to get a new ID one.CreatePage(sectionId, out var newPageId); // set the page ID to the new page's ID page.Root.Attribute("ID").Value = newPageId; // remove all objectID values and let OneNote generate new IDs page.Root.Descendants().Attributes("objectID").Remove(); await one.Update(page); lastId = newPageId; progress.Increment(); } } // navigate after progress dialog is closed otherwise it will hang! if (lastId != null) { await one.NavigateTo(lastId); } }
private async Task Toggle(bool pageOnly, bool showTimestamps) { using (var one = new OneNote()) { if (pageOnly) { var page = one.GetPage(); await SetTimestampVisibility(one, page, showTimestamps); } else { var section = one.GetSection(); if (section != null) { var ns = one.GetNamespace(section); var pageIds = section.Elements(ns + "Page") .Select(e => e.Attribute("ID").Value) .ToList(); using (var progress = new UI.ProgressDialog()) { progress.SetMaximum(pageIds.Count); progress.Show(owner); foreach (var pageId in pageIds) { var page = one.GetPage(pageId, OneNote.PageDetail.Basic); var name = page.Root.Attribute("name").Value; progress.SetMessage(name); progress.Increment(); await SetTimestampVisibility(one, page, showTimestamps); } } } } } }
private async Task <int> ApplyNumbering( List <PageBasics> pages, int index, int level, bool numeric, string prefix) { int counter = 1; while (index < pages.Count && pages[index].Level == level) { var page = one.GetPage(pages[index].ID, OneNote.PageDetail.Basic); var cdata = page.Root.Element(ns + "Title") .Element(ns + "OE") .Element(ns + "T") .GetCData(); progress.SetMessage(string.Format(Properties.Resources.NumberingPage_Message, pages[index].Name)); progress.Increment(); var text = cdata.Value; if (cleaner != null) { cleaner.RemoveNumbering(cdata.Value, out text); } cdata.Value = BuildPrefix(counter, numeric, level, prefix) + " " + text; await one.Update(page); index++; counter++; if (index < pages.Count && pages[index].Level > level) { index = await ApplyNumbering( pages, index, pages[index].Level, numeric, $"{prefix}{counter - 1}."); } } return(index); }
private async Task Archive(UI.ProgressDialog progress, XElement root, string path) { foreach (var element in root.Elements()) { if (element.Name.LocalName == "Page") { var page = one.GetPage( element.Attribute("ID").Value, OneNote.PageDetail.BinaryData); progress.SetMessage($"Archiving {page.Title}"); progress.Increment(); await ArchivePage(element, page, path); } else { // SectionGroup or Section element.ReadAttributeValue("locked", out bool locked, false); if (locked) { continue; } element.ReadAttributeValue("isRecycleBin", out bool recycle, false); if (recycle) { continue; } // append name of Section/Group to path to build zip folder path var name = element.Attribute("name").Value; await Archive(progress, element, Path.Combine(path, name)); } } }
private void Export(List <string> pageIDs) { OneNote.ExportFormat format; string path; bool withAttachments; bool useUnderscores; // dialog... using (var dialog = new ExportDialog(pageIDs.Count)) { if (dialog.ShowDialog(owner) != DialogResult.OK) { return; } path = dialog.FolderPath; format = dialog.Format; withAttachments = dialog.WithAttachments; useUnderscores = dialog.UseUnderscores; } // prepare... string ext = null; switch (format) { case OneNote.ExportFormat.HTML: ext = ".htm"; break; case OneNote.ExportFormat.PDF: ext = ".pdf"; break; case OneNote.ExportFormat.Word: ext = ".docx"; break; case OneNote.ExportFormat.XML: ext = ".xml"; break; case OneNote.ExportFormat.Markdown: ext = ".md"; break; case OneNote.ExportFormat.OneNote: ext = ".one"; break; } // export... using (var progress = new UI.ProgressDialog()) { progress.SetMaximum(pageIDs.Count); progress.Show(owner); var archivist = new Archivist(one); foreach (var pageID in pageIDs) { var page = one.GetPage(pageID, OneNote.PageDetail.BinaryData); var title = useUnderscores ? PathFactory.CleanFileName(page.Title).Replace(' ', '_') : page.Title; var filename = Path.Combine(path, title + ext); progress.SetMessage(filename); progress.Increment(); if (format == OneNote.ExportFormat.HTML) { if (withAttachments) { archivist.ExportHTML(page, ref filename); } else { archivist.Export(page.PageId, filename, OneNote.ExportFormat.HTML); } } else if (format == OneNote.ExportFormat.XML) { archivist.ExportXML(page.Root, filename, withAttachments); } else if (format == OneNote.ExportFormat.Markdown) { archivist.ExportMarkdown(page, filename, withAttachments); } else { archivist.Export(page.PageId, filename, format, withAttachments); } } } SaveDefaultPath(path); UIHelper.ShowMessage(string.Format(Resx.SaveAsMany_Success, pageIDs.Count, path)); }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Invoked by the ProgressDialog OnShown callback private async Task Execute(UI.ProgressDialog progress, CancellationToken token) { logger.Start(); logger.StartClock(); using (one = new OneNote()) { if (page == null) { page = one.GetPage(); ns = page.Namespace; } PageNamespace.Set(ns); var title = Unstamp(page.Title); string startId = string.Empty; switch (scope) { case OneNote.Scope.Sections: startId = one.CurrentNotebookId; break; case OneNote.Scope.Pages: startId = one.CurrentSectionId; break; } logger.WriteLine($"searching for '{title}'"); var results = one.Search(startId, title, unindexed); if (token.IsCancellationRequested) { logger.WriteLine("cancelled"); return; } //logger.WriteLine(results); var referals = FlattenPages(results, page.PageId); var total = referals.Count(); if (total == 0) { UIHelper.ShowInfo(Resx.LinkReferencesCommand_noref); return; } // initialize search-and-replace editor... var whatText = $@"\b{SearchAndReplaceEditor.EscapeEscapes(title)}\b"; var pageLink = one.GetHyperlink(page.PageId, string.Empty); var withElement = new XElement("A", new XAttribute("href", pageLink), page.Title ); var editor = new SearchAndReplaceEditor(whatText, withElement, useRegex: true, caseSensitive: false ); // process pages... progress.SetMaximum(total); progress.SetMessage($"Linking for {total} pages"); var updates = 0; foreach (var referal in referals) { progress.Increment(); progress.SetMessage(referal.Attribute(NameAttr).Value); var refpage = one.GetPage(referal.Attribute("ID").Value, OneNote.PageDetail.Basic); logger.WriteLine($"searching for '{whatText}' on {refpage.Title}"); var count = editor.SearchAndReplace(refpage); if (count > 0) { await one.Update(refpage); referal.SetAttributeValue(LinkedAttr, "true"); referal.SetAttributeValue(SynopsisAttr, GetSynopsis(refpage)); updates++; } else { logger.WriteLine($"search not found on {referal.Attribute(NameAttr).Value}"); } if (token.IsCancellationRequested) { logger.WriteLine("cancelled"); break; } } if (updates > 0) { // even if cancellation is request, must update page with referals that were // modified, otherwise, there will be referal pages that link to this page // without this page referring back! AppendReferalBlock(page, referals); await one.Update(page); } } logger.WriteTime("linking complete"); logger.End(); }
public async Task MovePages(List <string> pageIds) { var sections = new Dictionary <string, XElement>(); var section = one.GetSection(sectionId); var ns = one.GetNamespace(section); var updated = false; using (var progress = new UI.ProgressDialog()) { progress.SetMaximum(pageIds.Count); progress.Show(owner); foreach (var pageId in pageIds) { // find the section that currently owns the page var parentId = one.GetParent(pageId); if (parentId == sectionId) { continue; } // load the owning section XElement parent; if (sections.ContainsKey(parentId)) { parent = sections[parentId]; } else { parent = one.GetSection(parentId); sections.Add(parentId, parent); } // get the Page reference within the owing section var element = parent.Elements(ns + "Page") .FirstOrDefault(e => e.Attribute("ID").Value == pageId); if (element != null) { progress.SetMessage(element.Attribute("name").Value); // remove page from current owner element.Remove(); // remove misc attributes; OneNote will recreate them element.Attributes() .Where(a => a.Name != "ID" && a.Name != "name") .Remove(); // add page to target section section.Add(element); updated = true; } progress.Increment(); } } // updated at least one if (updated) { // update each source section foreach (var s in sections.Values) { one.UpdateHierarchy(s); } sections.Clear(); // update target section one.UpdateHierarchy(section); // navigate after progress dialog is closed otherwise it will hang! await one.NavigateTo(sectionId); } }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Invoked by the ProgressDialog OnShown callback private async Task Execute(UI.ProgressDialog progress, CancellationToken token) { logger.Start(); logger.StartClock(); using (one = new OneNote()) { var hierarchy = GetHierarchy(); if (token.IsCancellationRequested) { logger.WriteLine("cancelled"); return; } try { var hyperlinks = await GetHyperlinks(progress, token); if (token.IsCancellationRequested) { logger.WriteLine("cancelled"); return; } var elements = hierarchy.Descendants(ns + "Page").ToList(); var titles = new Dictionary <string, string>(); logger.WriteLine($"building map for {elements.Count} pages"); progress.SetMaximum(elements.Count); progress.SetMessage($"Building map for {elements.Count} pages"); foreach (var element in elements) { progress.Increment(); if (token.IsCancellationRequested) { return; } var parentId = element.Attribute("ID").Value; var xml = one.GetPageXml(parentId); var matches = regex.Matches(xml); if (matches.Count == 0) { element.Remove(); continue; } var parent = new Page(XElement.Parse(xml)); var name = element.Parent.Attribute("name").Value; progress.SetMessage($"Scanning {name}/{parent.Title}"); // prevent duplicates var refs = new List <string>(); foreach (Match match in matches) { var pid = match.Groups[1].Value; if (refs.Contains(pid)) { // already captured this pid continue; } if (!hyperlinks.ContainsKey(pid)) { logger.WriteLine($"not found in scope: {pid} on {name}/{parent.Title}"); continue; } var hyperlink = hyperlinks[pid]; if (hyperlink.PageID != parentId) { string title; if (titles.ContainsKey(hyperlink.PageID)) { title = titles[hyperlink.PageID]; } else { var p = one.GetPage(hyperlink.PageID, OneNote.PageDetail.Basic); title = p.Title; titles.Add(hyperlink.PageID, title); } element.Add(new XElement("Ref", new XAttribute("title", title), new XAttribute("ID", hyperlink.PageID) )); //logger.WriteLine($" - {title}"); refs.Add(pid); } } } if (titles.Count == 0) { UIHelper.ShowMessage("No linked pages were found"); return; } if (token.IsCancellationRequested) { return; } Prune(hierarchy); await BuildMapPage(hierarchy); } catch (Exception exc) { logger.WriteLine(exc); } } logger.WriteTime("map complete"); logger.End(); }
private void ReportNotebooks(XElement container, XElement notebooks) { progress.SetMessage("Notebooks..."); progress.Increment(); var backupUri = new Uri(backupPath).AbsoluteUri; var folderUri = new Uri(defaultPath).AbsoluteUri; container.Add( new Paragraph("Summary").SetQuickStyle(heading1Index), new Paragraph(Resx.AnalyzeCommand_SummarySummary), new Paragraph(new ContentList(ns, new Bullet($"<span style='font-style:italic'>Default location</span>: <a href=\"{folderUri}\">{defaultPath}</a>"), new Bullet($"<span style='font-style:italic'>Backup location</span>: <a href=\"{backupUri}\">{backupPath}</a>") )), new Paragraph(string.Empty) ); var table = new Table(ns, 1, 4) { HasHeaderRow = true, BordersVisible = true }; table.SetColumnWidth(0, 120); table.SetColumnWidth(1, 70); table.SetColumnWidth(2, 70); table.SetColumnWidth(3, 70); var row = table[0]; row.SetShading(HeaderShading); row[0].SetContent(new Paragraph("Notebook").SetStyle(HeaderCss)); row[1].SetContent(new Paragraph("Backups").SetStyle(HeaderCss).SetAlignment("center")); row[2].SetContent(new Paragraph("RecycleBin").SetStyle(HeaderCss).SetAlignment("center")); row[3].SetContent(new Paragraph("Total").SetStyle(HeaderCss).SetAlignment("center")); long total = 0; foreach (var notebook in notebooks.Elements(ns + "Notebook")) { row = table.AddRow(); var name = notebook.Attribute("name").Value; var remote = notebook.Attribute("path").Value.Contains("https://"); row[0].SetContent(remote ? $"{name} {Cloud}" : name); var path = Path.Combine(remote ? backupPath : defaultPath, name); if (Directory.Exists(path)) { var dir = new DirectoryInfo(path); var size = dir.EnumerateFiles("*.*", SearchOption.AllDirectories).Sum(f => f.Length); var repath = Path.Combine(path, RecycleBin); if (Directory.Exists(repath)) { dir = new DirectoryInfo(repath); var relength = dir.EnumerateFiles("*.*", SearchOption.AllDirectories).Sum(f => f.Length); row[1].SetContent(new Paragraph((size - relength).ToBytes(1)).SetAlignment("right")); row[2].SetContent(new Paragraph(relength.ToBytes(1)).SetAlignment("right")); row[3].SetContent(new Paragraph(size.ToBytes(1)).SetAlignment("right")); } total += size; } } if (total > 0) { row = table.AddRow(); row[3].SetContent(new Paragraph(total.ToBytes(1)).SetAlignment("right")); } container.Add( new Paragraph(table.Root), new Paragraph(string.Empty) ); }