View Issue Details

IDProjectCategoryView StatusLast Update
0001555Composrsearchpublic2021-11-01 20:11
ReporterChris GrahamAssigned To 
SeverityFeature-request 
Status non-assignedResolutionopen 
Product Version 
Fixed in Version 
Summary0001555: Allow highlighting of keywords within Comcode html tags
DescriptionDeploy a basic HTML parser that looks at the HTML coming out of the Comcode parser and tries to put highlight tags around things that Comcode did not already highlight.
Additional InformationThis is a risky thing to do and needs to be an option. It's a performance hit (doing an HTML parse), difficult to actually do without mangling HTML, and may cause display corruptions. For example, CSS that targets particular DOM-tree relationships won't work correctly if new elements are inserted within the DOM tree.

It may be better to implement this in Javascript, relying on the browsers inbuilt DOM rendering. This won't resolve the CSS risk, but will resolve the mangling and performance risks.
TagsHas Patch, Roadmap: Over the horizon, Type: Performance
Time estimation (hours)8
Sponsorship open

Activities

Chris Graham

2020-05-18 17:24

administrator   ~0006551

I've flagged this as a performance issue because the current re-parsing of Comcode within search results is a performance hit.

Chris Graham

2020-05-28 21:18

administrator   ~0006571

Last edited: 2020-05-28 21:19

View 2 revisions

Here's a messy diff to implement this, made on a v9 site and using https://markjs.io/...

diff --git a/site/pages/modules/search.php b/site/pages/modules/search.php
index 45bf567..7272be5 100644
--- a/site/pages/modules/search.php
+++ b/site/pages/modules/search.php
@@ -558,7 +558,40 @@ class Module_search
                        }
                }
 
- return do_template('SEARCH_FORM_SCREEN',array('_GUID'=>'8bb208185740183323a6fe6e89d55de5','SEARCH_TERM'=>is_null($content)?'':$content,'HAS_TEMPLATE_SEARCH'=>$has_template_search,'NUM_RESULTS'=>integer_format($num_results),'CAN_ORDER_BY_RATING'=>$can_order_by_rating,'EXTRA_SORT_FIELDS'=>$extra_sort_fields,'USER_LABEL'=>$user_label,'DAYS_LABEL'=>$days_label,'BOOLEAN_SEARCH'=>$this->_is_boolean_search(),'AND'=>$boolean_operator=='AND','ONLY_TITLES'=>$only_titles,'DAYS'=>strval($days),'SORT'=>$sort,'DIRECTION'=>$direction,'CONTENT'=>$content,'RESULTS'=>$out,'PAGINATION'=>$pagination,'OLD_MYSQL'=>$old_mysql,'TITLE'=>$title,'AUTHOR'=>$author,'SPECIALISATION'=>$specialisation,'URL'=>$url));
+ if (get_value('js_highlight')==='1') {
+ require_javascript('javascript_mark');
+
+ global $SEARCH__CONTENT_BITS;
+ $search_keywords = $SEARCH__CONTENT_BITS;
+ } else {
+ $search_keywords = null;
+ }
+
+ return do_template('SEARCH_FORM_SCREEN',array(
+ '_GUID'=>'8bb208185740183323a6fe6e89d55de5',
+ 'SEARCH_TERM'=>is_null($content)?'':$content,
+ 'HAS_TEMPLATE_SEARCH'=>$has_template_search,
+ 'NUM_RESULTS'=>integer_format($num_results),
+ 'CAN_ORDER_BY_RATING'=>$can_order_by_rating,
+ 'EXTRA_SORT_FIELDS'=>$extra_sort_fields,
+ 'USER_LABEL'=>$user_label,
+ 'DAYS_LABEL'=>$days_label,
+ 'BOOLEAN_SEARCH'=>$this->_is_boolean_search(),
+ 'AND'=>$boolean_operator=='AND',
+ 'ONLY_TITLES'=>$only_titles,
+ 'DAYS'=>strval($days),
+ 'SORT'=>$sort,
+ 'DIRECTION'=>$direction,
+ 'CONTENT'=>$content,
+ 'RESULTS'=>$out,
+ 'PAGINATION'=>$pagination,
+ 'OLD_MYSQL'=>$old_mysql,
+ 'TITLE'=>$title,
+ 'AUTHOR'=>$author,
+ 'SPECIALISATION'=>$specialisation,
+ 'URL'=>$url,
+ 'SEARCH_KEYWORDS'=>$search_keywords,
+ ));
        }
 
        /**
@@ -612,7 +645,7 @@ class Module_search
                $_content_bits=explode(' ',str_replace('"','',preg_replace('#(^|\s)\+#','',preg_replace('#(^|\s)\-#','',$content))));
                $SEARCH__CONTENT_BITS=array();
                require_code('textfiles');
- $too_common_words=explode(chr(10),read_text_file('too_common_words','',true));
+ $too_common_words=(get_value('js_highlight')==='1')?array():explode(chr(10),read_text_file('too_common_words','',true));
                foreach ($_content_bits as $content_bit)
                {
                        $content_bit=trim($content_bit);
diff --git a/sources/lang.php b/sources/lang.php
index 1b77963..3568198 100644
--- a/sources/lang.php
+++ b/sources/lang.php
@@ -1164,7 +1164,7 @@ function get_translated_tempcode($table,$row,$field_name,$connection=NULL,$lang=
                }
 
                global $SEARCH__CONTENT_BITS;
- if ($SEARCH__CONTENT_BITS!==NULL) // Doing a search so we need to reparse, with highlighting on
+ if (($SEARCH__CONTENT_BITS!==NULL) && (get_value('js_highlight')!=='1')) // Doing a search so we need to reparse, with highlighting on
                {
                        $_result=$connection->query_select('translate',array('text_original','source_user'),array('id'=>$entry,'language'=>$lang),'',1);
                        if (array_key_exists(0,$_result))
@@ -1198,7 +1198,7 @@ function get_translated_tempcode($table,$row,$field_name,$connection=NULL,$lang=
        } else
        {
                global $SEARCH__CONTENT_BITS;
- if ($SEARCH__CONTENT_BITS!==NULL) // Doing a search so we need to reparse, with highlighting on
+ if (($SEARCH__CONTENT_BITS!==NULL) && (get_value('js_highlight')!=='1')) // Doing a search so we need to reparse, with highlighting on
                {
                        global $LAX_COMCODE;
                        $temp=$LAX_COMCODE;
diff --git a/sources/tempcode_compiler.php b/sources/tempcode_compiler.php
index e887e53..d5860b2 100644
--- a/sources/tempcode_compiler.php
+++ b/sources/tempcode_compiler.php
@@ -601,7 +601,7 @@ function _do_template($theme,$path,$codename,$_codename,$lang,$suffix,$theme_ori
                $_path=$base_dir.filter_naughty($theme.$path.$codename).$suffix;
                $tmp=fopen($_path,'rb');
                flock($tmp,LOCK_SH);
- $html=unixify_line_format(file_get_contents($_path));
+ $html=unixify_line_format(file_get_contents($_path),($codename=='JAVASCRIPT_MARK')?'utf-8':null);
                flock($tmp,LOCK_UN);
                fclose($tmp);
        }
diff --git a/themes/VWGolf-2015/templates_custom/SEARCH_FORM_SCREEN.tpl b/themes/VWGolf-2015/templates_custom/SEARCH_FORM_SCREEN.tpl
index 7962755..ada1fda 100644
--- a/themes/VWGolf-2015/templates_custom/SEARCH_FORM_SCREEN.tpl
+++ b/themes/VWGolf-2015/templates_custom/SEARCH_FORM_SCREEN.tpl
@@ -172,4 +172,23 @@
                        </div>
                </div></div>
        </form>
-{+END}
\ No newline at end of file
+{+END}
+
+{+START,IF_PASSED,SEARCH_KEYWORDS}
+ <script>
+ // https://markjs.io/
+
+ var element = document.querySelectorAll('.search_result');
+ var instance = new Mark(element);
+ instance.mark(
+ [
+ {+START,LOOP,SEARCH_KEYWORDS}
+ '{_loop_var;}',
+ {+END}
+ ],
+ {
+ 'className': 'comcode_highlight',
+ }
+ );
+ </script>
+{+END}
diff --git a/themes/default/templates/JAVASCRIPT_NEED.tpl b/themes/default/templates/JAVASCRIPT_NEED.tpl
index acc50f1..c133a0e 100644
--- a/themes/default/templates/JAVASCRIPT_NEED.tpl
+++ b/themes/default/templates/JAVASCRIPT_NEED.tpl
@@ -1 +1 @@
-<script type="text/javascript" src="{$CUSTOM_BASE_URL*}/themes/{$THEME*}/templates_cached/{$LANG*}/{CODE*}.js{+START,IF_PASSED,SUP}?{SUP*}{+END}"></script>
+<script{+START,IF,{$EQ,{CODE},javascript_mark}} charset="utf-8"{+END} type="text/javascript" src="{$CUSTOM_BASE_URL*}/themes/{$THEME*}/templates_cached/{$LANG*}/{CODE*}.js{+START,IF_PASSED,SUP}?{SUP*}{+END}"></script>


I'm not putting into v11 just because it requires JS code to be done neatly to the new framework, and we have a bottleneck in that area at the moment.


When done, the mark.js dependency will need tracking properly.

Issue History

Date Modified Username Field Change
2020-05-18 17:23 Chris Graham Tag Attached: Type: Performance
2020-05-18 17:24 Chris Graham Note Added: 0006551
2020-05-28 20:35 Chris Graham Tag Attached: Roadmap: v12
2020-05-28 21:18 Chris Graham Note Added: 0006571
2020-05-28 21:19 Chris Graham Note Edited: 0006571 View Revisions
2021-11-01 20:11 Chris Graham Tag Attached: Has Patch
2024-03-26 00:58 Patrick Schmalstig Tag Renamed Roadmap: v12 => Roadmap: Over the horizon