fragment_highlighter-rails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +41 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/fragment_highlighter-rails.gemspec +26 -0
- data/lib/fragment_highlighter/rails.rb +8 -0
- data/lib/fragment_highlighter/rails/version.rb +5 -0
- data/vendor/assets/javascripts/fragment-highlighter/fragment-highlighter.js +35 -0
- data/vendor/assets/javascripts/fragment-highlighter/libs/classes/HView.js +68 -0
- data/vendor/assets/javascripts/fragment-highlighter/libs/classes/HWindowCtrls.js +64 -0
- data/vendor/assets/javascripts/fragment-highlighter/libs/classes/LS.js +10 -0
- data/vendor/assets/javascripts/fragment-highlighter/libs/classes/Marker.js +56 -0
- data/vendor/assets/javascripts/fragment-highlighter/libs/classes/Tools.js +9 -0
- data/vendor/assets/javascripts/fragment-highlighter/libs/classes/UserSettings.js +86 -0
- data/vendor/assets/javascripts/fragment-highlighter/libs/jquery.mark.es6.min.js +7 -0
- data/vendor/assets/stylesheets/fragment-highlighter.css +26 -0
- metadata +119 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c6408468fafdf63427c816205dd38a1215f48f4e
|
4
|
+
data.tar.gz: b461fe69e5f315729de0fcedde65a5a36fd38eb3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b75f5574ec1c03e52cb652eee80b8d1e6d5274139d9f18d1dbb5d573945d421e6be293365729c71dcf1b4b19dfef92c12bfaea5a8fea7c861de231dca35ff9a1
|
7
|
+
data.tar.gz: 74e581c62c117065ad72acdfc4a4d7c34fd2119fa81d0a561b6ea53f202fefd07fb34d9ebd7377379364f8f910ca322b43e71c1f3ac63c7a8a47d247a49c74ca
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017 Flower Team
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# fragment_highlighter-rails
|
2
|
+
JavaScript UI library for highlighting text fragments on page and saving ones into localStorage
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'fragment_highlighter-rails'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install fragment_highlighter-rails
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
#application.css
|
23
|
+
|
24
|
+
@import "bootstrap-sprockets";
|
25
|
+
@import "bootstrap";
|
26
|
+
*= require 'fragment-highlighter'
|
27
|
+
|
28
|
+
#application.js
|
29
|
+
|
30
|
+
//= require jquery
|
31
|
+
//= require bootstrap-sprockets
|
32
|
+
//= require fragment-highlighter/fragment-highlighter.js
|
33
|
+
|
34
|
+
$(function() {
|
35
|
+
let allowedPages = ['/articles/'];
|
36
|
+
new FragmentHighlighter(allowedPages);
|
37
|
+
});
|
38
|
+
|
39
|
+
## Contributing
|
40
|
+
|
41
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/fragment_highlighter-rails.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "fragment_highlighter/rails"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "fragment_highlighter/rails/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "fragment_highlighter-rails"
|
8
|
+
spec.version = FragmentHighlighter::Rails::VERSION
|
9
|
+
spec.authors = ["PhlowerTeam"]
|
10
|
+
spec.email = ["phlowerteam@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{JavaScript UI library for highlighting text fragments on the page and saving ones into localStorage}
|
13
|
+
spec.homepage = "https://github.com/phlowerteam/fragment_highlighter-rails"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.15"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "bootstrap-sass", "~> 3.3.5"
|
25
|
+
spec.add_development_dependency "jquery-rails"
|
26
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
//= require fragment-highlighter/libs/jquery.mark.es6.min.js
|
2
|
+
//= require fragment-highlighter/libs/classes/HView.js
|
3
|
+
//= require fragment-highlighter/libs/classes/HWindowCtrls.js
|
4
|
+
//= require fragment-highlighter/libs/classes/LS.js
|
5
|
+
//= require fragment-highlighter/libs/classes/Marker.js
|
6
|
+
//= require fragment-highlighter/libs/classes/Tools.js
|
7
|
+
//= require fragment-highlighter/libs/classes/UserSettings.js
|
8
|
+
|
9
|
+
class FragmentHighlighter {
|
10
|
+
|
11
|
+
constructor(pages) {
|
12
|
+
FragmentHighlighter.init(pages);
|
13
|
+
}
|
14
|
+
|
15
|
+
static init(allowedPages) {
|
16
|
+
$(function(){
|
17
|
+
if (HView.isSupportedPage(allowedPages)) {
|
18
|
+
HView.renderModeButton();
|
19
|
+
}
|
20
|
+
|
21
|
+
HView.initHighlightWindow();
|
22
|
+
UserSettings.init();
|
23
|
+
|
24
|
+
if (HView.isHModeOn(allowedPages)) {
|
25
|
+
$(document.body).on('click', '.remove-text', function(e){
|
26
|
+
Marker.removeMarked(e.target);
|
27
|
+
});
|
28
|
+
|
29
|
+
$(document.body).bind('mouseup', function(e){
|
30
|
+
Marker.extractFragment();
|
31
|
+
});
|
32
|
+
}
|
33
|
+
});
|
34
|
+
}
|
35
|
+
}
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class HView {
|
2
|
+
|
3
|
+
static isHModeOn(allowedPages) {
|
4
|
+
return (UserSettings.isHMode() && HView.isSupportedPage(allowedPages));
|
5
|
+
}
|
6
|
+
|
7
|
+
static isSupportedPage(allowedPages) {
|
8
|
+
let matcher = new RegExp("(" + allowedPages.join('|') + ")", "g");
|
9
|
+
return matcher.test(window.location.href)
|
10
|
+
}
|
11
|
+
|
12
|
+
static renderModeButton() {
|
13
|
+
// https://www.w3schools.com/howto/howto_css_sidenav_buttons.asp
|
14
|
+
$('body').prepend(`
|
15
|
+
<div id='highlightSidenav' class='sidenav'>
|
16
|
+
<a href='#' id='h-mode' onclick='HWindowCtrls.showHighlightWindow()'>
|
17
|
+
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
|
18
|
+
</a>
|
19
|
+
</div>`);
|
20
|
+
}
|
21
|
+
|
22
|
+
static initHighlightWindow() {
|
23
|
+
$('body').prepend(`
|
24
|
+
<div class="modal fade" id="highlightModal" tabindex="-1" role="dialog" aria-labelledby="highlightModalLabel" aria-hidden="true">
|
25
|
+
<div class="modal-dialog">
|
26
|
+
<div class="modal-content">
|
27
|
+
<div class="modal-header">
|
28
|
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
29
|
+
<h4 class="modal-title" id="myModalLabel">Highlighted Articles</h4>
|
30
|
+
</div>
|
31
|
+
<div class="modal-body" id="marked-items-list">
|
32
|
+
...
|
33
|
+
</div>
|
34
|
+
<div class="modal-footer">
|
35
|
+
<row>
|
36
|
+
<div class="col-md-8">
|
37
|
+
<div class="checkbox">
|
38
|
+
<label><input type="checkbox" id="hmode_checkbox" value="" onclick="HWindowCtrls.turnOnHMode()"> TURN ON Highlighting Mode</label>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
<div class="col-md-4">
|
42
|
+
<button type="button" class="btn btn-primary" onclick='HWindowCtrls.exportJSON()'>Export Settings</button>
|
43
|
+
</div>
|
44
|
+
</row>
|
45
|
+
<br>
|
46
|
+
<br>
|
47
|
+
<row>
|
48
|
+
<div class="col-md-12">
|
49
|
+
<form id="jsonFile" name="jsonFile" enctype="multipart/form-data" method="post">
|
50
|
+
<fieldset>
|
51
|
+
<label class="custom-file">
|
52
|
+
<input type="file" id="fileinput" class="custom-file-input" required>
|
53
|
+
<span class="custom-file-control"></span>
|
54
|
+
</label>
|
55
|
+
<input type='button' class="btn btn-success" id='btnLoad' value='Import Settings' onclick='HWindowCtrls.importJSON();'>
|
56
|
+
</fieldset>
|
57
|
+
</form>
|
58
|
+
</div>
|
59
|
+
</row>
|
60
|
+
</div>
|
61
|
+
<a id="downloadAnchorElem" style="display:none"></a>
|
62
|
+
</div>
|
63
|
+
</div>
|
64
|
+
</div>`);
|
65
|
+
|
66
|
+
$('#highlightModal').modal({ show: false });
|
67
|
+
}
|
68
|
+
}
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class HWindowCtrls {
|
2
|
+
|
3
|
+
static showHighlightWindow(){
|
4
|
+
$('#marked-items-list').html('');
|
5
|
+
let userSettings = LS.uSettings();
|
6
|
+
for (let key in userSettings.articles_titles) {
|
7
|
+
$('#marked-items-list').append(`<span><a href='${key}' target='_blank'>${userSettings.articles_titles[key]}</a> <a href="#" onclick="HWindowCtrls.deleteFragments('${key}')">[Delete]</a></span><br>`);
|
8
|
+
};
|
9
|
+
$('input#hmode_checkbox')[0].checked = userSettings.settings.hmode_is_on;
|
10
|
+
$('#highlightModal').modal();
|
11
|
+
}
|
12
|
+
|
13
|
+
static exportJSON(){
|
14
|
+
let userSettings = LS.uSettings();
|
15
|
+
let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(userSettings));
|
16
|
+
let dlAnchorElem = document.getElementById('downloadAnchorElem');
|
17
|
+
dlAnchorElem.setAttribute("href", dataStr );
|
18
|
+
dlAnchorElem.setAttribute("download", "scene.json");
|
19
|
+
dlAnchorElem.click();
|
20
|
+
}
|
21
|
+
|
22
|
+
static importJSON(){
|
23
|
+
let input, file, fr;
|
24
|
+
|
25
|
+
if (typeof window.FileReader !== 'function') {
|
26
|
+
alert("The file API isn't supported on this browser yet.");
|
27
|
+
return;
|
28
|
+
}
|
29
|
+
|
30
|
+
input = document.getElementById('fileinput');
|
31
|
+
if (!input) {
|
32
|
+
alert("Um, couldn't find the fileinput element.");
|
33
|
+
}
|
34
|
+
else if (!input.files) {
|
35
|
+
alert("This browser doesn't seem to support the `files` property of file inputs.");
|
36
|
+
}
|
37
|
+
else if (!input.files[0]) {
|
38
|
+
alert("Please select a file before clicking 'Load'");
|
39
|
+
}
|
40
|
+
else {
|
41
|
+
file = input.files[0];
|
42
|
+
fr = new FileReader();
|
43
|
+
fr.onload = receivedText;
|
44
|
+
fr.readAsText(file);
|
45
|
+
}
|
46
|
+
|
47
|
+
function receivedText(e) {
|
48
|
+
LS.saveUSettings(JSON.parse(e.target.result));
|
49
|
+
Tools.reloadPage();
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
static turnOnHMode(){
|
54
|
+
let userSettings = LS.uSettings();
|
55
|
+
userSettings.settings.hmode_is_on = $('input#hmode_checkbox')[0].checked;
|
56
|
+
LS.saveUSettings(userSettings);
|
57
|
+
Tools.reloadPage();
|
58
|
+
}
|
59
|
+
|
60
|
+
static deleteFragments(url) {
|
61
|
+
UserSettings.deleteFragments(url);
|
62
|
+
Tools.reloadPage();
|
63
|
+
}
|
64
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class Marker {
|
2
|
+
|
3
|
+
static removeMarked(element){
|
4
|
+
let textElement = $(element).prev();
|
5
|
+
UserSettings.removeFragment($(textElement).text());
|
6
|
+
$(textElement).removeClass('highlight-marked');
|
7
|
+
$(textElement).unmark();
|
8
|
+
$(element).remove();
|
9
|
+
}
|
10
|
+
|
11
|
+
static extractFragment(element){
|
12
|
+
let selection;
|
13
|
+
|
14
|
+
if (window.getSelection) {
|
15
|
+
selection = window.getSelection();
|
16
|
+
} else if (document.selection) {
|
17
|
+
selection = document.selection.createRange();
|
18
|
+
}
|
19
|
+
|
20
|
+
if (selection.toString() !== '') {
|
21
|
+
Marker.saveFragments(selection.toString());
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
static saveFragments(text){
|
26
|
+
let fragments = text.trim().split("\n\n");
|
27
|
+
fragments.forEach( fragment => {
|
28
|
+
if (fragment.length > 0) {
|
29
|
+
UserSettings.saveFragment(fragment);
|
30
|
+
Marker.highlight(fragment.trim());
|
31
|
+
}
|
32
|
+
});
|
33
|
+
}
|
34
|
+
|
35
|
+
static highlight(text){
|
36
|
+
$("body").mark(text, {
|
37
|
+
"className": "highlight-marked",
|
38
|
+
"caseSensitive": true,
|
39
|
+
"separateWordSearch": false,
|
40
|
+
"diacritics": false
|
41
|
+
});
|
42
|
+
|
43
|
+
let highlights = $(".highlight-marked");
|
44
|
+
if (highlights){
|
45
|
+
highlights.each((i, hl) => {
|
46
|
+
let next = $(hl).next();
|
47
|
+
if(next && $(next).attr('class') == 'remove-text'){
|
48
|
+
} else {
|
49
|
+
$('<span class="remove-text">[X]</span>').insertAfter(hl);
|
50
|
+
}
|
51
|
+
})
|
52
|
+
}
|
53
|
+
$(".highlight-marked").css('background-color', 'yellow');
|
54
|
+
$(".remove-text").css('background-color', 'gold');
|
55
|
+
}
|
56
|
+
}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
// userSettings format:
|
2
|
+
// {
|
3
|
+
// articles: {
|
4
|
+
// 'url': [
|
5
|
+
// {
|
6
|
+
// text: 'fragment'
|
7
|
+
// }
|
8
|
+
// ]
|
9
|
+
// },
|
10
|
+
// articles_titles: {
|
11
|
+
// 'url': 'title'
|
12
|
+
// },
|
13
|
+
// settings: {
|
14
|
+
// hmode_is_on: true
|
15
|
+
// }
|
16
|
+
// }
|
17
|
+
|
18
|
+
class UserSettings {
|
19
|
+
|
20
|
+
static init() {
|
21
|
+
let userSettings = LS.uSettings();
|
22
|
+
if (!userSettings){
|
23
|
+
// if (true){ //for debug
|
24
|
+
let userSettings = {
|
25
|
+
articles: {},
|
26
|
+
articles_titles: {},
|
27
|
+
settings:{
|
28
|
+
hmode_is_on: true
|
29
|
+
}
|
30
|
+
};
|
31
|
+
LS.saveUSettings(userSettings);
|
32
|
+
} else {
|
33
|
+
let hModeOn = LS.uSettings().settings.hmode_is_on;
|
34
|
+
if(hModeOn){
|
35
|
+
let articleFragments = userSettings.articles[Tools.href()] || [];
|
36
|
+
articleFragments.forEach(fragment => {
|
37
|
+
Marker.highlight(fragment.text);
|
38
|
+
});
|
39
|
+
}
|
40
|
+
};
|
41
|
+
}
|
42
|
+
|
43
|
+
static isHMode() {
|
44
|
+
let mode;
|
45
|
+
try { mode = LS.uSettings().settings.hmode_is_on } catch(e) {};
|
46
|
+
return mode;
|
47
|
+
}
|
48
|
+
|
49
|
+
static isNotPresent(text){
|
50
|
+
let article = LS.uSettings().articles[Tools.href()];
|
51
|
+
return (article && article.findIndex(i => i.text.trim() === text.trim()) < 0);
|
52
|
+
}
|
53
|
+
|
54
|
+
static removeFragment(text){
|
55
|
+
let userSettings = LS.uSettings();
|
56
|
+
let articleFragments = userSettings.articles[Tools.href()] || [];
|
57
|
+
userSettings.articles[Tools.href()].forEach(((fragment, i) => {
|
58
|
+
if (fragment.text.trim() == text.trim()){
|
59
|
+
userSettings.articles[Tools.href()].splice(i, 1);
|
60
|
+
LS.saveUSettings(userSettings);
|
61
|
+
return;
|
62
|
+
}
|
63
|
+
}));
|
64
|
+
}
|
65
|
+
|
66
|
+
static saveFragment(text){
|
67
|
+
let userSettings = LS.uSettings();
|
68
|
+
userSettings.articles[Tools.href()] = userSettings.articles[Tools.href()] || [];
|
69
|
+
userSettings.articles_titles = userSettings.articles_titles || {};
|
70
|
+
|
71
|
+
if (UserSettings.isNotPresent(text)) {
|
72
|
+
userSettings.articles[Tools.href()].push({
|
73
|
+
text: text.trim()
|
74
|
+
});
|
75
|
+
}
|
76
|
+
userSettings.articles_titles[Tools.href()] = $('h1').text();
|
77
|
+
LS.saveUSettings(userSettings);
|
78
|
+
}
|
79
|
+
|
80
|
+
static deleteFragments(url) {
|
81
|
+
let userSettings = LS.uSettings();
|
82
|
+
delete userSettings.articles[url];
|
83
|
+
delete userSettings.articles_titles[url];
|
84
|
+
LS.saveUSettings(userSettings);
|
85
|
+
}
|
86
|
+
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
/*!***************************************************
|
2
|
+
* mark.js v8.11.0
|
3
|
+
* https://github.com/julmot/mark.js
|
4
|
+
* Copyright (c) 2014–2017, Julian Motz
|
5
|
+
* Released under the MIT license https://git.io/vwTVl
|
6
|
+
*****************************************************/
|
7
|
+
"use strict";((factory,window,document)=>{if(typeof define==="function"&&define.amd){define(["jquery"],jQuery=>{return factory(window,document,jQuery);});}else if(typeof module==="object"&&module.exports){module.exports=factory(window,document,require("jquery"));}else{factory(window,document,jQuery);}})((window,document,$)=>{class Mark{constructor(ctx){this.ctx=ctx;this.ie=false;const ua=window.navigator.userAgent;if(ua.indexOf("MSIE")>-1||ua.indexOf("Trident")>-1){this.ie=true;}}set opt(val){this._opt=Object.assign({},{"element":"","className":"","exclude":[],"iframes":false,"iframesTimeout":5000,"separateWordSearch":true,"diacritics":true,"synonyms":{},"accuracy":"partially","acrossElements":false,"caseSensitive":false,"ignoreJoiners":false,"ignoreGroups":0,"ignorePunctuation":[],"wildcards":"disabled","each":()=>{},"noMatch":()=>{},"filter":()=>true,"done":()=>{},"debug":false,"log":window.console},val);}get opt(){return this._opt;}get iterator(){return new DOMIterator(this.ctx,this.opt.iframes,this.opt.exclude,this.opt.iframesTimeout);}log(msg,level="debug"){const log=this.opt.log;if(!this.opt.debug){return;}if(typeof log==="object"&&typeof log[level]==="function"){log[level](`mark.js: ${msg}`);}}escapeStr(str){return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&");}createRegExp(str){if(this.opt.wildcards!=="disabled"){str=this.setupWildcardsRegExp(str);}str=this.escapeStr(str);if(Object.keys(this.opt.synonyms).length){str=this.createSynonymsRegExp(str);}if(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length){str=this.setupIgnoreJoinersRegExp(str);}if(this.opt.diacritics){str=this.createDiacriticsRegExp(str);}str=this.createMergedBlanksRegExp(str);if(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length){str=this.createJoinersRegExp(str);}if(this.opt.wildcards!=="disabled"){str=this.createWildcardsRegExp(str);}str=this.createAccuracyRegExp(str);return str;}createSynonymsRegExp(str){const syn=this.opt.synonyms,sens=this.opt.caseSensitive?"":"i",joinerPlaceholder=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\u0000":"";for(let index in syn){if(syn.hasOwnProperty(index)){const value=syn[index],k1=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(index):this.escapeStr(index),k2=this.opt.wildcards!=="disabled"?this.setupWildcardsRegExp(value):this.escapeStr(value);if(k1!==""&&k2!==""){str=str.replace(new RegExp(`(${k1}|${k2})`,`gm${sens}`),joinerPlaceholder+`(${this.processSynomyms(k1)}|`+`${this.processSynomyms(k2)})`+joinerPlaceholder);}}}return str;}processSynomyms(str){if(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length){str=this.setupIgnoreJoinersRegExp(str);}return str;}setupWildcardsRegExp(str){str=str.replace(/(?:\\)*\?/g,val=>{return val.charAt(0)==="\\"?"?":"\u0001";});return str.replace(/(?:\\)*\*/g,val=>{return val.charAt(0)==="\\"?"*":"\u0002";});}createWildcardsRegExp(str){let spaces=this.opt.wildcards==="withSpaces";return str.replace(/\u0001/g,spaces?"[\\S\\s]?":"\\S?").replace(/\u0002/g,spaces?"[\\S\\s]*?":"\\S*");}setupIgnoreJoinersRegExp(str){return str.replace(/[^(|)\\]/g,(val,indx,original)=>{let nextChar=original.charAt(indx+1);if(/[(|)\\]/.test(nextChar)||nextChar===""){return val;}else{return val+"\u0000";}});}createJoinersRegExp(str){let joiner=[];const ignorePunctuation=this.opt.ignorePunctuation;if(Array.isArray(ignorePunctuation)&&ignorePunctuation.length){joiner.push(this.escapeStr(ignorePunctuation.join("")));}if(this.opt.ignoreJoiners){joiner.push("\\u00ad\\u200b\\u200c\\u200d");}return joiner.length?str.split(/\u0000+/).join(`[${joiner.join("")}]*`):str;}createDiacriticsRegExp(str){const sens=this.opt.caseSensitive?"":"i",dct=this.opt.caseSensitive?["aàáâãäåāąă","AÀÁÂÃÄÅĀĄĂ","cçćč","CÇĆČ","dđď","DĐĎ","eèéêëěēę","EÈÉÊËĚĒĘ","iìíîïī","IÌÍÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóôõöøō","OÒÓÔÕÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúûüůū","UÙÚÛÜŮŪ","yÿý","YŸÝ","zžżź","ZŽŻŹ"]:["aàáâãäåāąăAÀÁÂÃÄÅĀĄĂ","cçćčCÇĆČ","dđďDĐĎ","eèéêëěēęEÈÉÊËĚĒĘ","iìíîïīIÌÍÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóôõöøōOÒÓÔÕÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúûüůūUÙÚÛÜŮŪ","yÿýYŸÝ","zžżźZŽŻŹ"];let handled=[];str.split("").forEach(ch=>{dct.every(dct=>{if(dct.indexOf(ch)!==-1){if(handled.indexOf(dct)>-1){return false;}str=str.replace(new RegExp(`[${dct}]`,`gm${sens}`),`[${dct}]`);handled.push(dct);}return true;});});return str;}createMergedBlanksRegExp(str){return str.replace(/[\s]+/gmi,"[\\s]+");}createAccuracyRegExp(str){const chars=`!"#$%&'()*+,-./:;<=>?@[\\]^_\`{|}~¡¿`;let acc=this.opt.accuracy,val=typeof acc==="string"?acc:acc.value,ls=typeof acc==="string"?[]:acc.limiters,lsJoin="";ls.forEach(limiter=>{lsJoin+=`|${this.escapeStr(limiter)}`;});switch(val){case"partially":default:return`()(${str})`;case"complementary":lsJoin="\\s"+(lsJoin?lsJoin:this.escapeStr(chars));return`()([^${lsJoin}]*${str}[^${lsJoin}]*)`;case"exactly":return`(^|\\s${lsJoin})(${str})(?=$|\\s${lsJoin})`;}}getSeparatedKeywords(sv){let stack=[];sv.forEach(kw=>{if(!this.opt.separateWordSearch){if(kw.trim()&&stack.indexOf(kw)===-1){stack.push(kw);}}else{kw.split(" ").forEach(kwSplitted=>{if(kwSplitted.trim()&&stack.indexOf(kwSplitted)===-1){stack.push(kwSplitted);}});}});return{"keywords":stack.sort((a,b)=>{return b.length-a.length;}),"length":stack.length};}isNumeric(value){return Number(parseFloat(value))==value;}checkRanges(array){if(!Array.isArray(array)||Object.prototype.toString.call(array[0])!=="[object Object]"){this.log("markRanges() will only accept an array of objects");this.opt.noMatch(array);return[];}const stack=[];let last=0;array.sort((a,b)=>{return a.start-b.start;}).forEach(item=>{let{start,end,valid}=this.callNoMatchOnInvalidRanges(item,last);if(valid){item.start=start;item.length=end-start;stack.push(item);last=end;}});return stack;}callNoMatchOnInvalidRanges(range,last){let start,end,valid=false;if(range&&typeof range.start!=="undefined"){start=parseInt(range.start,10);end=start+parseInt(range.length,10);if(this.isNumeric(range.start)&&this.isNumeric(range.length)&&end-last>0&&end-start>0){valid=true;}else{this.log(`Ignoring invalid or overlapping range: `+`${JSON.stringify(range)}`);this.opt.noMatch(range);}}else{this.log(`Ignoring invalid range: ${JSON.stringify(range)}`);this.opt.noMatch(range);}return{start:start,end:end,valid:valid};}checkWhitespaceRanges(range,originalLength,string){let end,valid=true,max=string.length,offset=originalLength-max,start=parseInt(range.start,10)-offset;start=start>max?max:start;end=start+parseInt(range.length,10);if(end>max){end=max;this.log(`End range automatically set to the max value of ${max}`);}if(start<0||end-start<0||start>max||end>max){valid=false;this.log(`Invalid range: ${JSON.stringify(range)}`);this.opt.noMatch(range);}else if(string.substring(start,end).replace(/\s+/g,"")===""){valid=false;this.log("Skipping whitespace only range: "+JSON.stringify(range));this.opt.noMatch(range);}return{start:start,end:end,valid:valid};}getTextNodes(cb){let val="",nodes=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,node=>{nodes.push({start:val.length,end:(val+=node.textContent).length,node});},node=>{if(this.matchesExclude(node.parentNode)){return NodeFilter.FILTER_REJECT;}else{return NodeFilter.FILTER_ACCEPT;}},()=>{cb({value:val,nodes:nodes});});}matchesExclude(el){return DOMIterator.matches(el,this.opt.exclude.concat(["script","style","title","head","html"]));}wrapRangeInTextNode(node,start,end){const hEl=!this.opt.element?"mark":this.opt.element,startNode=node.splitText(start),ret=startNode.splitText(end-start);let repl=document.createElement(hEl);repl.setAttribute("data-markjs","true");if(this.opt.className){repl.setAttribute("class",this.opt.className);}repl.textContent=startNode.textContent;startNode.parentNode.replaceChild(repl,startNode);return ret;}wrapRangeInMappedTextNode(dict,start,end,filterCb,eachCb){dict.nodes.every((n,i)=>{const sibl=dict.nodes[i+1];if(typeof sibl==="undefined"||sibl.start>start){if(!filterCb(n.node)){return false;}const s=start-n.start,e=(end>n.end?n.end:end)-n.start,startStr=dict.value.substr(0,n.start),endStr=dict.value.substr(e+n.start);n.node=this.wrapRangeInTextNode(n.node,s,e);dict.value=startStr+endStr;dict.nodes.forEach((k,j)=>{if(j>=i){if(dict.nodes[j].start>0&&j!==i){dict.nodes[j].start-=e;}dict.nodes[j].end-=e;}});end-=e;eachCb(n.node.previousSibling,n.start);if(end>n.end){start=n.end;}else{return false;}}return true;});}wrapMatches(regex,ignoreGroups,filterCb,eachCb,endCb){const matchIdx=ignoreGroups===0?0:ignoreGroups+1;this.getTextNodes(dict=>{dict.nodes.forEach(node=>{node=node.node;let match;while((match=regex.exec(node.textContent))!==null&&match[matchIdx]!==""){if(!filterCb(match[matchIdx],node)){continue;}let pos=match.index;if(matchIdx!==0){for(let i=1;i<matchIdx;i++){pos+=match[i].length;}}node=this.wrapRangeInTextNode(node,pos,pos+match[matchIdx].length);eachCb(node.previousSibling);regex.lastIndex=0;}});endCb();});}wrapMatchesAcrossElements(regex,ignoreGroups,filterCb,eachCb,endCb){const matchIdx=ignoreGroups===0?0:ignoreGroups+1;this.getTextNodes(dict=>{let match;while((match=regex.exec(dict.value))!==null&&match[matchIdx]!==""){let start=match.index;if(matchIdx!==0){for(let i=1;i<matchIdx;i++){start+=match[i].length;}}const end=start+match[matchIdx].length;this.wrapRangeInMappedTextNode(dict,start,end,node=>{return filterCb(match[matchIdx],node);},(node,lastIndex)=>{regex.lastIndex=lastIndex;eachCb(node);});}endCb();});}wrapRangeFromIndex(ranges,filterCb,eachCb,endCb){this.getTextNodes(dict=>{const originalLength=dict.value.length;ranges.forEach((range,counter)=>{let{start,end,valid}=this.checkWhitespaceRanges(range,originalLength,dict.value);if(valid){this.wrapRangeInMappedTextNode(dict,start,end,node=>{return filterCb(node,range,dict.value.substring(start,end),counter);},node=>{eachCb(node,range);});}});endCb();});}unwrapMatches(node){const parent=node.parentNode;let docFrag=document.createDocumentFragment();while(node.firstChild){docFrag.appendChild(node.removeChild(node.firstChild));}parent.replaceChild(docFrag,node);if(!this.ie){parent.normalize();}else{this.normalizeTextNode(parent);}}normalizeTextNode(node){if(!node){return;}if(node.nodeType===3){while(node.nextSibling&&node.nextSibling.nodeType===3){node.nodeValue+=node.nextSibling.nodeValue;node.parentNode.removeChild(node.nextSibling);}}else{this.normalizeTextNode(node.firstChild);}this.normalizeTextNode(node.nextSibling);}markRegExp(regexp,opt){this.opt=opt;this.log(`Searching with expression "${regexp}"`);let totalMatches=0,fn="wrapMatches";const eachCb=element=>{totalMatches++;this.opt.each(element);};if(this.opt.acrossElements){fn="wrapMatchesAcrossElements";}this[fn](regexp,this.opt.ignoreGroups,(match,node)=>{return this.opt.filter(node,match,totalMatches);},eachCb,()=>{if(totalMatches===0){this.opt.noMatch(regexp);}this.opt.done(totalMatches);});}mark(sv,opt){this.opt=opt;let totalMatches=0,fn="wrapMatches";const{keywords:kwArr,length:kwArrLen}=this.getSeparatedKeywords(typeof sv==="string"?[sv]:sv),sens=this.opt.caseSensitive?"":"i",handler=kw=>{let regex=new RegExp(this.createRegExp(kw),`gm${sens}`),matches=0;this.log(`Searching with expression "${regex}"`);this[fn](regex,1,(term,node)=>{return this.opt.filter(node,kw,totalMatches,matches);},element=>{matches++;totalMatches++;this.opt.each(element);},()=>{if(matches===0){this.opt.noMatch(kw);}if(kwArr[kwArrLen-1]===kw){this.opt.done(totalMatches);}else{handler(kwArr[kwArr.indexOf(kw)+1]);}});};if(this.opt.acrossElements){fn="wrapMatchesAcrossElements";}if(kwArrLen===0){this.opt.done(totalMatches);}else{handler(kwArr[0]);}}markRanges(rawRanges,opt){this.opt=opt;let totalMatches=0,ranges=this.checkRanges(rawRanges);if(ranges&&ranges.length){this.log("Starting to mark with the following ranges: "+JSON.stringify(ranges));this.wrapRangeFromIndex(ranges,(node,range,match,counter)=>{return this.opt.filter(node,range,match,counter);},(element,range)=>{totalMatches++;this.opt.each(element,range);},()=>{this.opt.done(totalMatches);});}else{this.opt.done(totalMatches);}}unmark(opt){this.opt=opt;let sel=this.opt.element?this.opt.element:"*";sel+="[data-markjs]";if(this.opt.className){sel+=`.${this.opt.className}`;}this.log(`Removal selector "${sel}"`);this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT,node=>{this.unwrapMatches(node);},node=>{const matchesSel=DOMIterator.matches(node,sel),matchesExclude=this.matchesExclude(node);if(!matchesSel||matchesExclude){return NodeFilter.FILTER_REJECT;}else{return NodeFilter.FILTER_ACCEPT;}},this.opt.done);}}class DOMIterator{constructor(ctx,iframes=true,exclude=[],iframesTimeout=5000){this.ctx=ctx;this.iframes=iframes;this.exclude=exclude;this.iframesTimeout=iframesTimeout;}static matches(element,selector){const selectors=typeof selector==="string"?[selector]:selector,fn=element.matches||element.matchesSelector||element.msMatchesSelector||element.mozMatchesSelector||element.oMatchesSelector||element.webkitMatchesSelector;if(fn){let match=false;selectors.every(sel=>{if(fn.call(element,sel)){match=true;return false;}return true;});return match;}else{return false;}}getContexts(){let ctx,filteredCtx=[];if(typeof this.ctx==="undefined"||!this.ctx){ctx=[];}else if(NodeList.prototype.isPrototypeOf(this.ctx)){ctx=Array.prototype.slice.call(this.ctx);}else if(Array.isArray(this.ctx)){ctx=this.ctx;}else if(typeof this.ctx==="string"){ctx=Array.prototype.slice.call(document.querySelectorAll(this.ctx));}else{ctx=[this.ctx];}ctx.forEach(ctx=>{const isDescendant=filteredCtx.filter(contexts=>{return contexts.contains(ctx);}).length>0;if(filteredCtx.indexOf(ctx)===-1&&!isDescendant){filteredCtx.push(ctx);}});return filteredCtx;}getIframeContents(ifr,successFn,errorFn=()=>{}){let doc;try{const ifrWin=ifr.contentWindow;doc=ifrWin.document;if(!ifrWin||!doc){throw new Error("iframe inaccessible");}}catch(e){errorFn();}if(doc){successFn(doc);}}isIframeBlank(ifr){const bl="about:blank",src=ifr.getAttribute("src").trim(),href=ifr.contentWindow.location.href;return href===bl&&src!==bl&&src;}observeIframeLoad(ifr,successFn,errorFn){let called=false,tout=null;const listener=()=>{if(called){return;}called=true;clearTimeout(tout);try{if(!this.isIframeBlank(ifr)){ifr.removeEventListener("load",listener);this.getIframeContents(ifr,successFn,errorFn);}}catch(e){errorFn();}};ifr.addEventListener("load",listener);tout=setTimeout(listener,this.iframesTimeout);}onIframeReady(ifr,successFn,errorFn){try{if(ifr.contentWindow.document.readyState==="complete"){if(this.isIframeBlank(ifr)){this.observeIframeLoad(ifr,successFn,errorFn);}else{this.getIframeContents(ifr,successFn,errorFn);}}else{this.observeIframeLoad(ifr,successFn,errorFn);}}catch(e){errorFn();}}waitForIframes(ctx,done){let eachCalled=0;this.forEachIframe(ctx,()=>true,ifr=>{eachCalled++;this.waitForIframes(ifr.querySelector("html"),()=>{if(! --eachCalled){done();}});},handled=>{if(!handled){done();}});}forEachIframe(ctx,filter,each,end=()=>{}){let ifr=ctx.querySelectorAll("iframe"),open=ifr.length,handled=0;ifr=Array.prototype.slice.call(ifr);const checkEnd=()=>{if(--open<=0){end(handled);}};if(!open){checkEnd();}ifr.forEach(ifr=>{if(DOMIterator.matches(ifr,this.exclude)){checkEnd();}else{this.onIframeReady(ifr,con=>{if(filter(ifr)){handled++;each(con);}checkEnd();},checkEnd);}});}createIterator(ctx,whatToShow,filter){return document.createNodeIterator(ctx,whatToShow,filter,false);}createInstanceOnIframe(contents){return new DOMIterator(contents.querySelector("html"),this.iframes);}compareNodeIframe(node,prevNode,ifr){const compCurr=node.compareDocumentPosition(ifr),prev=Node.DOCUMENT_POSITION_PRECEDING;if(compCurr&prev){if(prevNode!==null){const compPrev=prevNode.compareDocumentPosition(ifr),after=Node.DOCUMENT_POSITION_FOLLOWING;if(compPrev&after){return true;}}else{return true;}}return false;}getIteratorNode(itr){const prevNode=itr.previousNode();let node;if(prevNode===null){node=itr.nextNode();}else{node=itr.nextNode()&&itr.nextNode();}return{prevNode,node};}checkIframeFilter(node,prevNode,currIfr,ifr){let key=false,handled=false;ifr.forEach((ifrDict,i)=>{if(ifrDict.val===currIfr){key=i;handled=ifrDict.handled;}});if(this.compareNodeIframe(node,prevNode,currIfr)){if(key===false&&!handled){ifr.push({val:currIfr,handled:true});}else if(key!==false&&!handled){ifr[key].handled=true;}return true;}if(key===false){ifr.push({val:currIfr,handled:false});}return false;}handleOpenIframes(ifr,whatToShow,eCb,fCb){ifr.forEach(ifrDict=>{if(!ifrDict.handled){this.getIframeContents(ifrDict.val,con=>{this.createInstanceOnIframe(con).forEachNode(whatToShow,eCb,fCb);});}});}iterateThroughNodes(whatToShow,ctx,eachCb,filterCb,doneCb){const itr=this.createIterator(ctx,whatToShow,filterCb);let ifr=[],elements=[],node,prevNode,retrieveNodes=()=>{({prevNode,node}=this.getIteratorNode(itr));return node;};while(retrieveNodes()){if(this.iframes){this.forEachIframe(ctx,currIfr=>{return this.checkIframeFilter(node,prevNode,currIfr,ifr);},con=>{this.createInstanceOnIframe(con).forEachNode(whatToShow,ifrNode=>elements.push(ifrNode),filterCb);});}elements.push(node);}elements.forEach(node=>{eachCb(node);});if(this.iframes){this.handleOpenIframes(ifr,whatToShow,eachCb,filterCb);}doneCb();}forEachNode(whatToShow,each,filter,done=()=>{}){const contexts=this.getContexts();let open=contexts.length;if(!open){done();}contexts.forEach(ctx=>{const ready=()=>{this.iterateThroughNodes(whatToShow,ctx,each,filter,()=>{if(--open<=0){done();}});};if(this.iframes){this.waitForIframes(ctx,ready);}else{ready();}});}}$.fn.mark=function(sv,opt){new Mark(this.get()).mark(sv,opt);return this;};$.fn.markRegExp=function(regexp,opt){new Mark(this.get()).markRegExp(regexp,opt);return this;};$.fn.markRanges=function(ranges,opt){new Mark(this.get()).markRanges(ranges,opt);return this;};$.fn.unmark=function(opt){new Mark(this.get()).unmark(opt);return this;};return $;},window,document);
|
@@ -0,0 +1,26 @@
|
|
1
|
+
/* Style the links inside the sidenav */
|
2
|
+
#highlightSidenav a {
|
3
|
+
position: fixed; /* Position them relative to the browser window */
|
4
|
+
left: -15px; /* Position them outside of the screen */
|
5
|
+
transition: 0.3s; /* Add transition on hover */
|
6
|
+
padding: 15px; /* 15px padding */
|
7
|
+
width: 50px; /* Set a specific width */
|
8
|
+
text-decoration: none; /* Remove underline */
|
9
|
+
font-size: 20px; /* Increase font size */
|
10
|
+
color: white; /* White text color */
|
11
|
+
border-radius: 0 5px 5px 0; /* Rounded corners on the top right and bottom right side */
|
12
|
+
}
|
13
|
+
|
14
|
+
#highlightSidenav a:hover {
|
15
|
+
left: 0; /* On mouse-over, make the elements appear as they should */
|
16
|
+
}
|
17
|
+
|
18
|
+
#highlightSidenav a, a:visited {
|
19
|
+
color: #D3D3D3 !important;
|
20
|
+
}
|
21
|
+
|
22
|
+
/* The about link: 20px from the top with a green background */
|
23
|
+
#h-mode {
|
24
|
+
top: 50%;
|
25
|
+
background-color: #4CAF50;
|
26
|
+
}
|
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fragment_highlighter-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- PhlowerTeam
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-11-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.15'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bootstrap-sass
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.3.5
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.3.5
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: jquery-rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- phlowerteam@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE
|
79
|
+
- README.md
|
80
|
+
- Rakefile
|
81
|
+
- bin/console
|
82
|
+
- bin/setup
|
83
|
+
- fragment_highlighter-rails.gemspec
|
84
|
+
- lib/fragment_highlighter/rails.rb
|
85
|
+
- lib/fragment_highlighter/rails/version.rb
|
86
|
+
- vendor/assets/javascripts/fragment-highlighter/fragment-highlighter.js
|
87
|
+
- vendor/assets/javascripts/fragment-highlighter/libs/classes/HView.js
|
88
|
+
- vendor/assets/javascripts/fragment-highlighter/libs/classes/HWindowCtrls.js
|
89
|
+
- vendor/assets/javascripts/fragment-highlighter/libs/classes/LS.js
|
90
|
+
- vendor/assets/javascripts/fragment-highlighter/libs/classes/Marker.js
|
91
|
+
- vendor/assets/javascripts/fragment-highlighter/libs/classes/Tools.js
|
92
|
+
- vendor/assets/javascripts/fragment-highlighter/libs/classes/UserSettings.js
|
93
|
+
- vendor/assets/javascripts/fragment-highlighter/libs/jquery.mark.es6.min.js
|
94
|
+
- vendor/assets/stylesheets/fragment-highlighter.css
|
95
|
+
homepage: https://github.com/phlowerteam/fragment_highlighter-rails
|
96
|
+
licenses: []
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.6.13
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: JavaScript UI library for highlighting text fragments on the page and saving
|
118
|
+
ones into localStorage
|
119
|
+
test_files: []
|