-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New extension WordHighlighter - for highlighting words. (#238)
* init commit for new extension WordHighlighter - for highlighting words. * use `json` for storing configuration, add more configuration options (enable_in_article, enable_logs, case_sensitive, separate_word_search) and refactored & simplified code * fix: try to fix test errors * fix: try to fix tests * fix unnecessary casting to string * fix: try to fix PHPStan errors, mostly: Cannot access offset '...' on mixed. And add missing types. * fix: try to fix "Cannot access offset '...' on mixed." * fix typo in comment * refactor: remove $lineSeparator and replace `explode` with `preg_split` * i18n: fr --------- Co-authored-by: Lukáš Melega <[email protected]> Co-authored-by: Alexandre Alapetite <[email protected]>
- Loading branch information
1 parent
f845a6d
commit 31bbdb5
Showing
15 changed files
with
1,053 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# WordHighlighter extension | ||
|
||
A FreshRSS extension which give ability to highlight user-defined words. | ||
|
||
## Usage | ||
|
||
To use it, upload this directory in your `./extensions` directory and enable it on the extension panel in FreshRSS. You can add words to be highlighted by clicking on the manage button ⚙️. | ||
See also official docs at freshrss.github.io/FreshRSS/en/admins/15_extensions.html | ||
|
||
## Preview | ||
|
||
Light theme: | ||
|
||
![snapshot](./snapshot.png) | ||
|
||
<!-- markdownlint-disable --> | ||
<details> | ||
<summary>click to see example screenshot in dark theme</summary> | ||
|
||
![snapshot-dark-theme](./snapshot-dark.png) | ||
|
||
</details> | ||
<!-- markdownlint-enable --> | ||
|
||
## Changelog | ||
|
||
- 0.0.2 use `json` for storing configuration, add more configuration options | ||
(enable_in_article, enable_logs, case_sensitive, separate_word_search) | ||
and refactored & simplified code | ||
- 0.0.1 initial version (as a proper FreshRSS extension) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
<?php | ||
declare(strict_types=1); | ||
/** @var WordHighlighterExtension $this */ | ||
?> | ||
<form action="<?= _url('extension', 'configure', 'e', urlencode($this->getName())) ?>" method="post"> | ||
<input type="hidden" name="_csrf" value="<?= FreshRSS_Auth::csrfToken() ?>" /> | ||
|
||
<div class="form-group"> | ||
<label class="group-name" for="words_list"> | ||
<?= _t('ext.word_highlighter.write_words') ?> <br /> | ||
<?= _t('ext.word_highlighter.write_words_more') ?> | ||
</label> | ||
<div class="group-controls"> | ||
<textarea name="words_list" | ||
id="words_list"><?= $this->word_highlighter_conf ?></textarea> | ||
</div> | ||
</div> | ||
|
||
<div class="form-group"> | ||
<label for="enable-in-article" class="group-name"> | ||
<?= _t('ext.word_highlighter.enable_in_article') ?> | ||
</label> | ||
<div class="group-controls"> | ||
<?php if ($this->enable_in_article == '') { ?> | ||
<input type="checkbox" name="enable-in-article" id="enable-in-article"></input> | ||
<?php } else { ?> | ||
<input type="checkbox" name="enable-in-article" id="enable-in-article" checked="true"></input> | ||
<?php } ?> | ||
<i><?= _t('ext.word_highlighter.enable_in_article_more') ?></i> | ||
</div> | ||
</div> | ||
|
||
<details> | ||
<summary>Click to see more advanced options</summary> | ||
|
||
<div class="form-group"> | ||
<label for="case_sensitive" class="group-name"> | ||
<?= _t('ext.word_highlighter.case_sensitive') ?> | ||
</label> | ||
<div class="group-controls"> | ||
<?php if ($this->case_sensitive == '') { ?> | ||
<input type="checkbox" name="case_sensitive" id="case_sensitive"></input> | ||
<?php } else { ?> | ||
<input type="checkbox" name="case_sensitive" id="case_sensitive" checked="true"></input> | ||
<?php } ?> | ||
</div> | ||
</div> | ||
|
||
<div class="form-group"> | ||
<label for="separate_word_search" class="group-name"> | ||
<?= _t('ext.word_highlighter.separate_word_search') ?> | ||
</label> | ||
<div class="group-controls"> | ||
<?php if ($this->separate_word_search == '') { ?> | ||
<input type="checkbox" name="separate_word_search" id="separate_word_search"></input> | ||
<?php } else { ?> | ||
<input type="checkbox" name="separate_word_search" id="separate_word_search" checked="true"></input> | ||
<?php } ?> | ||
</div> | ||
</div> | ||
|
||
<div class="form-group"> | ||
<label for="enable_logs" class="group-name"> | ||
<?= _t('ext.word_highlighter.enable_logs') ?> | ||
</label> | ||
<div class="group-controls"> | ||
<?php if ($this->enable_logs == '') { ?> | ||
<input type="checkbox" name="enable_logs" id="enable_logs"></input> | ||
<?php } else { ?> | ||
<input type="checkbox" name="enable_logs" id="enable_logs" checked="true"></input> | ||
<?php } ?> | ||
</div> | ||
|
||
</div> | ||
</details> | ||
|
||
<div class="form-group form-actions"> | ||
<?php if ($this->permission_problem !== '') { ?> | ||
<p class="alert alert-error"><?= _t('ext.word_highlighter.permission_problem', $this->permission_problem) ?></p> | ||
<?php } else { ?> | ||
<div class="group-controls"> | ||
<button type="submit" class="btn btn-important"><?= _t('gen.action.submit') ?></button> | ||
<button type="reset" class="btn"><?= _t('gen.action.cancel') ?></button> | ||
</div> | ||
<?php } ?> | ||
</div> | ||
|
||
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
final class WordHighlighterExtension extends Minz_Extension | ||
{ | ||
const JSON_ENCODE_CONF = JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR; | ||
|
||
public string $word_highlighter_conf = 'test'; | ||
public string $permission_problem = ''; | ||
public bool $enable_in_article = false; | ||
public bool $enable_logs = false; | ||
public bool $case_sensitive = false; | ||
public bool $separate_word_search = false; | ||
|
||
#[\Override] | ||
public function init(): void | ||
{ | ||
$this->registerTranslates(); | ||
|
||
// register CSS for WordHighlighter: | ||
Minz_View::appendStyle($this->getFileUrl('style.css', 'css')); | ||
|
||
Minz_View::appendScript($this->getFileUrl('mark.min.js', 'js'), false, false, false); | ||
|
||
$current_user = Minz_Session::paramString('currentUser'); | ||
|
||
$staticPath = join_path($this->getPath(), 'static'); | ||
$configFileJs = join_path($staticPath, ('config.' . $current_user . '.js')); | ||
|
||
if (file_exists($configFileJs)) { | ||
Minz_View::appendScript($this->getFileUrl(('config.' . $current_user . '.js'), 'js')); | ||
} | ||
|
||
Minz_View::appendScript($this->getFileUrl('word-highlighter.js', 'js')); | ||
} | ||
|
||
#[\Override] | ||
public function handleConfigureAction(): void | ||
{ | ||
$this->registerTranslates(); | ||
|
||
$current_user = Minz_Session::paramString('currentUser'); | ||
$staticPath = join_path($this->getPath(), 'static'); | ||
|
||
$configFileJson = join_path($staticPath, ('config.' . $current_user . '.json')); | ||
|
||
if (!file_exists($configFileJson) && !is_writable($staticPath)) { | ||
$tmpPath = explode(EXTENSIONS_PATH . '/', $staticPath); | ||
$this->permission_problem = $tmpPath[1] . '/'; | ||
|
||
} elseif (file_exists($configFileJson) && !is_writable($configFileJson)) { | ||
$tmpPath = explode(EXTENSIONS_PATH . '/', $configFileJson); | ||
$this->permission_problem = $tmpPath[1]; | ||
|
||
} elseif (Minz_Request::isPost()) { | ||
$configWordList = html_entity_decode(Minz_Request::paramString('words_list')); | ||
|
||
$this->word_highlighter_conf = $configWordList; | ||
$this->enable_in_article = (bool) Minz_Request::paramString('enable-in-article'); | ||
$this->enable_logs = (bool) Minz_Request::paramString('enable_logs'); | ||
$this->case_sensitive = (bool) Minz_Request::paramString('case_sensitive'); | ||
$this->separate_word_search = (bool) Minz_Request::paramString('separate_word_search'); | ||
|
||
$configObj = [ | ||
'enable_in_article' => $this->enable_in_article, | ||
'enable_logs' => $this->enable_logs, | ||
'case_sensitive' => $this->case_sensitive, | ||
'separate_word_search' => $this->separate_word_search, | ||
'words' => preg_split("/\r\n|\n|\r/", $configWordList), | ||
]; | ||
$configJson = json_encode($configObj, WordHighlighterExtension::JSON_ENCODE_CONF); | ||
file_put_contents(join_path($staticPath, ('config.' . $current_user . '.json')), $configJson . PHP_EOL); | ||
file_put_contents(join_path($staticPath, ('config.' . $current_user . '.js')), $this->jsonToJs($configJson) . PHP_EOL); | ||
} | ||
|
||
if (file_exists($configFileJson)) { | ||
try { | ||
$confJson = json_decode(file_get_contents($configFileJson) ?: '', true, 8, JSON_THROW_ON_ERROR); | ||
if (json_last_error() !== JSON_ERROR_NONE || !is_array($confJson)) { | ||
return; | ||
} | ||
$this->enable_in_article = (bool) ($confJson['enable_in_article'] ?? false); | ||
$this->enable_logs = (bool) ($confJson['enable_logs'] ?? false); | ||
$this->case_sensitive = (bool) ($confJson['case_sensitive'] ?? false); | ||
$this->separate_word_search = (bool) ($confJson['separate_word_search'] ?? false); | ||
$this->word_highlighter_conf = implode("\n", (array) ($confJson['words'] ?? [])); | ||
|
||
} catch (Exception $exception) { | ||
// probably nothing to do needed | ||
} | ||
} | ||
} | ||
|
||
private function jsonToJs(string $jsonStr): string | ||
{ | ||
$js = "window.WordHighlighterConf = " . | ||
$jsonStr . ";\n" . | ||
"window.WordHighlighterConf.enable_logs && console.log('WordHighlighter: loaded user config:', window.WordHighlighterConf);"; | ||
return $js; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
return array( | ||
'word_highlighter' => array( | ||
'write_words' => 'Words to highlight', | ||
'write_words_more' => '(separated by newline)', | ||
'enable_in_article' => 'Enable highlighting also in article', | ||
'enable_in_article_more' => '(⚠️ may be slower with a lot of words)', | ||
'enable_logs' => 'Enable logs', | ||
'case_sensitive' => 'Case sensitive', | ||
'separate_word_search' => 'Separate word search', | ||
'test_highlighting_word' => 'highlight', | ||
'permission_problem' => 'Your config file is not writable, please change the file permissions for %s', | ||
), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
return array( | ||
'word_highlighter' => array( | ||
'write_words' => 'Mots à surligner', | ||
'write_words_more' => '(séparés par une nouvelle ligne)', | ||
'enable_in_article' => 'Activer la mise en évidence également dans l’article', | ||
'enable_in_article_more' => '(⚠️ peut être plus lent avec beaucoup de mots)', | ||
'enable_logs' => 'Activer les journaux', | ||
'case_sensitive' => 'Sensible à la casse', | ||
'separate_word_search' => 'Recherche de mots séparés', | ||
'test_highlighting_word' => 'surligner', | ||
'permission_problem' => 'Votre fichier de configuration n’est pas accessible en écriture, veuillez modifier les permissions du fichier %s', | ||
), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"name": "Word highlighter", | ||
"author": "Lukas Melega", | ||
"description": "Highlight specific words", | ||
"version": "0.0.2", | ||
"entrypoint": "WordHighlighter", | ||
"type": "user" | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
config-words.*.js | ||
config-words.*.txt |
Oops, something went wrong.