private BlogEditingTemplate ParseBlogPostIntoTemplate(BlogPostRegionLocatorStrategy regionLocator, IProgressHost progress, string postUrl) { progress.UpdateProgress(Res.Get(StringId.ProgressCreatingEditingTemplate)); BlogPostRegions regions = regionLocator.LocateRegionsOnUIThread(progress, postUrl); IHTMLElement primaryTitleRegion = GetPrimaryEditableTitleElement(regions.BodyRegion, regions.Document, regions.TitleRegions); // IF // - primaryTitleRegion is not null (title found) // - BodyRegion is null (no post body found) // - AND primaryTitleRegion is a link if (primaryTitleRegion != null && regions.BodyRegion == null && primaryTitleRegion.tagName.ToLower() == "a") { // Title region was detected, but body region was not. // It is possible that only titles are shown on the homepage // Try requesting the post itself, and loading regions from the post itself // HACK Somewhere the 'about:' protocol replaces http/https, replace it again with the correct protocol var pathMatch = new Regex("^about:(.*)$").Match((primaryTitleRegion as IHTMLAnchorElement).href); Debug.Assert(pathMatch.Success); // Assert that this URL is to the format we expect var newPostPath = pathMatch.Groups[1].Value; // Grab the path from the URL var homepageUri = new Uri(_blogHomepageUrl); var newPostUrl = $"{homepageUri.Scheme}://{homepageUri.Host}{newPostPath}"; // Recreate the full post URL // Set the NextTryPostUrl flag in the region locater // This will indicate to the other thread that another page should be parsed _nextTryPostUrl = newPostUrl; return(null); } BlogEditingTemplate template = GenerateBlogTemplate((IHTMLDocument3)regions.Document, primaryTitleRegion, regions.TitleRegions, regions.BodyRegion); progress.UpdateProgress(100, 100); return(template); }
public BlogEditingTemplateDetector(IBlogClientUIContext uiContext, Control parentControl, IBlogSettingsAccessor blogSettings, bool probeForManifest) : this(uiContext, parentControl) { BlogAccount blogAccount = new BlogAccount(blogSettings.ServiceName, blogSettings.ClientType, blogSettings.PostApiUrl, blogSettings.HostBlogId); string blogTemplateDir = BlogEditingTemplate.GetBlogTemplateDir(blogSettings.Id); SetContext(blogAccount, blogSettings.Credentials, blogSettings.HomepageUrl, blogTemplateDir, blogSettings.ManifestDownloadInfo, probeForManifest, blogSettings.ProviderId, blogSettings.OptionOverrides, blogSettings.UserOptionOverrides, blogSettings.HomePageOverrides); }
private BlogEditingTemplate ParseBlogPostIntoTemplate(BlogPostRegionLocatorStrategy regionLocator, IProgressHost progress) { progress.UpdateProgress(Res.Get(StringId.ProgressCreatingEditingTemplate)); BlogPostRegions regions = regionLocator.LocateRegionsOnUIThread(progress); IHTMLElement primaryTitleRegion = GetPrimaryEditableTitleElement(regions.BodyRegion, regions.Document, regions.TitleRegions); BlogEditingTemplate template = GenerateBlogTemplate((IHTMLDocument3)regions.Document, primaryTitleRegion, regions.TitleRegions, regions.BodyRegion); progress.UpdateProgress(100, 100); return(template); }
/// <summary> /// Parses a webpage into an editing template using a marshalled callback on the UI context's thread. /// </summary> /// <param name="uiContext"></param> /// <param name="progress"></param> /// <returns></returns> private string ParseWebpageIntoEditingTemplate_OnUIThread(Control uiContext, BlogPostRegionLocatorStrategy regionLocator, IProgressHost progress, string postUrl) { BlogEditingTemplate blogEditingTemplate = (BlogEditingTemplate)uiContext.Invoke( new TemplateParser(ParseBlogPostIntoTemplate), new object[] { regionLocator, new ProgressTick(progress, 1, 100), postUrl }); return(blogEditingTemplate?.Template); }
private void DetectWeblogSettingsCompleted(object result) { // no-op if we don't have a blog detected if (HostBlogId == String.Empty) { return; } // get the editing template directory string blogTemplateDir = BlogEditingTemplate.GetBlogTemplateDir(_localBlogId); // set context for template detector BlogAccount blogAccount = new BlogAccount(ServiceName, ClientType, PostApiUrl, HostBlogId); _blogEditingTemplateDetector.SetContext(blogAccount, _credentials, _homepageUrl, blogTemplateDir, _manifestDownloadInfo, false, _providerId, _optionOverrides, null, _homePageOverrides); }
public void LoadHtmlFragment(string title, string postBodyHtml, string baseUrl, BlogEditingTemplate editingTemplate) { const int SPACE_BETWEEN_TITLE_AND_BODY = 4; if (editingTemplate.ContainsTitle) { // Make sure the title textbox is showing if there is a title. textBoxTitle.Visible = true; panelSourceEditor.Top = textBoxTitle.Bottom + SPACE_BETWEEN_TITLE_AND_BODY; panelSourceEditor.Height = Height - panelSourceEditor.Top; textBoxTitle.Text = title; } else { // We need to hide the title textbox if there is no title. textBoxTitle.Visible = false; panelSourceEditor.Top = textBoxTitle.Top; panelSourceEditor.Height = Height - panelSourceEditor.Top; } //make the post body HTML look pretty postBodyHtml = ApplyPostBodyFormatting(postBodyHtml); sourceControl.LoadHtmlFragment(postBodyHtml); sourceControl.Focus(); }
private BlogEditingTemplateFiles SafeGetTemplates(IProgressHost progress) { WriterEditingManifest editingManifest = null; BlogEditingTemplateFiles templateFiles = new BlogEditingTemplateFiles(); try { // if we have a manifest url then try to get our manifest if (_manifestDownloadInfo != null) { // try to get the editing manifest string manifestUrl = _manifestDownloadInfo.SourceUrl; editingManifest = WriterEditingManifest.FromUrl( new Uri(manifestUrl), _blogClient, _credentials, true); // progress CheckCancelRequested(progress); progress.UpdateProgress(20, 100); } // if we have no editing manifest then probe (if allowed) if ((editingManifest == null) && _probeForManifest) { editingManifest = WriterEditingManifest.FromHomepage( new LazyHomepageDownloader(_blogHomepageUrl, new HttpRequestHandler(_blogClient.SendAuthenticatedHttpRequest)), new Uri(_blogHomepageUrl), _blogClient, _credentials); } // progress CheckCancelRequested(progress); progress.UpdateProgress(40, 100); // if we got one then return templates from it as-appropriate if (editingManifest != null) { if (editingManifest.WebLayoutUrl != null) { string webLayoutTemplate = DownloadManifestTemplate(new ProgressTick(progress, 10, 100), editingManifest.WebLayoutUrl); if (BlogEditingTemplate.ValidateTemplate(webLayoutTemplate)) { // download supporting files string templateFile = DownloadTemplateFiles(webLayoutTemplate, _blogHomepageUrl, new ProgressTick(progress, 20, 100)); // return the template templateFiles.FramedTemplate = new BlogEditingTemplateFile(BlogEditingTemplateType.Framed, templateFile); } else { Trace.WriteLine("Invalid webLayoutTemplate specified in manifest"); } } if (editingManifest.WebPreviewUrl != null) { string webPreviewTemplate = DownloadManifestTemplate(new ProgressTick(progress, 10, 100), editingManifest.WebPreviewUrl); if (BlogEditingTemplate.ValidateTemplate(webPreviewTemplate)) { // download supporting files string templateFile = DownloadTemplateFiles(webPreviewTemplate, _blogHomepageUrl, new ProgressTick(progress, 20, 100)); // return the template templateFiles.WebPageTemplate = new BlogEditingTemplateFile(BlogEditingTemplateType.Webpage, templateFile); } else { Trace.WriteLine("Invalid webPreviewTemplate specified in manifest"); } } } } catch { } finally { progress.UpdateProgress(100, 100); } return(templateFiles); }
public void LoadHtmlFragment(string title, string blogPostBody, string baseUrl, BlogEditingTemplate editingTemplate) { _spellingManager.ClearIgnoreOnce(); _templateContainsTitle = editingTemplate.ContainsTitle; //if any manually attached behaviors are attached, remove them. //Note: this is necessary to prevent errors from occuring when switching between wysiwyg and code view //to quickly. DetachBehaviors(); // Deterministically dispose any automatically created behaviors. _elementBehaviorManager.DisposeCreatedBehaviors(); if (TidyWhitespace && Editable) { blogPostBody = HTMLTrimmer.Trim(blogPostBody, true); if (blogPostBody != String.Empty) blogPostBody += CONTENT_BODY_PADDING; } // SInce this action is reverted in the deattach of the behvaiors, we only do this in edit mode, // otherwie there is no deattach to balance it out. See that AttachBehaviors() doesnt attach in edit mode if (Editable) { //attach the extended entry HTML behavior blogPostBody = PostBodyEditingElementBehavior.ApplyExtendedEntryBehavior(blogPostBody); } //Hack: cache the title and body HTML to avoid returning a bogus value //GetEdited[Html|TitleHtml] is called before the document behaviors are attached. _lastSetTitle = title; _lastSetBodyHtml = blogPostBody; preserver.Reset(); blogPostBody = preserver.ScanAndPreserve(blogPostBody); // update html content with standard header and footer // Hack: put some padding at the bottom of the div so that the bottom line of text does not get // cutoff if it extends below the baseline (p's and g's sometimes cause issues) //put an ID'd span around the title so that editing behaviors can be attachd to it. //Note: use a span instead of a DIV as since DIVs can't be nested inside inline elements, so if //the title text was surrounded by inline tags (like font, or bold, etc) then the DIV would //break the rendering of the surrounding inline styles. string titleHtml = _strategy.OnTitleInserted(title); if (blogPostBody == String.Empty && TidyWhitespace) blogPostBody = "<p> </p>"; blogPostBody = _strategy.OnBodyInserted(blogPostBody); string postHtml = editingTemplate.ApplyTemplateToPostHtml(title, titleHtml, blogPostBody); //add the base tag for the HTML so relative resource references in the post will be resolved. postHtml = postHtml.Replace("</HEAD>", String.Format(CultureInfo.InvariantCulture, "<BASE href=\"{0}\"></HEAD>", baseUrl)); // save the content to a temp file for loading string documentPath = TempFileManager.Instance.CreateTempFile("index.htm"); using (StreamWriter streamWriter = new StreamWriter(documentPath, false, Encoding.UTF8)) streamWriter.Write(postHtml); // load the document base.LoadHtmlFile(documentPath); }
public void SetTheme(string wysiwygHTML, string previewHTML, bool containsTitle) { if (string.IsNullOrEmpty(wysiwygHTML)) throw new ArgumentException("wysiwygHTML cannot be a null or empty"); Debug.Assert(wysiwygHTML.ToLower(CultureInfo.InvariantCulture).Contains("<head"), "wysiwygHTML does not contain head element"); Debug.Assert(wysiwygHTML.ToLower(CultureInfo.InvariantCulture).Contains("<body"), "wysiwygHTML does not contain body element"); BeforeSetTheme(ref wysiwygHTML, ref previewHTML, containsTitle); //transform the template HTML into the form required by the HTML editor string wysiwygTemplateWithBehaviors = CreateTemplateWithBehaviors(wysiwygHTML, _normalHtmlContentEditor.BehaviorManager); _editingTemplateWysiwyg = new BlogEditingTemplate(wysiwygTemplateWithBehaviors, containsTitle); if (!string.IsNullOrEmpty(previewHTML)) { Debug.Assert(previewHTML.ToLower(CultureInfo.InvariantCulture).Contains("<head"), "previewHTML does not contain head element"); Debug.Assert(previewHTML.ToLower(CultureInfo.InvariantCulture).Contains("<body"), "previewHTML does not contain body element"); string previewTemplateWithBehaviors = CreateTemplateWithBehaviors(previewHTML, new NullElementBehaviorManager()); _editingTemplatePreview = new BlogEditingTemplate(previewTemplateWithBehaviors, containsTitle); } ReloadEditor(); }
private BlogEditingTemplate GetSurroundingContent() { // surrounding content based on standard header and footer if (_editingTemplateWysiwyg == null) { throw new Exception("SetTheme was not called before the editor was loaded"); } BlogEditingTemplate template = null; switch (CurrentEditingMode) { case EditingMode.Wysiwyg: template = _editingTemplateWysiwyg; break; case EditingMode.Preview: template = _editingTemplatePreview; break; case EditingMode.Source: template = new BlogEditingTemplate(_editingTemplateWysiwyg.ContainsTitle); break; case EditingMode.PlainText: template = EditingTemplatePlain; break; } if (template != null) return template; throw new Exception("Cannot find correct template for EditingMode: " + CurrentEditingMode); }