Merge remote-tracking branch 'origin/master'

This commit is contained in:
Egor Aristov 2025-02-23 17:03:47 +03:00
commit 3d907bfa04
3 changed files with 0 additions and 158 deletions

View File

@ -1,69 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="main.css">
<script defer src="main.js"></script>
<title>RSS Alchemy</title>
</head>
<body>
<div class="form">
<form name="wizard">
<div class="field">
<div class="label"><label for="w_url">URL of page for converting</label></div>
<div class="input">
<input type="url" name="url" id="w_url"/>
<a id="page_screenshot_link" target="_blank">Render screenshot</a>
</div>
</div>
<div class="field">
<div class="label"><label for="w_selector_post">CSS Selector for post</label></div>
<div class="input"><input type="text" name="selector_post" id="w_selector_post"/></div>
</div>
<div class="field">
<div class="label"><label for="w_selector_title">CSS Selector for title</label></div>
<div class="input"><input type="text" name="selector_title" id="w_selector_title"/></div>
</div>
<div class="field">
<div class="label"><label for="w_selector_link">CSS Selector for link</label></div>
<div class="input"><input type="text" name="selector_link" id="w_selector_link"/></div>
</div>
<div class="field">
<div class="label"><label for="w_selector_description">CSS Selector for description</label></div>
<div class="input"><input type="text" name="selector_description" id="w_selector_description"/></div>
</div>
<div class="field">
<div class="label"><label for="w_selector_author">CSS Selector for author</label></div>
<div class="input"><input type="text" name="selector_author" id="w_selector_author"/></div>
</div>
<div class="field">
<div class="label"><label for="w_selector_created">CSS Selector for created date</label></div>
<div class="input"><input type="text" name="selector_created" id="w_selector_created"/></div>
</div>
<div class="field">
<div class="label"><label for="w_selector_content">CSS Selector for content</label></div>
<div class="input"><input type="text" name="selector_content" id="w_selector_content"/></div>
</div>
<div class="field">
<div class="label"><label for="w_selector_enclosure">CSS Selector for enclosure (e.g. image url)</label>
</div>
<div class="input"><input type="text" name="selector_enclosure" id="w_selector_enclosure"/></div>
</div>
<div class="field">
<div class="label"><label for="w_cache_lifetime">Cache lifetime (format examples: 10s, 1m, 2h)</label>
</div>
<div class="input"><input type="text" name="cache_lifetime" id="w_cache_lifetime"/></div>
</div>
</form>
<br/>
<button type="button" id="btn_gen_url">Generate url</button>
<input type="url" id="url_input"/>
<button type="button" id="btn_edit">Edit</button>
<div><a id="ready_url_link" target="_blank">Preview in browser</a></div>
<div id="cont_url_len"></div>
</div>
</body>
</html>

View File

@ -1,8 +0,0 @@
#ready_url_link, #page_screenshot_link {
visibility: hidden;
}
div.field input {
width: 250px;
margin-bottom: 4px;
}

View File

@ -1,81 +0,0 @@
function readSpecsForm() {
let specs = {};
for (let field of document.forms['wizard'].elements) {
specs[field.name] = field.value;
}
return specs;
}
function writeSpecsToForm(specs) {
for (let [k, v] of Object.entries(specs)) {
document.forms['wizard'].elements[k].value = v;
}
}
async function encodeSpecs(specs) {
let byteArray = new TextEncoder().encode(JSON.stringify(specs));
let cs = new CompressionStream('deflate-raw');
let writer = cs.writable.getWriter();
writer.write(byteArray);
writer.close();
let response = new Response(cs.readable);
let respBuffer = await response.arrayBuffer();
let b64str = btoa(String.fromCharCode.apply(null, new Uint8Array(respBuffer)));
return b64str.replaceAll('=', '');
}
async function decodeSpecs(str) {
const byteArray = Uint8Array.from(atob(str), c => c.charCodeAt(0));
let ds = new DecompressionStream('deflate-raw');
let writer = ds.writable.getWriter();
writer.write(byteArray);
writer.close();
let response = new Response(ds.readable);
let respText = await response.text();
return JSON.parse(respText);
}
function displayUrl(url) {
let link = document.getElementById('ready_url_link');
link.href = url;
link.style.visibility = 'visible';
let readyUrlInput = document.getElementById('url_input');
readyUrlInput.value = url;
readyUrlInput.focus();
readyUrlInput.select();
document.getElementById('cont_url_len').innerText = `len=${url.length}`;
}
function baseUrl() {
return document.location.origin + '/api/v1';
}
async function genUrl() {
let specs = readSpecsForm();
let encodedSpecs = await encodeSpecs(specs);
let url = baseUrl() + '/render/' + encodedSpecs;
displayUrl(url);
}
async function editUrl() {
let url = document.getElementById('url_input').value;
let specs = await decodeSpecs(url.replace(baseUrl() + '/render/', ''));
writeSpecsToForm(specs);
displayUrl(url);
}
function onUrlInput() {
let url = document.forms['wizard'].elements['url'].value;
if (url.trim().length > 0) {
document.getElementById('page_screenshot_link').style.visibility = 'visible';
document.getElementById('page_screenshot_link').href = `${baseUrl()}/screenshot?url=${url}`;
} else {
document.getElementById('page_screenshot_link').style.visibility = 'hidden';
}
}
document.addEventListener('DOMContentLoaded', ev => {
document.getElementById('btn_gen_url').addEventListener('click', genUrl);
document.getElementById('btn_edit').addEventListener('click', editUrl);
document.getElementById('w_url').addEventListener('input', onUrlInput);
});