LINUX.ORG.RU

На чём спотыкается JavaScript в букмарклете? Вероятно, что-то в работе с JSON

 , ,


0

1

Букмарклет:

javascript:(function() {
    var isbn = prompt("Enter the ISBN of the book");
    var lang = prompt("Optionally enter the Wikipedia subdomain (for supported non-English Wikipedias)");

    if (!isbn) {
        alert("No ISBN provided.");
        return;
    }

    fetch("https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbn)
        .then(response => response.json())
        .then(data => {
            var title = data.items[0].volumeInfo.title;
            var author = data.items[0].volumeInfo.authors.join(", ");
            var publisher = data.items[0].volumeInfo.publisher;
            var date = data.items[0].volumeInfo.publishedDate;
            var year = date.substring(0, 4);

            var template = "";
            if (lang === "ru") {
                template = "{{" + "Книга" + "\n" +
                    "  |название=" + title + "\n" +
                    "  |автор=" + author + "\n" +
                    "  |год=" + year + "\n" +
                    "  |издательство=" + publisher + "\n" +
                    "  |isbn=" + isbn + "\n" +
                    "  |ref=" + "\n" +
                    "}}";
            }
			
            else {
                template = "{{" + "Cite book" + "\n" +
                    "  |title=" + title + "\n" +
                    "  |author=" + author + "\n" +
                    "  |date=" + date + "\n" +
                    "  |publisher=" + publisher + "\n" +
                    "  |isbn=" + isbn + "\n" +
                    "  |ref=" + "\n" +
                    "}}";
            }
			
    template.select();
    document.execCommand('copy');
    prompt("Your Wikipedia template:", template, " has been copied into the clipboard.");
   });
})();

Ожидаемое поведение: сгенерированный шаблон для Википедии из пропарсенного JSON от Google Books копируется в буфер обмена.

Внешнее поведение: показываются промпты для ввода; не показывается вывод и ничего не копируется.

Консоль Chrome: https://pastebin.com/raw/etPh6SJe

★★★★★

Офтоп, просто практикуюсь по lua =) Досвиданья.

json  = require("json") -- GET https://raw.githubusercontent.com/rxi/json.lua/master/json.lua > json.lua
https = require("ssl.https") -- sudo apt install lua-sec

BOOK = "https://www.googleapis.com/books/v1/volumes?q=isbn:"
ISBN = arg[1] -- "3940862215"
body, code, headers, status = https.request(BOOK..ISBN)
data = json.decode(body)

title =     data.items[1].volumeInfo.title;
author =    data.items[1].volumeInfo.authors[1];
publisher = data.items[1].volumeInfo.publisher;
date =      data.items[1].volumeInfo.publishedDate;
year =      date:sub(0, 4);
template = "{{" .. "Книга" .. "\n" ..
       "  |название=" .. tostring(title) .. "\n" ..
       "  |автор="    .. tostring(author) .. "\n" ..
       "  |год="      .. tostring(year) .. "\n" ..
       "  |издательство=" .. tostring(publisher) .. "\n" ..
       "  |isbn="     .. tostring(ISBN) .. "\n" ..
       "  |ref="      .. "\n" ..
       "}}";
print(template)

clipboard = io.popen("xclip -selection clipboard","w")
clipboard:write(template)
clipboard:close()
print("Шаблон скопирован в буфер обмена")
dron@gnu:~/Рабочий-стол/xxcc$ lua main.lua 3940862215
{{Книга
  |название=ISBN - Internationale Standard-Buchnummer
  |автор= Walravens, Hartmut
  |год=2010
  |издательство=Simon Bibliothekswissen
  |isbn=3940862215
  |ref=
}}
Шаблон скопирован в буфер обмена
dron@gnu:~/Рабочий-стол/xxcc$
LINUX-ORG-RU ★★★★★
()

У переменной template нет метода select. Откройте DevTools в браузере через F12 и там в консоли напишите var template = "", нажмите Enter и затем начните писать template.se, в подсказках будет только search и еще парочка методов для строк. Вот если бы template была бы HTMLInputElement тогда select был бы. Но такой метод копирования, когда создается скрытый HTMLInputElement, туда записывается текст, и потом копируется через select, довольно устарел, да и execCommand помечен как deprecated. Так что советую использовать Clipboard API.

//template.select();
//document.execCommand('copy');
navigator.clipboard.writeText(template).then(function() {
  prompt("Your Wikipedia template:", template, " has been copied into the clipboard.");
})

Отлаживать скрипт, чтобы видеть понятные ошибки, можно в той же DevTools консоли, запуская всю программу как IIFE

(function() {
  var isbn = prompt("Enter the ISBN of the book");
  //...
    prompt("Your Wikipedia template:", template, " has been copied into the clipboard.");
  });
})();

Тогда вы сразу увидите человекочитаемую ошибку, что функции select у template нет.

Uncaught (in promise) TypeError: template.select is not a function

от которой дальше можно плясать

mydibyje ★★★★
()
Последнее исправление: mydibyje (всего исправлений: 2)
Ответ на: комментарий от LINUX-ORG-RU

Это полезный офтоп!

1. В Википедии же модули на Lua - Ваш код хорошо бы mutatis mutandi туда затащить!

2. А нельзя ли на основе этого при помощи Fengari соорудить Lua-bookmarklet?

eugrus ★★★★★
() автор топика
Ответ на: комментарий от eugrus

Ну, эт же обычное консольное приложение, если на стороне сервера только, типа по запросу генерировать там, ну можно наверное, луа она и в африке lua. Короче оно работает как просто приложение, а как интегрировать тут уж дело хозяйское.

Вот исправленная версия, там автор может быть не один

json  = require("json") -- GET https://raw.githubusercontent.com/rxi/json.lua/master/json.lua > json.lua
https = require("ssl.https") -- sudo apt install lua-sec

BOOK = "https://www.googleapis.com/books/v1/volumes?q=isbn:"
ISBN = arg[1] -- "3940862215"
body, code, headers, status = https.request(BOOK..ISBN)
data = json.decode(body)
title =     data.items[1].volumeInfo.title;
author =    ""
for k,v in  pairs(data.items[1].volumeInfo.authors) do
    author = v .. ", "
end
author = author:sub(0,#author-2)
publisher = data.items[1].volumeInfo.publisher;
date = data.items[1].volumeInfo.publishedDate;
year = date:sub(0, 4);
template = "{{" .. "Книга" .. "\n" ..
       "  |название=" .. tostring(title)  .. "\n" ..
       "  |автор="    .. tostring(author) .. "\n" ..
       "  |год="      .. tostring(year)   .. "\n" ..
       "  |издательство=" .. tostring(publisher) .. "\n" ..
       "  |isbn="     .. tostring(ISBN)   .. "\n" ..
       "  |ref="      .. "\n" ..
       "}}";
print(template)
clipboard = io.popen("xclip -selection clipboard","w")
clipboard:write(template)
clipboard:close()
print("Шаблон скопирован в буфер обмена")

mutatis mutandi

Чоита такое?

А нельзя ли на основе этого при помощи Fengari соорудить Lua-bookmarklet?

Типа интерпритетор луы жаваскриптом. Ну по сути только https запрос нужно поменять на тамошний и копипасту в буфер обмена и всё. Ну в смысле работоспособности кода. А так я Fengari не тыкал.

Мож попробую попозже

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от mydibyje

Благодарю!

Вот так теперь работает:

javascript:(function() {
    var isbn = prompt("Enter the ISBN of the book");
    var lang = prompt("Optionally enter the Wikipedia subdomain (for supported non-English Wikipedias)");

    if (!isbn) {
        alert("No ISBN provided.");
        return;
    }

    fetch("https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbn)
        .then(response => response.json())
        .then(data => {
            var title = data.items[0].volumeInfo.title;
            var author = data.items[0].volumeInfo.authors.join(", ");
            var publisher = data.items[0].volumeInfo.publisher;
            var date = data.items[0].volumeInfo.publishedDate;
            var year = date.substring(0, 4);

            var template = "";
            if (lang === "ru") {
                template = "{{" + "Книга" + "\n" +
                    "  |название=" + title + "\n" +
                    "  |автор=" + author + "\n" +
                    "  |год=" + year + "\n" +
                    "  |издательство=" + publisher + "\n" +
                    "  |isbn=" + isbn + "\n" +
                    "  |ref=" + "\n" +
                    "}}";
            }
			
            else {
                template = "{{" + "Cite book" + "\n" +
                    "  |title=" + title + "\n" +
                    "  |author=" + author + "\n" +
                    "  |date=" + date + "\n" +
                    "  |publisher=" + publisher + "\n" +
                    "  |isbn=" + isbn + "\n" +
                    "  |ref=" + "\n" +
                    "}}";
            }
    navigator.clipboard.writeText(template);
   });
})();
eugrus ★★★★★
() автор топика
Ответ на: комментарий от eugrus

Гыы, ну тут работает. Короче узнал я только что что такое эти букмарклеты лол, прикольно работает. Сейчас есть полчасика попробую впиндюрить lua в js через Fengari и посмотреть чво будет. Хотя это мне кажется дикий оверхед =) Ну да пофиг. Вдруг и правда заработает хехе

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Горячо приветствую! 👍

С моей стороны уже итого скопились рабочие реализации на Bash, на PowerShell и на JavaScript :) https://github.com/eugrus/isbn4wiki

Дальше хочу допилить так, чтобы когда чего-то не хватает на Google Books, дополнял из https://openlibrary.org/api/books?bibkeys=ISBN:$isbn&jscmd=data&format=json

eugrus ★★★★★
() автор топика
Ответ на: комментарий от eugrus

Просто var author = data.items[0].volumeInfo.authors; разве не работает у вас?

А, пардон, понял. Вы хотите с пробелом после запятой.

Toxo2 ★★★★
()
Последнее исправление: Toxo2 (всего исправлений: 2)
Ответ на: комментарий от Toxo2

Проверил - в таком варианте «почти работает», но получается без пробелов между авторами, так что лучше и здесь оставить превращение массива в строку.

eugrus ★★★★★
() автор топика
Ответ на: комментарий от eugrus

Понятненько, короче, оно работает :D

<!DOCTYPE html>
<head>
<script src="fengari-web.js" type="text/javascript"></script>
</head>
<body>
<a href="javascript:fengari.load(' 
local js = require \'js\';
local window = js.global;
window:alert(\'lua lua lua\') 
')()">xxx</a>
</body>
</html>

Но переносить код не вижу смысла, так как от lua там останется только очень небольшая логика, разве что упороться и притащить разбор json на lua. Короче если очень постараться то можно. Ну, а так да, можно lua гонять в браузере, работает хехе.

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от eugrus

Ссылку со страницы (не на страницу, а с страницы) добавил в закладки по клику на закладку тоже аллект выскакивает, значит работает. Но не дёргается prompt для ввода, наверное будет работать если выделить текст и нажать на закладку тогда выделенный текст можно пустить на обработку и через alert показать template содержимое и скопировать в буфер обмена.

По хорошему да нужно весь код совать в ссылку,но там будет огромаднейшая каша из сначала фенрара и только в конце eval по сути только load уже lua который будет дёргать js для httpRequest и для разбора json итог от lua останется только цикл и sub функция, ну и синтаксис :D Это жестоко =) Но если упороться то я уверен можно, но точно не нужно. Есть вон выше скрипт, он работает просто как скрипт, так же как твой баш скрипт, а это уже будет извращение чистой воды. Но вот просто запускать lua в браузере, да можно, это прикольно, но годно оно чисто для чистого lua кода, иначе оч много всего менять надо на вызовы js а тут прям всё в одном и сеть и json надо дрыгать через js или копирастить сюда же в исходник lua-json тогда от js нужно только будет получить json данные.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

Букмарклет именно и лишь потому сработал, что он был вызван при нахождении на той странице, которая уже сама подгрузила транспайлер.

Если откроете новую вкладку браузера, в которой fengari-web.js не предподгружен через HTML страницы, то там букмарклет в такой реализации никак не может работать.

eugrus ★★★★★
() автор топика
Ответ на: комментарий от eugrus

Ну я и говорю, можно и нужно всё засунуть в одну строку, но там будет 10+ килобайт текста, который будет делать то же самое что и js у тебя, только медленее в разы =) Там ещё ведь сжаный фенгар этот, если чистаемость сохранить то уххх.

Суть в том что отрабатывает lua, да пусть только при открытой странице где подгружена виртуалка для lua на js. Главное работает, остальное дело техники, к сожалению я с js на вы, поэтому пердолится не хоца =) Да и результат если оч постараться будет сомнительным.

Но эксперимент я считаю удачным :)

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Именно что не можно в одну строку с транспайлером - браузер не примет такое длинное закладкой :)

Рабочим решением была бы подгрузка коротким JS в закладке fengari-web.js со стороннего сервера: тут обсуждались всякие варианты https://stackoverflow.com/questions/14521108/dynamically-load-js-inside-js

А дальше fengari.load()

eugrus ★★★★★
() автор топика
Последнее исправление: eugrus (всего исправлений: 1)
Ответ на: комментарий от eugrus

Во. Теперь игрался с luarocks и автоматической проверки зависимостей и их накатки.


package.path  = package.path ..  ";/home/"..os.getenv("USER").."/.luarocks/share/lua/5.1/?.lua;"
package.cpath = package.cpath .. ";/home/"..os.getenv("USER").."./lualib/lib/lua/5.1/?.so;"

local json, https;

function loadmodules() 
json  = require("rxi-json-lua")
https = require("ssl.https")
end
-----------------------------------------------------------
if pcall(loadmodules) then
    --print("all okey")
else
    print("Первый запуск, установка зависимостей")
    os.execute("luarocks --local install rxi-json-lua")
    json  = require("rxi-json-lua")
    os.execute("luarocks --local install luasec")
    https = require("ssl.https")
end
------------------------------------------------------------
BOOK = "https://www.googleapis.com/books/v1/volumes?q=isbn:"
ISBN =  arg[1] -- example "3940862215"
LANG =  arg[2] -- "ru" or "en"

if ISBN == "en" or ISBN == "ru" then
    LANG = ISBN
    ISBN = nil
end

if ISBN == nil then
    clip_pipe = io.popen("xclip -selection clipboard -o")
    clip_data = tonumber(clip_pipe:read("*a"))
    if type(clip_data) == "number" then
        ISBN = clip_data;
    end
end 
if ISBN == nil then
    print("Нужно задать ISBN номер книги в параметры запуска скрипта: $lua script.lua ISBN_НОМЕР [en ru опционально] ")
    print("Или скопировать номер ISBN в буфер обмена")
    return
end
------------------------------------------------------------
if LANG == nil then
   LANG = "ru" -- default russian
end
------------------------------------------------------------
body, code, headers, status = https.request(BOOK..ISBN)
data = json.decode(body)
------------------------------------------------------------
if data == nil or data.items == nil then
    print("Нет книг для этого ISBN")
    return
end
------------------------------------------------------------
title  =    data.items[1].volumeInfo.title;
author =    ""
for k,v in  pairs(data.items[1].volumeInfo.authors) do
    author = v .. ", "
end
author =    author:sub(0,#author-2)
publisher = data.items[1].volumeInfo.publisher;
date =      data.items[1].volumeInfo.publishedDate;
year =      date:sub(0, 4);
------------------------------------------------------------
if LANG == "ru" then
template = "{{" .. "Книга" .. "\n" ..
       "  |название=" .. tostring(title)  .. "\n" ..
       "  |автор="    .. tostring(author) .. "\n" ..
       "  |год="      .. tostring(year)   .. "\n" ..
       "  |издательство=" .. tostring(publisher) .. "\n" ..
       "  |isbn="     .. tostring(ISBN)   .. "\n" ..
       "  |ref="      .. "\n" ..
       "}}";
else
template = "{{" .. "Book" .. "\n" ..
       "  |title="     .. tostring(title)  .. "\n" ..
       "  |author="    .. tostring(author) .. "\n" ..
       "  |date="      .. tostring(year)   .. "\n" ..
       "  |publisher=" .. tostring(publisher) .. "\n" ..
       "  |isbn="      .. tostring(ISBN)   .. "\n" ..
       "  |ref="       .. "\n" ..
       "}}";
end
------------------------------------------------------------
print(template)
clipboard = io.popen("xclip -selection clipboard","w")
clipboard:write(template)
clipboard:close()
print("Шаблон скопирован в буфер обмена")
os.execute("notify-send -e 'Шаблон скопирован в буфер обмена'")

Теперь оно само развернёт при первом запуске необходимое, а патчи прописаны сразу. en/ru на выбор. В случае неправильного кода ISBN будут сообщения, мол такой книги нету. Если парамерты не заданы то пытается взять код из буфера обмена, если это удаётся то получает данные, в терминале можно отдельно задать язык без указывания кода ISBN тогда код будет браться только из буфера обмена. Номер ISBN обязан быть числом иначе не распознает

Всё вроде работает, всё я наигрался. Досвиданья.

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от token_polyak

К слову да, вот буквально 15 минут назад хотел в толксы про это написать. Мол я понял наконец почему у нас все дистрибутивы засраны скриптовым говном, почему утилитки на две строки имеют зависимости как IDE и всё вот это вот. Это оказывается удобно, а люди ленивые твари. И от этого пошла молва мол «вычислильное время сейчас дешёвое,докупи оперативки, поменяй проц, время дороже» и прочий отчасти бред. Это удобно, действительно удобно, только вот есть одно, но. Удобно для прототипирования и частых изменений, если программа устоялась, переписать на компилируемое и не сношать моск.

Но тут у меня есть оправдание, я тренируюсь =) Надо же прикладные вещи делать при обучении, вот тыкнул пальцем попал сюда и всё. Мне нужен скоро будет язык компаньон для автоматизации и одновременно встраиваемый, для прототипирования и расширения основной программы, типа если есть новый формат файла который надо сожрать то сначала набрасывается реализация на компаньоне, а когда уже изменений нет и не будет то переписывается на сишку (хотя если оно вообще стоит того, скрипты для себя хоть на PHP можно держать, переписывать надо что-то дельное и обладающее реальной вычислительной затратностью, а не тупо логику).

Всякие luarocks с поддтягом зависимостей это ненужное зло, но надо понимать хоть маленько как оно работает ибо локально порой надо что-то сделать быстро/временно, может пригодится.

Метался между языками lua и pawn оба подходят, у обоих приколы у павна сишный синтаксис (это и есть си для маленьких) у луа гибкость. pawn проиграл, но язык интересный очень.

Можно то что выше переписать используя системные curl для получения данных и jq для разбора json будет просто bash скрипт с логикой на чистой lua. И это было бы уже Ъ решение, без зависимостей (системные не в счёт), по всем канонам. Но надо поиграться и с зависимостями.

Вот такие пироги, на этапе обучения надо тыкать всё. Каюсь, позорище. Но lua это исключение, луа это уродливая няшка, дочка папы Си которая бегает в школу аэробики и часто там стукалась головой, развив гибкость и немного тугодумия ^.^

А как компаньён/скрипота lua хороша для такого, на баше яб не стал такое писать.
До этого это был скрипт на си запускаемый через tcc

------------------------------------------
-------Simple auto WakeUP from sleep------
------копиригхт Цы LINUX-ORG-RU-----------
------------license WTFPL-----------------
------------------------------------------
--- заранее в /etc/rc.local шобы работало
--- chmod ugo+r  /dev/rtc0
--- chown $USER  /sys/power/state
------------------------------------------

local ctime = 
{
    year = tonumber(os.date("%Y")),
    mont = tonumber(os.date("%m")),
    days = tonumber(os.date("%d")),
    hour = tonumber(os.date("%H")),
    mins = tonumber(os.date("%M")),
    seco = tonumber(os.date("%S")),
}

chunks = {}
for substring in arg[1]:gmatch("([^:]+)") do
   table.insert(chunks, substring)
end

local wtime = 
{
    hour = tonumber(chunks[1]),
    mins = tonumber(chunks[2]),
}

if wtime.hour == nil or wtime.mins == nil then
    print("./rtcwake час:минута")
    return
end

local time = 0
local incd = 0

if ctime.hour > wtime.hour then
    incd = 1
end

time = os.time
{
    year  = ctime.year,
    month = ctime.mont,
    day   = ctime.days+incd,
    hour  = wtime.hour,
    min   = wtime.mins,
    sec   = ctime.secs
}

print("Включение в "..ctime.year.."/"..ctime.mont.."/"..ctime.days+incd.." "..wtime.hour..":"..wtime.mins)

os.execute("killall rtcwake")
os.execute("/usr/sbin/rtcwake -m mem -s "..time-os.time())
os.execute("sleep 2")
os.execute("xset dpms force on")
os.execute("nmcli networking off")
os.execute("nmcli networking on")

print("тютютю")

Всё, я оправдался :D

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)