/// <summary> /// Gets sense display string from entry, leaving traditional/simplified away for monolingual searches. /// </summary> private string getSense(int senseIx) { var cs = entry.GetSenseAt(senseIx); string res = ""; if (!cs.Domain.EqualsPlainText("CL:")) { string domain = CedictFormatter.HybridToHtml(cs.Domain, script); domain = CedictFormatter.StripPlainFromHtml(domain); res += domain; } if (cs.Equiv != HybridText.Empty) { if (res != string.Empty) { res += " "; } string equiv = CedictFormatter.HybridToHtml(cs.Equiv, script); equiv = CedictFormatter.StripPlainFromHtml(equiv); res += equiv; } if (cs.Note != HybridText.Empty) { if (res != string.Empty) { res += " "; } string note = CedictFormatter.HybridToHtml(cs.Note, script); note = CedictFormatter.StripPlainFromHtml(note); res += note; } return(res); }
public static void Write(CedictEntry entry, out string head, out string trg) { StringBuilder sbHead = new StringBuilder(); sbHead.Append(entry.ChTrad); sbHead.Append(' '); sbHead.Append(entry.ChSimpl); sbHead.Append(" ["); for (int i = 0; i != entry.PinyinCount; ++i) { if (i != 0) { sbHead.Append(' '); } sbHead.Append(entry.GetPinyinAt(i).GetDisplayString(false)); } sbHead.Append("]"); head = sbHead.ToString(); StringBuilder sbTrg = new StringBuilder(); sbTrg.Append('/'); for (int i = 0; i != entry.SenseCount; ++i) { string sense = entry.GetSenseAt(i).GetPlainText(); if (sense.Contains('/')) { sense = sense.Replace('/', '\\'); } sbTrg.Append(sense); sbTrg.Append('/'); } trg = sbTrg.ToString(); }
public static string Write(CedictEntry entry) { StringBuilder sb = new StringBuilder(); sb.Append(entry.ChTrad); sb.Append(' '); sb.Append(entry.ChSimpl); sb.Append(" ["); for (int i = 0; i != entry.PinyinCount; ++i) { if (i != 0) { sb.Append(' '); } sb.Append(entry.GetPinyinAt(i).GetDisplayString(false)); } sb.Append("] /"); for (int i = 0; i != entry.SenseCount; ++i) { string sense = entry.GetSenseAt(i).GetPlainText(); if (sense.Contains('/')) { sense = sense.Replace('/', '\\'); } sb.Append(sense); sb.Append('/'); } return(sb.ToString()); }
/// <summary> /// Returns true of display font covers all Hanzi in entry; false otherwise. /// </summary> private bool areHanziCovered(CedictEntry entry) { // Simplified and traditional headword if (!areHanziCovered(entry.ChSimpl, entry.ChTrad)) { return(false); } // Hanzi in hybrid text of senses for (int i = 0; i != entry.SenseCount; ++i) { CedictSense cs = entry.GetSenseAt(i); if (!areHanziCovered(cs.Domain)) { return(false); } if (!areHanziCovered(cs.Equiv)) { return(false); } if (!areHanziCovered(cs.Note)) { return(false); } } // We're good to go. return(true); }
private void renderAnnotation(HtmlTextWriter writer) { CedictEntry entry = prov.GetEntry(ann.EntryId); string entryClass = "entry"; if (tones == UiTones.Pleco) { entryClass += " toneColorsPleco"; } else if (tones == UiTones.Dummitt) { entryClass += " toneColorsDummitt"; } writer.AddAttribute(HtmlTextWriterAttribute.Class, entryClass); writer.RenderBeginTag(HtmlTextWriterTag.Div); // <div class="entry"> writer.AddAttribute(HtmlTextWriterAttribute.Class, "hw-ann"); writer.RenderBeginTag(HtmlTextWriterTag.Span); // <span class="hw-simp"> renderHanzi(query, entry, ann.StartInQuery, ann.LengthInQuery, writer); writer.RenderEndTag(); // <span class="hw-ann"> writer.AddAttribute(HtmlTextWriterAttribute.Class, "hw-pinyin"); writer.RenderBeginTag(HtmlTextWriterTag.Span); // <span class="hw-pinyin"> bool firstSyll = true; foreach (var pinyin in entry.Pinyin) { if (!firstSyll) { writer.WriteEncodedText(" "); } firstSyll = false; writer.WriteEncodedText(pinyin.GetDisplayString(true)); } writer.RenderEndTag(); // <span class="hw-pinyin"> writer.AddAttribute(HtmlTextWriterAttribute.Class, "senses"); writer.RenderBeginTag(HtmlTextWriterTag.Div); // <div class="senses"> for (int i = 0; i != entry.SenseCount; ++i) { renderSense(writer, entry.GetSenseAt(i), i, null); } writer.RenderEndTag(); // <div class="senses"> writer.RenderEndTag(); // <div class="entry"> }
private void renderResult(StringBuilder sb, string lang, bool renderEntryDiv, string extraSensesClass = "") { CedictEntry entry = entryToRender; if (entry == null) { entry = res.Entry; } Dictionary <int, CedictTargetHighlight> senseHLs = new Dictionary <int, CedictTargetHighlight>(); if (res != null) { foreach (CedictTargetHighlight hl in res.TargetHilites) { senseHLs[hl.SenseIx] = hl; } } string entryClass = "entry"; if (tones == UiTones.Pleco) { entryClass += " toneColorsPleco"; } else if (tones == UiTones.Dummitt) { entryClass += " toneColorsDummitt"; } if (extraEntryClass != "") { entryClass += " " + extraEntryClass; } if (renderEntryDiv) { sb.Append("<div class='" + entryClass + "'>"); // <div class="entry"> } if (entryId != null && lang != null) { sb.Append("<a class='ajax' href='/" + lang + "/edit/existing/" + entryId + "'>"); sb.Append("<i class='fa fa-pencil entryAction edit'></i></a>"); } XRenderStatus(sb); XRenderHanzi(sb); XRenderPinyin(sb); string sensesClass = "senses"; if (!string.IsNullOrEmpty(extraSensesClass)) { sensesClass += " " + extraSensesClass; } sb.Append("<div class='" + sensesClass + "'>"); // <div class="senses"> int senseIx = 0; for (int i = 0; i != entry.SenseCount; ++i) { CedictTargetHighlight thl = null; if (senseHLs.ContainsKey(i)) { thl = senseHLs[i]; } var sense = entry.GetSenseAt(i); if (isSpecialSense(sense)) { if (i != 0) { sb.Append("<br/>"); } } else if (i != 0) { if (isSpecialSense(entry.GetSenseAt(i - 1))) { sb.Append("<br/>"); } else { sb.Append(' '); } } renderSense(sb, sense, ref senseIx, thl); } sb.Append("</div>"); // <div class="senses"> if (renderEntryDiv) { sb.Append("</div>"); // <div class="entry"> } }
private void renderAnnotation(StringBuilder sb) { CedictEntry entry = ann.Entry; string entryClass = "entry"; if (tones == UiTones.Pleco) { entryClass += " toneColorsPleco"; } else if (tones == UiTones.Dummitt) { entryClass += " toneColorsDummitt"; } if (extraEntryClass != "") { entryClass += " " + extraEntryClass; } sb.Append("<div class='" + entryClass + "'>"); // <div class="entry"> sb.Append("<span class='hw-ann'>"); // <span class="hw-simp"> renderHanzi(query, entry, ann.StartInQuery, ann.LengthInQuery, sb); sb.Append("</span>"); // <span class="hw-ann"> sb.Append("<span class='hw-pinyin'>"); // <span class="hw-pinyin"> bool firstSyll = true; foreach (var pinyin in entry.Pinyin) { if (!firstSyll) { sb.Append(" "); } firstSyll = false; sb.Append(HtmlEncoder.Default.Encode(pinyin.GetDisplayString(true))); } sb.Append("</span>"); // <span class="hw-pinyin"> sb.Append("<div class='senses'>"); // <div class="senses"> int senseIx = 0; for (int i = 0; i != entry.SenseCount; ++i) { var sense = entry.GetSenseAt(i); if (isSpecialSense(sense)) { if (i != 0) { sb.Append("<br/>"); } } else if (i != 0) { if (isSpecialSense(entry.GetSenseAt(i - 1))) { sb.Append("<br/>"); } else { sb.Append(' '); } } renderSense(sb, sense, ref senseIx, null); } sb.Append("</div>"); // <div class="senses"> sb.Append("</div>"); // <div class="entry"> }
private bool verifyTrg(Tokenizer tokenizer, CedictEntry entry, int entryId, int senseIx, List <Token> qtoks, List <CedictResult> res) { if (entry == null) { return(false); } // Tokenize indicated sense's equiv; see if it matches query string equiv = entry.GetSenseAt(senseIx).Equiv; List <Token> rtoks = tokenizer.Tokenize(equiv); for (int i = 0; i != rtoks.Count; ++i) { int j = 0; bool startSplit = false; bool endSplit = false; for (; j != qtoks.Count; ++j) { if (i + j >= rtoks.Count) { break; } bool ok = false; Token rtok = rtoks[i + j]; Token qtok = qtoks[j]; if (rtok.Norm == qtok.Norm) { // Stopwords: only OK if token is an entire sub-sense in retrieved sense if (!trgStopWords.Contains(rtok.Norm)) { ok = true; } else { ok = rtok.SubSeq == 0 && (i == rtoks.Count - 1 || rtoks[i + 1].SubSeq == 0); } } // First query word: can be second half of word in retrieved sense if (j == 0 && rtok.SplitPosNorm != 0) { string rTwo = rtok.Norm.Substring(rtok.SplitPosNorm); if (rTwo == qtok.Norm) { // Stopwords: only if query is min 2 tokens, or result is one token only if (!trgStopWords.Contains(rTwo) || qtoks.Count > 1) { ok = true; } startSplit = true; } } // Last query word: can be first half of word in retrieved sense if (j == qtoks.Count - 1 && rtok.SplitPosNorm != 0) { string rOne = rtok.Norm.Substring(0, rtok.SplitPosNorm); if (rOne == qtok.Norm) { // Stopwords: only if query is min 2 tokens, or result is one token only if (!trgStopWords.Contains(rOne) || qtoks.Count > 1) { ok = true; } endSplit = true; } } if (!ok) { break; } } if (j != qtoks.Count) { continue; } // We got a match starting at i! CedictTargetHighlight[] hlarr = new CedictTargetHighlight[1]; int start = rtoks[i].Start; if (startSplit) { start += rtoks[i].SplitPosSurf; } int end = rtoks[i + j - 1].Start + rtoks[i + j - 1].Surf.Length; if (endSplit) { end -= (rtoks[i + j - 1].Surf.Length - rtoks[i + j - 1].SplitPosSurf); } hlarr[0] = new CedictTargetHighlight(senseIx, start, end - start); ReadOnlyCollection <CedictTargetHighlight> hlcoll = new ReadOnlyCollection <CedictTargetHighlight>(hlarr); CedictResult cr = new CedictResult(entry, hlcoll); // Stop right here res.Add(cr); return(true); } // Not a match return(false); }
/// <summary> /// Gets the entry formatted in HTML. /// </summary> public static string GetHtml(ITextProvider tprov, CedictEntry entry, SearchScript script) { StringBuilder bodyHtml = new StringBuilder(); // Are we showing one or two Hanzi headwords? string hanzi1 = script == SearchScript.Traditional ? entry.ChTrad : entry.ChSimpl; string hanzi2 = null; if (script == SearchScript.Both && entry.ChSimpl != entry.ChTrad) { hanzi2 = entry.ChTrad; } // Find simplest possible template, work with that // Only one hanzi, no longer than 2 chars, only one sense bool mustDoSenses = true; if (hanzi2 == null && hanzi1.Length <= 2 && entry.SenseCount == 1) { mustDoSenses = false; bodyHtml.Append(template1); bodyHtml.Replace("{hanzi}", escape(hanzi1)); bodyHtml.Replace("{pinyin}", escape(GetPinyinString(entry.GetPinyinForDisplay(true)))); bodyHtml.Replace("{sense}", getSenseHtmlPure(tprov, entry.GetSenseAt(0), script)); } // Only one script, no more than 6 chars else if (hanzi2 == null && hanzi1.Length <= 6) { bodyHtml.Append(template2); bodyHtml.Replace("{hanzi}", escape(hanzi1)); bodyHtml.Replace("{pinyin}", escape(GetPinyinString(entry.GetPinyinForDisplay(true)))); } // Only one script else if (hanzi2 == null) { bodyHtml.Append(template3); bodyHtml.Replace("{hanzi}", escape(hanzi1)); bodyHtml.Replace("{pinyin}", escape(GetPinyinString(entry.GetPinyinForDisplay(true)))); } // Everything else: very full-fledged entry else { bodyHtml.Append(template4); bodyHtml.Replace("{hanzi1}", escape(hanzi1)); bodyHtml.Replace("{hanzi2}", escape(hanzi2)); bodyHtml.Replace("{pinyin}", escape(GetPinyinString(entry.GetPinyinForDisplay(true)))); } // In all but the first, simplest case, dealing with senses is the same if (mustDoSenses) { StringBuilder sbSenses = new StringBuilder(); foreach (CedictSense sense in entry.Senses) { string senseHtml = ""; if (!sense.Domain.EqualsPlainText("CL:")) { senseHtml += templateDiamond; senseHtml += " "; } senseHtml += getSenseHtmlPure(tprov, sense, script); senseHtml = templateSense.Replace("{sense}", senseHtml); sbSenses.Append(senseHtml); } bodyHtml.Replace("{senses}", sbSenses.ToString()); } // Assemble the whole HTML StringBuilder sb = new StringBuilder(); sb.Append(templateOuter); sb.Replace("{body}", bodyHtml.ToString()); // Purge new lines and tabs: this avoids extra spaces e.g. when pasting into Word sb.Replace("\r\n", ""); sb.Replace("\t", ""); // Done return(sb.ToString()); }
private void renderResult(HtmlTextWriter writer) { int hanziLimit = isMobile ? 4 : 6; CedictEntry entry = prov.GetEntry(res.EntryId); Dictionary <int, CedictTargetHighlight> senseHLs = new Dictionary <int, CedictTargetHighlight>(); foreach (CedictTargetHighlight hl in res.TargetHilites) { senseHLs[hl.SenseIx] = hl; } string entryClass = "entry"; if (tones == UiTones.Pleco) { entryClass += " toneColorsPleco"; } else if (tones == UiTones.Dummitt) { entryClass += " toneColorsDummitt"; } writer.AddAttribute(HtmlTextWriterAttribute.Class, entryClass); writer.RenderBeginTag(HtmlTextWriterTag.Div); // <div class="entry"> if (script != UiScript.Trad) { writer.AddAttribute(HtmlTextWriterAttribute.Class, "hw-simp"); writer.RenderBeginTag(HtmlTextWriterTag.Span); // <span class="hw-simp"> renderHanzi(entry, true, false, writer); writer.RenderEndTag(); // <span class="hw-simp"> } if (script == UiScript.Both) { // Up to 6 hanzi: on a single line if (entry.ChSimpl.Length <= hanziLimit) { string clsSep = "hw-sep"; if (tones != UiTones.None) { clsSep = "hw-sep faint"; } writer.AddAttribute(HtmlTextWriterAttribute.Class, clsSep); writer.RenderBeginTag(HtmlTextWriterTag.Span); // <span class="hw-sep"> writer.WriteEncodedText("•"); writer.RenderEndTag(); // <span class="hw-sep"> } // Otherwise, line break else { writer.RenderBeginTag(HtmlTextWriterTag.Br); writer.RenderEndTag(); } } if (script != UiScript.Simp) { string clsTrad = "hw-trad"; // Need special class so traditional floats left after line break if (script == UiScript.Both && entry.ChSimpl.Length > hanziLimit) { clsTrad = "hw-trad break"; } writer.AddAttribute(HtmlTextWriterAttribute.Class, clsTrad); writer.RenderBeginTag(HtmlTextWriterTag.Span); // <span class="hw-trad"> renderHanzi(entry, false, script == UiScript.Both, writer); writer.RenderEndTag(); // <span class="hw-trad"> } writer.AddAttribute(HtmlTextWriterAttribute.Class, "hw-pinyin"); writer.RenderBeginTag(HtmlTextWriterTag.Span); // <span class="hw-pinyin"> bool firstSyll = true; foreach (var pinyin in entry.Pinyin) { if (!firstSyll) { writer.WriteEncodedText(" "); } firstSyll = false; writer.WriteEncodedText(pinyin.GetDisplayString(true)); } writer.RenderEndTag(); // <span class="hw-pinyin"> writer.AddAttribute(HtmlTextWriterAttribute.Class, "senses"); writer.RenderBeginTag(HtmlTextWriterTag.Div); // <div class="senses"> for (int i = 0; i != entry.SenseCount; ++i) { CedictTargetHighlight thl = null; if (senseHLs.ContainsKey(i)) { thl = senseHLs[i]; } renderSense(writer, entry.GetSenseAt(i), i, thl); } writer.RenderEndTag(); // <div class="senses"> writer.RenderEndTag(); // <div class="entry"> }