16 #include <string_view>
17 #include "../config/btconfig.h"
18 #include "../drivers/cswordmoduleinfo.h"
19 #include "../managers/cswordbackend.h"
20 #include "../managers/referencemanager.h"
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wsuggest-override"
25 #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
29 #pragma GCC diagnostic pop
34 template <
typename UserData>
37 sword::SWModule
const & myModule,
38 UserData
const & myUserData)
40 QString
const ref(osisRef);
56 QStringLiteral(
"standardBible"));
65 auto const pos = ref.indexOf(
':');
69 && ref.at(pos - 1).isLetter()
70 && ref.at(pos + 1).isLetter())
72 auto const newModuleName(ref.left(pos));
73 hrefRef = ref.mid(pos + 1);
75 if (
auto const *
const moduleByName =
86 QString::fromUtf8(myUserData.key->getText()),
87 myModule.getLanguage()};
97 buf.append(
"<a href=\"")
98 .append(hyperlink.constData())
99 .append(
"\" crossrefs=\"")
100 .append(moduleMarker.constData())
111 setPassThruUnknownEscapeString(
true);
113 addTokenSubstitute(
"inscription",
"<span class=\"inscription\">");
114 addTokenSubstitute(
"/inscription",
"</span>");
116 addTokenSubstitute(
"mentioned",
"<span class=\"mentioned\">");
117 addTokenSubstitute(
"/mentioned",
"</span>");
127 addTokenSubstitute(
"table",
"<table>");
128 addTokenSubstitute(
"/table",
"</table>");
129 addTokenSubstitute(
"row",
"<tr>");
130 addTokenSubstitute(
"/row",
"</tr>");
131 addTokenSubstitute(
"cell",
"<td>");
132 addTokenSubstitute(
"/cell",
"</td>");
137 using namespace std::literals;
140 if (!substituteToken(buf, token)) {
142 sword::SWModule* myModule =
const_cast<sword::SWModule*
>(myUserData->module);
144 sword::XMLTag
const tag(token);
146 auto const osisQToTickEntry =
147 userData->module->getConfigEntry(
"OSISqToTick");
148 bool const osisQToTick =
149 !osisQToTickEntry || osisQToTickEntry !=
"false"sv;
151 std::string_view
const tagName(tag.getName());
153 if (tagName ==
"div"sv) {
154 if (tag.isEndTag()) {
155 buf.append(
"</div>");
157 sword::SWBuf type( tag.getAttribute(
"type") );
158 if (type ==
"introduction") {
160 buf.append(
"<div class=\"introduction\">");
161 }
else if (type ==
"chapter") {
163 buf.append(
"<div class=\"chapter\" ></div>");
164 }
else if (type ==
"x-p") {
166 }
else if (type ==
"paragraph") {
167 if (tag.getAttribute(
"sID"))
169 else if (tag.getAttribute(
"eID"))
176 else if (tagName ==
"w"sv) {
177 if ((!tag.isEmpty()) && (!tag.isEndTag())) {
181 sword::XMLTag outTag(
"span");
182 sword::SWBuf attrValue;
184 if ((attrib = tag.getAttribute(
"xlit"))) {
185 val = strchr(attrib,
':');
186 val = (val) ? (val + 1) : attrib;
187 outTag.setAttribute(
"xlit", val);
190 if ((attrib = tag.getAttribute(
"gloss"))) {
191 val = strchr(attrib,
':');
192 val = (val) ? (val + 1) : attrib;
193 outTag.setAttribute(
"gloss", val);
196 if ((attrib = tag.getAttribute(
"lemma"))) {
197 char splitChar =
'|';
198 const int countSplit1 = tag.getAttributePartCount(
"lemma",
'|');
199 const int countSplit2 = tag.getAttributePartCount(
"lemma",
' ');
202 if (countSplit1 > countSplit2) {
211 int i = (count > 1) ? 0 : -1;
215 if (attrValue.length()) {
216 attrValue.append(
'|' );
219 attrib = tag.getAttribute(
"lemma", i, splitChar);
225 val = strchr(attrib,
':');
226 val = (val) ? (val + 1) : attrib;
228 attrValue.append(val);
232 if (attrValue.length()) {
233 outTag.setAttribute(
"lemma", attrValue.c_str());
237 if ((attrib = tag.getAttribute(
"morph"))) {
238 char splitChar =
'|';
239 const int countSplit1 = tag.getAttributePartCount(
"morph",
'|');
240 const int countSplit2 = tag.getAttributePartCount(
"morph",
' ');
243 if (countSplit1 > countSplit2) {
252 int i = (count > 1) ? 0 : -1;
257 if (attrValue.length()) {
258 attrValue.append(
'|');
261 attrib = tag.getAttribute(
"morph", i, splitChar);
267 val = strchr(attrib,
':');
271 if (!strncmp(
"robinson:", attrib, 9)) {
272 attrValue.append(
"Robinson:" );
273 attrValue.append( val + 1 );
280 attrValue.append( !strncmp(attrib,
"x-", 2) ? attrib + 2 : attrib );
285 const bool skipFirst = ((val[0] ==
'T') && ((val[1] ==
'H') || (val[1] ==
'G')));
286 attrValue.append( skipFirst ? val + 1 : val );
291 if (attrValue.length()) {
292 outTag.setAttribute(
"morph", attrValue.c_str());
296 if ((attrib = tag.getAttribute(
"POS"))) {
297 val = strchr(attrib,
':');
298 val = (val) ? (val + 1) : attrib;
299 outTag.setAttribute(
"pos", val);
302 buf.append( outTag.toString() );
304 else if (tag.isEndTag()) {
305 buf.append(
"</span>");
308 else if (tagName ==
"note"sv) {
309 if (!tag.isEndTag()) {
310 const sword::SWBuf type( tag.getAttribute(
"type") );
312 if (type ==
"crossReference") {
325 buf.append(
"<span class=\"crossreference\">");
326 sword::SWBuf footnoteNumber = tag.getAttribute(
"swordFootnote");
327 sword::SWBuf footnoteBody = myUserData->
entryAttributes[
"Footnote"][footnoteNumber][
"body"];
328 buf += myModule->renderText(footnoteBody);
334 else if ((type ==
"strongsMarkup") || (type ==
"x-strongsMarkup")) {
340 myUserData->suspendTextPassThru =
true;
341 myUserData->
noteTypes.emplace_back(UserData::StrongsMarkup);
346 buf.append(
" <span class=\"footnote\" note=\"");
347 buf.append(myModule->getName());
349 buf.append(myUserData->key->getShortText());
351 buf.append( QString::number(myUserData->
swordFootnote++).toUtf8().constData() );
353 const sword::SWBuf n = tag.getAttribute(
"n");
356 buf.append( (n.length() > 0) ? n.c_str() :
"*" );
357 buf.append(
"</span> ");
360 myUserData->suspendTextPassThru =
true;
363 else if ( !myUserData->
noteTypes.empty()) {
365 buf.append(
"</span> ");
371 myUserData->suspendTextPassThru =
false;
374 else if (tagName ==
"reference"sv) {
375 if (!tag.isEndTag() && !tag.isEmpty()) {
381 else if (tag.isEndTag()) {
388 else if (tagName ==
"title"sv) {
389 if (!tag.isEndTag() && !tag.isEmpty()) {
390 buf.append(
"<div class=\"sectiontitle\">");
392 else if (tag.isEndTag()) {
393 buf.append(
"</div>");
400 else if (tagName ==
"hi"sv) {
401 const sword::SWBuf type = tag.getAttribute(
"type");
403 if ((!tag.isEndTag()) && (!tag.isEmpty())) {
404 if (type ==
"bold") {
405 buf.append(
"<span class=\"bold\">");
407 else if (type ==
"illuminated") {
408 buf.append(
"<span class=\"illuminated\">");
410 else if (type ==
"italic") {
411 buf.append(
"<span class=\"italic\">");
413 else if (type ==
"line-through") {
414 buf.append(
"<span class=\"line-through\">");
416 else if (type ==
"normal") {
417 buf.append(
"<span class=\"normal\">");
419 else if (type ==
"small-caps") {
420 buf.append(
"<span class=\"small-caps\">");
422 else if (type ==
"underline") {
423 buf.append(
"<span class=\"underline\">");
426 buf.append(
"<span>");
429 else if (tag.isEndTag()) {
430 buf.append(
"</span>");
433 else if (tagName ==
"name"sv) {
434 const sword::SWBuf type = tag.getAttribute(
"type");
436 if ((!tag.isEndTag()) && (!tag.isEmpty())) {
437 if (type ==
"geographic") {
438 buf.append(
"<span class=\"name\"><span class=\"geographic\">");
440 else if (type ==
"holiday") {
441 buf.append(
"<span class=\"name\"><span class=\"holiday\">");
443 else if (type ==
"nonhuman") {
444 buf.append(
"<span class=\"name\"><span class=\"nonhuman\">");
446 else if (type ==
"person") {
447 buf.append(
"<span class=\"name\"><span class=\"person\">");
449 else if (type ==
"ritual") {
450 buf.append(
"<span class=\"name\"><span class=\"ritual\">");
453 buf.append(
"<span class=\"name\"><span>");
456 else if (tag.isEndTag()) {
457 buf.append(
"</span></span> ");
460 else if (tagName ==
"transChange"sv) {
461 sword::SWBuf type( tag.getAttribute(
"type") );
463 if ( !type.length() ) {
464 type = tag.getAttribute(
"changeType");
467 if ((!tag.isEndTag()) && (!tag.isEmpty())) {
468 if (type ==
"added") {
469 buf.append(
"<span class=\"transchange\" title=\"");
470 buf.append(QObject::tr(
"Added text").toUtf8().constData());
471 buf.append(
"\"><span class=\"added\">");
473 else if (type ==
"amplified") {
474 buf.append(
"<span class=\"transchange\"><span class=\"amplified\">");
476 else if (type ==
"changed") {
477 buf.append(
"<span class=\"transchange\"><span class=\"changed\">");
479 else if (type ==
"deleted") {
480 buf.append(
"<span class=\"transchange\"><span class=\"deleted\">");
482 else if (type ==
"moved") {
483 buf.append(
"<span class=\"transchange\"><span class=\"moved\">");
485 else if (type ==
"tenseChange") {
486 buf.append(
"<span class=\"transchange\" title=\"");
487 buf.append(QObject::tr(
"Verb tense changed").toUtf8().constData());
488 buf.append(
"\"><span class=\"tenseChange\">");
491 buf.append(
"<span class=\"transchange\"><span>");
494 else if (tag.isEndTag()) {
495 buf.append(
"</span></span>");
498 else if (tagName ==
"p"sv) {
505 else if (tagName ==
"q"sv) {
507 sword::SWBuf who = tag.getAttribute(
"who");
508 const char *lev = tag.getAttribute(
"level");
509 int level = (lev) ? atoi(lev) : 1;
510 sword::SWBuf quoteMarker = tag.getAttribute(
"marker");
512 if ((!tag.isEndTag())) {
513 if (!tag.isEmpty()) {
517 if (quoteMarker.size() > 0) {
518 buf.append(quoteMarker);
520 else if (osisQToTick)
521 buf.append((level % 2) ?
'\"' :
'\'');
523 if (who ==
"Jesus") {
524 buf.append(
"<span class=\"jesuswords\">");
527 else if (tag.isEndTag()) {
528 if (myUserData->
quote.
who ==
"Jesus") {
529 buf.append(
"</span>");
531 if (quoteMarker.size() > 0) {
532 buf.append(quoteMarker);
534 else if (osisQToTick) {
535 buf.append((level % 2) ?
'\"' :
'\'');
541 else if (tagName ==
"abbr"sv) {
542 if (!tag.isEndTag() && !tag.isEmpty()) {
543 const sword::SWBuf expansion = tag.getAttribute(
"expansion");
545 buf.append(
"<span class=\"abbreviation\" expansion=\"");
546 buf.append(expansion);
549 else if (tag.isEndTag()) {
550 buf.append(
"</span>");
553 else if (tagName ==
"milestone"sv) {
554 const sword::SWBuf type = tag.getAttribute(
"type");
556 if ((type ==
"screen") || (type ==
"line")) {
558 userData->supressAdjacentWhitespace =
true;
560 else if (type ==
"x-p") {
562 const sword::SWBuf marker = tag.getAttribute(
"marker");
563 if (marker.length() > 0) {
568 else if (tagName ==
"seg"sv) {
569 if (!tag.isEndTag() && !tag.isEmpty()) {
571 const sword::SWBuf type = tag.getAttribute(
"type");
573 if (type ==
"morph") {
575 sword::XMLTag outTag(
"span");
576 outTag.setAttribute(
"class",
"morphSegmentation");
577 const char* attrValue;
580 if ((attrValue = tag.getAttribute(
"lemma"))) outTag.setAttribute(
"lemma", attrValue);
581 if ((attrValue = tag.getAttribute(
"morph"))) outTag.setAttribute(
"morph", attrValue);
582 if ((attrValue = tag.getAttribute(
"homonym"))) outTag.setAttribute(
"homonym", attrValue);
584 buf.append(outTag.toString());
588 buf.append(
"<span>");
592 buf.append(
"</span>");
597 else if (tagName ==
"divineName"sv) {
598 if (!tag.isEndTag()) {
599 buf.append(
"<span class=\"name\"><span class=\"divine\">");
602 buf.append(
"</span></span>");
606 return sword::OSISHTMLHREF::handleToken(buf, token, userData);
BtConfig & btConfig()
This is a shortchand for BtConfig::getInstance().
CSwordModuleInfo * getDefaultSwordModuleByType(const QString &moduleType)
Returns default sword module info class for a given module type.
CSwordModuleInfo * findFirstAvailableModule(CSwordModuleInfo::ModuleType type)
static CSwordBackend & instance() noexcept
CSwordModuleInfo * findSwordModuleByPointer(const sword::SWModule *const swmodule) const
Searches for a module with the given sword module as module().
unsigned short int swordFootnote
sword::AttributeTypeList entryAttributes
std::vector< NoteType > noteTypes
struct Filters::OsisToHtml::UserData::@0 quote
bool handleToken(sword::SWBuf &buf, const char *token, sword::BasicFilterUserData *userData) override
QString parseVerseReference(QString const &ref, ParseOptions const &options)
QString encodeHyperlink(CSwordModuleInfo const &module, QString const &key)
void renderReference(char const *const osisRef, sword::SWBuf &buf, sword::SWModule const &myModule, UserData const &myUserData)