mirror of
https://github.com/hkalexling/Mango.git
synced 2026-05-01 00:00:55 -04:00
Compare commits
7 Commits
5daeac72cb
...
98a0c54499
| Author | SHA1 | Date | |
|---|---|---|---|
| 98a0c54499 | |||
| cb3df432d0 | |||
| 47af6ee284 | |||
| 9fe269ab13 | |||
| 75a30a88e0 | |||
| 5b58d8ac59 | |||
| 30d5ad0c19 |
@@ -12,3 +12,4 @@ Layout/LineLength:
|
|||||||
MaxLength: 80
|
MaxLength: 80
|
||||||
Excluded:
|
Excluded:
|
||||||
- src/routes/api.cr
|
- src/routes/api.cr
|
||||||
|
- spec/plugin_spec.cr
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const component = () => {
|
const component = () => {
|
||||||
return {
|
return {
|
||||||
plugins: [],
|
plugins: [],
|
||||||
|
subscribable: false,
|
||||||
info: undefined,
|
info: undefined,
|
||||||
pid: undefined,
|
pid: undefined,
|
||||||
chapters: undefined, // undefined: not searched yet, []: empty
|
chapters: undefined, // undefined: not searched yet, []: empty
|
||||||
@@ -60,6 +61,7 @@ const component = () => {
|
|||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (!data.success) throw new Error(data.error);
|
if (!data.success) throw new Error(data.error);
|
||||||
this.info = data.info;
|
this.info = data.info;
|
||||||
|
this.subscribable = data.subscribable;
|
||||||
this.pid = pid;
|
this.pid = pid;
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
@@ -70,6 +72,9 @@ const component = () => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
pluginChanged() {
|
pluginChanged() {
|
||||||
|
this.manga = undefined;
|
||||||
|
this.chapters = undefined;
|
||||||
|
this.mid = undefined;
|
||||||
this.loadPlugin(this.pid);
|
this.loadPlugin(this.pid);
|
||||||
localStorage.setItem("plugin", this.pid);
|
localStorage.setItem("plugin", this.pid);
|
||||||
},
|
},
|
||||||
@@ -140,6 +145,7 @@ const component = () => {
|
|||||||
if (!query) return;
|
if (!query) return;
|
||||||
|
|
||||||
this.manga = undefined;
|
this.manga = undefined;
|
||||||
|
this.mid = undefined;
|
||||||
if (this.info.version === 1) {
|
if (this.info.version === 1) {
|
||||||
this.searchChapters(query);
|
this.searchChapters(query);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"id": "test",
|
||||||
|
"title": "Test Plugin",
|
||||||
|
"placeholder": "placeholder",
|
||||||
|
"wait_seconds": 1
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
require "./spec_helper"
|
||||||
|
|
||||||
|
describe Plugin do
|
||||||
|
describe "helper functions" do
|
||||||
|
it "mango.text" do
|
||||||
|
with_plugin do |plugin|
|
||||||
|
res = plugin.eval <<-JS
|
||||||
|
mango.text('<a href="https://github.com">Click Me<a>');
|
||||||
|
JS
|
||||||
|
res.should eq "Click Me"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "mango.text returns empty string when no text" do
|
||||||
|
with_plugin do |plugin|
|
||||||
|
res = plugin.eval <<-JS
|
||||||
|
mango.text('<img src="https://github.com" />');
|
||||||
|
JS
|
||||||
|
res.should eq ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "mango.css" do
|
||||||
|
with_plugin do |plugin|
|
||||||
|
res = plugin.eval <<-JS
|
||||||
|
mango.css('<ul><li class="test">A</li><li class="test">B</li><li>C</li></ul>', 'li.test');
|
||||||
|
|
||||||
|
JS
|
||||||
|
res.should eq ["<li class=\"test\">A</li>", "<li class=\"test\">B</li>"]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "mango.css returns empty array when no match" do
|
||||||
|
with_plugin do |plugin|
|
||||||
|
res = plugin.eval <<-JS
|
||||||
|
mango.css('<ul><li class="test">A</li><li class="test">B</li><li>C</li></ul>', 'li.noclass');
|
||||||
|
JS
|
||||||
|
res.should eq [] of String
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "mango.attribute" do
|
||||||
|
with_plugin do |plugin|
|
||||||
|
res = plugin.eval <<-JS
|
||||||
|
mango.attribute('<a href="https://github.com">Click Me<a>', 'href');
|
||||||
|
JS
|
||||||
|
res.should eq "https://github.com"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "mango.attribute returns undefined when no match" do
|
||||||
|
with_plugin do |plugin|
|
||||||
|
res = plugin.eval <<-JS
|
||||||
|
mango.attribute('<div />', 'href') === undefined;
|
||||||
|
JS
|
||||||
|
res.should be_true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# https://github.com/hkalexling/Mango/issues/320
|
||||||
|
it "mango.attribute handles tags in attribute values" do
|
||||||
|
with_plugin do |plugin|
|
||||||
|
res = plugin.eval <<-JS
|
||||||
|
mango.attribute('<div data-a="<img />" data-b="test" />', 'data-b');
|
||||||
|
JS
|
||||||
|
res.should eq "test"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -3,6 +3,7 @@ require "../src/queue"
|
|||||||
require "../src/server"
|
require "../src/server"
|
||||||
require "../src/config"
|
require "../src/config"
|
||||||
require "../src/main_fiber"
|
require "../src/main_fiber"
|
||||||
|
require "../src/plugin/plugin"
|
||||||
|
|
||||||
class State
|
class State
|
||||||
@@hash = {} of String => String
|
@@hash = {} of String => String
|
||||||
@@ -54,3 +55,10 @@ def with_storage
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_plugin
|
||||||
|
with_default_config do
|
||||||
|
plugin = Plugin.new "test", "spec/asset/plugins"
|
||||||
|
yield plugin
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class Logger
|
|||||||
Log.setup do |c|
|
Log.setup do |c|
|
||||||
c.bind "*", @@severity, @backend
|
c.bind "*", @@severity, @backend
|
||||||
c.bind "db.*", :error, @backend
|
c.bind "db.*", :error, @backend
|
||||||
|
c.bind "duktape", :none, @backend
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+30
-9
@@ -105,9 +105,10 @@ class Plugin
|
|||||||
getter js_path = ""
|
getter js_path = ""
|
||||||
getter storage_path = ""
|
getter storage_path = ""
|
||||||
|
|
||||||
def self.build_info_ary
|
def self.build_info_ary(dir : String? = nil)
|
||||||
@@info_ary.clear
|
@@info_ary.clear
|
||||||
dir = Config.current.plugin_path
|
dir ||= Config.current.plugin_path
|
||||||
|
|
||||||
Dir.mkdir_p dir unless Dir.exists? dir
|
Dir.mkdir_p dir unless Dir.exists? dir
|
||||||
|
|
||||||
Dir.each_child dir do |f|
|
Dir.each_child dir do |f|
|
||||||
@@ -160,8 +161,8 @@ class Plugin
|
|||||||
list.save
|
list.save
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize(id : String)
|
def initialize(id : String, dir : String? = nil)
|
||||||
Plugin.build_info_ary
|
Plugin.build_info_ary dir
|
||||||
|
|
||||||
@info = @@info_ary.find &.id.== id
|
@info = @@info_ary.find &.id.== id
|
||||||
if @info.nil?
|
if @info.nil?
|
||||||
@@ -223,6 +224,10 @@ class Plugin
|
|||||||
raise Error.new "Missing required fields in the Page type"
|
raise Error.new "Missing required fields in the Page type"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def can_subscribe? : Bool
|
||||||
|
info.version > 1 && eval_exists?("newChapters")
|
||||||
|
end
|
||||||
|
|
||||||
def search_manga(query : String)
|
def search_manga(query : String)
|
||||||
if info.version == 1
|
if info.version == 1
|
||||||
raise Error.new "Manga searching is only available for plugins " \
|
raise Error.new "Manga searching is only available for plugins " \
|
||||||
@@ -315,7 +320,7 @@ class Plugin
|
|||||||
json
|
json
|
||||||
end
|
end
|
||||||
|
|
||||||
private def eval(str)
|
def eval(str)
|
||||||
@rt.eval str
|
@rt.eval str
|
||||||
rescue e : Duktape::SyntaxError
|
rescue e : Duktape::SyntaxError
|
||||||
raise SyntaxError.new e.message
|
raise SyntaxError.new e.message
|
||||||
@@ -327,6 +332,15 @@ class Plugin
|
|||||||
JSON.parse eval(str).as String
|
JSON.parse eval(str).as String
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private def eval_exists?(str) : Bool
|
||||||
|
@rt.eval str
|
||||||
|
true
|
||||||
|
rescue e : Duktape::ReferenceError
|
||||||
|
false
|
||||||
|
rescue e : Duktape::Error
|
||||||
|
raise Error.new e.message
|
||||||
|
end
|
||||||
|
|
||||||
private def def_helper_functions(sbx)
|
private def def_helper_functions(sbx)
|
||||||
sbx.push_object
|
sbx.push_object
|
||||||
|
|
||||||
@@ -435,9 +449,15 @@ class Plugin
|
|||||||
env = Duktape::Sandbox.new ptr
|
env = Duktape::Sandbox.new ptr
|
||||||
html = env.require_string 0
|
html = env.require_string 0
|
||||||
|
|
||||||
str = XML.parse(html).inner_text
|
begin
|
||||||
|
parser = Myhtml::Parser.new html
|
||||||
|
str = parser.body!.children.first.inner_text
|
||||||
|
|
||||||
|
env.push_string str
|
||||||
|
rescue
|
||||||
|
env.push_string ""
|
||||||
|
end
|
||||||
|
|
||||||
env.push_string str
|
|
||||||
env.call_success
|
env.call_success
|
||||||
end
|
end
|
||||||
sbx.put_prop_string -2, "text"
|
sbx.put_prop_string -2, "text"
|
||||||
@@ -448,8 +468,9 @@ class Plugin
|
|||||||
name = env.require_string 1
|
name = env.require_string 1
|
||||||
|
|
||||||
begin
|
begin
|
||||||
attr = XML.parse(html).first_element_child.not_nil![name]
|
parser = Myhtml::Parser.new html
|
||||||
env.push_string attr
|
attr = parser.body!.children.first.attribute_by name
|
||||||
|
env.push_string attr.not_nil!
|
||||||
rescue
|
rescue
|
||||||
env.push_undefined
|
env.push_undefined
|
||||||
end
|
end
|
||||||
|
|||||||
+4
-2
@@ -871,13 +871,15 @@ struct APIRouter
|
|||||||
"version" => Int32,
|
"version" => Int32,
|
||||||
"settings" => {} of String => String,
|
"settings" => {} of String => String,
|
||||||
},
|
},
|
||||||
|
"subscribable" => Bool,
|
||||||
}
|
}
|
||||||
get "/api/admin/plugin/info" do |env|
|
get "/api/admin/plugin/info" do |env|
|
||||||
begin
|
begin
|
||||||
plugin = Plugin.new env.params.query["plugin"].as String
|
plugin = Plugin.new env.params.query["plugin"].as String
|
||||||
send_json env, {
|
send_json env, {
|
||||||
"success" => true,
|
"success" => true,
|
||||||
"info" => plugin.info,
|
"info" => plugin.info,
|
||||||
|
"subscribable" => plugin.can_subscribe?,
|
||||||
}.to_json
|
}.to_json
|
||||||
rescue e
|
rescue e
|
||||||
Logger.error e
|
Logger.error e
|
||||||
|
|||||||
@@ -133,8 +133,10 @@
|
|||||||
</template>
|
</template>
|
||||||
<button class="uk-button uk-button-primary" @click.prevent="applyFilters()">Apply</button>
|
<button class="uk-button uk-button-primary" @click.prevent="applyFilters()">Apply</button>
|
||||||
<button class="uk-button uk-button-default" @click.prevent="clearFilters()">Clear</button>
|
<button class="uk-button uk-button-default" @click.prevent="clearFilters()">Clear</button>
|
||||||
<span class="uk-divider-vertical uk-margin-left uk-margin-right"></span>
|
<span x-show="subscribable">
|
||||||
<button class="uk-button uk-button-default" @click.prevent="UIkit.modal($refs.modal).show()" :disable="subscribing">Subscribe</button>
|
<span class="uk-divider-vertical uk-margin-left uk-margin-right"></span>
|
||||||
|
<button class="uk-button uk-button-default" @click.prevent="UIkit.modal($refs.modal).show()" :disable="subscribing">Subscribe</button>
|
||||||
|
</span>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p class="uk-text-meta" x-show="chapters && chapters.length > chaptersLimit" x-text="`The manga has ${chapters ? chapters.length : 0} chapters, but Mango can only list up to ${chaptersLimit}. Please use the filters to narrow down your search.`"></p>
|
<p class="uk-text-meta" x-show="chapters && chapters.length > chaptersLimit" x-text="`The manga has ${chapters ? chapters.length : 0} chapters, but Mango can only list up to ${chaptersLimit}. Please use the filters to narrow down your search.`"></p>
|
||||||
|
|||||||
Reference in New Issue
Block a user