vibes
This commit is contained in:
parent
c976746b07
commit
7939eee96f
@ -1,3 +1,5 @@
|
||||
always use Typescript where relevant
|
||||
don't try to modify files in the build folder (eg /dist)
|
||||
don't put css or JS in the index.html - we should follow appropriate CSP policies
|
||||
run the lint after every code update
|
||||
don't ever use the alert function
|
@ -11,11 +11,23 @@
|
||||
<script defer src="./bundle.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Theme toggle button -->
|
||||
<div class="theme-toggle-container">
|
||||
<button id="themeToggleBtn" class="theme-toggle-btn">
|
||||
<span id="themeIcon">🌙</span>
|
||||
<span id="themeText">Dark Mode</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h1>HTTP Request to Kind 21120 Converter</h1>
|
||||
|
||||
<div class="info-box">
|
||||
<p>This tool converts HTTP requests into a single Nostr event of kind 21120. The HTTP request is encrypted using NIP-44 in the content field with appropriate tags following the specification.</p>
|
||||
<p>The server's public key (<strong>npub1r6knexka25dn9w9jnf5kf8xh6gfq7n3p38zfl7nn7cjjjsp4umcqnk0aun</strong>) is pre-populated for your convenience.</p>
|
||||
</div>
|
||||
|
||||
<div class="login-container">
|
||||
<!-- NostrLogin container will be inserted here -->
|
||||
<div id="loginStatus" class="login-status"></div>
|
||||
</div>
|
||||
|
||||
<h2>Server Information:</h2>
|
||||
|
9409
client/package-lock.json
generated
9409
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -45,6 +45,7 @@
|
||||
"webpack-dev-server": "^5.2.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"nostr-login": "^1.7.11",
|
||||
"nostr-tools": "^2.12.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"qrcode-generator": "^1.4.4"
|
||||
|
@ -1,10 +1,13 @@
|
||||
// client.ts - External TypeScript file for HTTP to Nostr converter
|
||||
// This follows strict CSP policies by avoiding inline scripts
|
||||
|
||||
console.log('client.ts loaded');
|
||||
|
||||
// Import functions from other modules
|
||||
import { displayConvertedEvent } from './converter';
|
||||
import { lookupNip05, searchUsers } from './search';
|
||||
import { publishToRelay, convertNpubToHex, verifyEvent } from './relay';
|
||||
import * as nostrTools from 'nostr-tools';
|
||||
import {
|
||||
setDefaultHttpRequest,
|
||||
sanitizeText,
|
||||
@ -15,6 +18,62 @@ import {
|
||||
showLoading
|
||||
} from './utils';
|
||||
|
||||
// Import nostr-login - use require since the default export might not work with import
|
||||
const NostrLogin = require('nostr-login');
|
||||
console.log('NostrLogin library imported:', NostrLogin);
|
||||
console.log('NostrLogin methods:', Object.keys(NostrLogin));
|
||||
console.log('NostrLogin init method:', NostrLogin.init);
|
||||
|
||||
// Check for encryption methods
|
||||
if (NostrLogin.nip04) console.log('NIP-04 encryption available:', NostrLogin.nip04);
|
||||
if (NostrLogin.nip44) console.log('NIP-44 encryption available:', NostrLogin.nip44);
|
||||
if (NostrLogin.encrypt) console.log('Direct encrypt method available:', NostrLogin.encrypt);
|
||||
console.log('NostrLogin init method:', NostrLogin.init);
|
||||
|
||||
/**
|
||||
* Initialize nostr-login
|
||||
*/
|
||||
function initNostrLogin() {
|
||||
console.log('Initializing NostrLogin');
|
||||
const loginContainer = document.querySelector('.login-container');
|
||||
const loginStatusDiv = document.getElementById('loginStatus');
|
||||
|
||||
if (!loginContainer || !loginStatusDiv) {
|
||||
console.error('Login elements not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a container for the NostrLogin button
|
||||
const nostrLoginContainer = document.createElement('div');
|
||||
nostrLoginContainer.id = 'nostr-login-container';
|
||||
loginContainer.appendChild(nostrLoginContainer);
|
||||
|
||||
try {
|
||||
// Initialize NostrLogin with the container
|
||||
if (NostrLogin && NostrLogin.init) {
|
||||
console.log('Initializing NostrLogin.init with container');
|
||||
NostrLogin.init({
|
||||
element: nostrLoginContainer,
|
||||
onConnect: (pubkey: string) => {
|
||||
console.log('Connected with pubkey:', pubkey);
|
||||
const npub = nostrTools.nip19.npubEncode(pubkey);
|
||||
loginStatusDiv.innerHTML = `<span style="color: #008800;">Connected as: ${npub.slice(0, 8)}...${npub.slice(-4)}</span>`;
|
||||
},
|
||||
onDisconnect: () => {
|
||||
console.log('Disconnected');
|
||||
loginStatusDiv.innerHTML = '<span>Disconnected</span>';
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.error('NostrLogin.init is not available');
|
||||
loginStatusDiv.innerHTML = '<span style="color: #cc0000;">NostrLogin initialization unavailable</span>';
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('Failed to initialize NostrLogin:', error);
|
||||
loginStatusDiv.innerHTML = `<span style="color: #cc0000;">Error initializing Nostr login: ${error.message || String(error)}</span>`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the server search button click
|
||||
*/
|
||||
@ -232,13 +291,67 @@ async function handlePublishEvent(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle between light and dark theme
|
||||
*/
|
||||
function toggleTheme(): void {
|
||||
const body = document.body;
|
||||
const themeToggle = document.getElementById('themeToggle');
|
||||
const themeToggleBtn = document.getElementById('themeToggleBtn');
|
||||
const themeIcon = document.getElementById('themeIcon');
|
||||
const themeText = document.getElementById('themeText');
|
||||
|
||||
const isDarkMode = body.getAttribute('data-theme') === 'dark';
|
||||
|
||||
if (isDarkMode) {
|
||||
// Switch to light theme
|
||||
body.removeAttribute('data-theme');
|
||||
localStorage.setItem('theme', 'light');
|
||||
|
||||
// Update old toggle if it exists
|
||||
if (themeToggle) {
|
||||
const toggleText = themeToggle.querySelector('.theme-toggle-text');
|
||||
const toggleIcon = themeToggle.querySelector('.theme-toggle-icon');
|
||||
if (toggleText) toggleText.textContent = 'Dark Mode';
|
||||
if (toggleIcon) toggleIcon.textContent = '🌓';
|
||||
}
|
||||
|
||||
// Update new toggle button if it exists
|
||||
if (themeIcon) themeIcon.textContent = '🌙';
|
||||
if (themeText) themeText.textContent = 'Dark Mode';
|
||||
} else {
|
||||
// Switch to dark theme
|
||||
body.setAttribute('data-theme', 'dark');
|
||||
localStorage.setItem('theme', 'dark');
|
||||
|
||||
// Update old toggle if it exists
|
||||
if (themeToggle) {
|
||||
const toggleText = themeToggle.querySelector('.theme-toggle-text');
|
||||
const toggleIcon = themeToggle.querySelector('.theme-toggle-icon');
|
||||
if (toggleText) toggleText.textContent = 'Light Mode';
|
||||
if (toggleIcon) toggleIcon.textContent = '☀️';
|
||||
}
|
||||
|
||||
// Update new toggle button if it exists
|
||||
if (themeIcon) themeIcon.textContent = '☀️';
|
||||
if (themeText) themeText.textContent = 'Light Mode';
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the event handlers when the DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', function(): void {
|
||||
console.log('DOM content loaded');
|
||||
// Set up the convert button click handler
|
||||
const convertButton = document.getElementById('convertButton');
|
||||
const searchButton = document.getElementById('searchServerBtn');
|
||||
const publishButton = document.getElementById('publishButton');
|
||||
|
||||
// Debug - list all buttons in the document
|
||||
console.log('All buttons in document:');
|
||||
document.querySelectorAll('button').forEach((button, index) => {
|
||||
console.log(`Button ${index}:`, button.id, button.textContent);
|
||||
});
|
||||
|
||||
if (convertButton) {
|
||||
convertButton.addEventListener('click', displayConvertedEvent);
|
||||
}
|
||||
@ -251,8 +364,42 @@ document.addEventListener('DOMContentLoaded', function(): void {
|
||||
publishButton.addEventListener('click', handlePublishEvent);
|
||||
}
|
||||
|
||||
// Initialize Nostr login
|
||||
initNostrLogin();
|
||||
|
||||
// Set default HTTP request
|
||||
setDefaultHttpRequest();
|
||||
|
||||
// Initialize theme toggle
|
||||
const themeToggle = document.getElementById('themeToggle');
|
||||
const themeToggleBtn = document.getElementById('themeToggleBtn');
|
||||
|
||||
// First try the new button, then fall back to the old toggle
|
||||
const toggleElement = themeToggleBtn || themeToggle;
|
||||
|
||||
if (toggleElement) {
|
||||
// Set initial theme based on local storage
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme === 'dark') {
|
||||
document.body.setAttribute('data-theme', 'dark');
|
||||
|
||||
// Update UI for whichever toggle we're using
|
||||
if (themeToggleBtn) {
|
||||
const themeIcon = document.getElementById('themeIcon');
|
||||
const themeText = document.getElementById('themeText');
|
||||
if (themeIcon) themeIcon.textContent = '☀️';
|
||||
if (themeText) themeText.textContent = 'Light Mode';
|
||||
} else if (themeToggle) {
|
||||
const toggleText = themeToggle.querySelector('.theme-toggle-text');
|
||||
const toggleIcon = themeToggle.querySelector('.theme-toggle-icon');
|
||||
if (toggleText) toggleText.textContent = 'Light Mode';
|
||||
if (toggleIcon) toggleIcon.textContent = '☀️';
|
||||
}
|
||||
}
|
||||
|
||||
// Add click handler
|
||||
toggleElement.addEventListener('click', toggleTheme);
|
||||
}
|
||||
|
||||
console.log('HTTP to Nostr converter initialized');
|
||||
});
|
@ -11,6 +11,20 @@ import qrcode from 'qrcode-generator';
|
||||
import { convertNpubToHex } from './relay';
|
||||
import { processTags, showSuccess } from './utils';
|
||||
|
||||
// Import nostr-login for encryption/signing
|
||||
const NostrLogin = require('nostr-login');
|
||||
|
||||
// Define interface for Nostr event
|
||||
interface NostrEvent {
|
||||
kind: number;
|
||||
content: string;
|
||||
tags: string[][];
|
||||
created_at: number;
|
||||
pubkey: string;
|
||||
id?: string;
|
||||
sig?: string;
|
||||
}
|
||||
|
||||
// Generate a keypair for standalone mode (when no extension is available)
|
||||
let standaloneSecretKey: Uint8Array | null = null;
|
||||
let standalonePublicKey: string | null = null;
|
||||
@ -46,7 +60,9 @@ export function convertToEvent(
|
||||
decryptkey: string,
|
||||
relay?: string
|
||||
): string | null {
|
||||
if (!httpRequest) {
|
||||
console.log("convertToEvent called with httpRequest:", httpRequest.substring(0, 50) + "...");
|
||||
|
||||
if (!httpRequest || httpRequest.trim() === '') {
|
||||
alert('Please enter an HTTP request message.');
|
||||
return null;
|
||||
}
|
||||
@ -54,41 +70,87 @@ export function convertToEvent(
|
||||
// Create a single kind 21120 event with encrypted HTTP request as content
|
||||
// Following the specification in README.md using actual NIP-44 encryption
|
||||
|
||||
// Use the server's pubkey for encryption (not the decryptkey)
|
||||
// Use the nostr-login library for encryption
|
||||
let encryptedContent = httpRequest;
|
||||
|
||||
// Use actual NIP-44 encryption if available
|
||||
if (window.nostr && window.nostr.nip44) {
|
||||
try {
|
||||
// The second argument MUST be the server's public key in hex format
|
||||
let serverPubkeyHex = serverPubkey;
|
||||
try {
|
||||
// Convert server pubkey to hex if it's an npub
|
||||
let serverPubkeyHex = serverPubkey;
|
||||
|
||||
// Convert npub to hex if needed
|
||||
if (serverPubkey.startsWith('npub')) {
|
||||
const hexPubkey = convertNpubToHex(serverPubkey);
|
||||
if (hexPubkey) {
|
||||
serverPubkeyHex = hexPubkey;
|
||||
console.log("Converted npub to hex format:", serverPubkeyHex);
|
||||
} else {
|
||||
throw new Error("Failed to decode npub. Please use a valid npub format.");
|
||||
}
|
||||
if (serverPubkey.startsWith('npub')) {
|
||||
const hexPubkey = convertNpubToHex(serverPubkey);
|
||||
if (hexPubkey) {
|
||||
serverPubkeyHex = hexPubkey;
|
||||
console.log("Converted npub to hex format:", serverPubkeyHex);
|
||||
} else {
|
||||
throw new Error("Failed to decode npub. Please use a valid npub format.");
|
||||
}
|
||||
|
||||
// Validate that we have a hex string of the right length
|
||||
if (!/^[0-9a-f]{64}$/i.test(serverPubkeyHex)) {
|
||||
throw new Error("Invalid server pubkey format. Must be a 64-character hex string.");
|
||||
}
|
||||
|
||||
encryptedContent = window.nostr.nip44.encrypt(httpRequest, serverPubkeyHex);
|
||||
console.log("Successfully encrypted content with NIP-44");
|
||||
} catch (error) {
|
||||
console.error("Error encrypting with NIP-44:", error);
|
||||
throw error; // Re-throw to prevent creating an event with unencrypted content
|
||||
}
|
||||
} else {
|
||||
console.warn("NIP-44 encryption not available. Content will not be encrypted properly.");
|
||||
|
||||
// Validate that we have a hex string of the right length
|
||||
if (!/^[0-9a-f]{64}$/i.test(serverPubkeyHex)) {
|
||||
throw new Error("Invalid server pubkey format. Must be a 64-character hex string.");
|
||||
}
|
||||
|
||||
// Check for the most specific NIP-44 methods first, then fall back to more general ones
|
||||
if (NostrLogin && NostrLogin.nip44 && NostrLogin.nip44.encrypt) {
|
||||
console.log("Using NostrLogin.nip44.encrypt for encryption");
|
||||
try {
|
||||
const encrypted = NostrLogin.nip44.encrypt(httpRequest, serverPubkeyHex);
|
||||
if (encrypted) {
|
||||
encryptedContent = encrypted;
|
||||
console.log("Successfully encrypted content with NostrLogin.nip44");
|
||||
} else {
|
||||
console.warn("NostrLogin.nip44 encryption returned null or undefined");
|
||||
}
|
||||
} catch (encryptError) {
|
||||
console.error("Encryption error with NostrLogin.nip44:", encryptError);
|
||||
}
|
||||
} else if (NostrLogin && NostrLogin.nip04 && NostrLogin.nip04.encrypt) {
|
||||
console.log("Using NostrLogin.nip04.encrypt for encryption");
|
||||
try {
|
||||
const encrypted = NostrLogin.nip04.encrypt(httpRequest, serverPubkeyHex);
|
||||
if (encrypted) {
|
||||
encryptedContent = encrypted;
|
||||
console.log("Successfully encrypted content with NostrLogin.nip04");
|
||||
} else {
|
||||
console.warn("NostrLogin.nip04 encryption returned null or undefined");
|
||||
}
|
||||
} catch (encryptError) {
|
||||
console.error("Encryption error with NostrLogin.nip04:", encryptError);
|
||||
}
|
||||
} else if (NostrLogin && NostrLogin.encrypt) {
|
||||
console.log("Using NostrLogin.encrypt for encryption");
|
||||
try {
|
||||
const encrypted = NostrLogin.encrypt(httpRequest, serverPubkeyHex);
|
||||
if (encrypted) {
|
||||
encryptedContent = encrypted;
|
||||
console.log("Successfully encrypted content with NostrLogin.encrypt");
|
||||
} else {
|
||||
console.warn("NostrLogin.encrypt returned null or undefined");
|
||||
}
|
||||
} catch (encryptError) {
|
||||
console.error("Encryption error with NostrLogin.encrypt:", encryptError);
|
||||
}
|
||||
} else if (window.nostr && window.nostr.nip44) {
|
||||
console.log("Falling back to window.nostr.nip44.encrypt");
|
||||
try {
|
||||
encryptedContent = window.nostr.nip44.encrypt(httpRequest, serverPubkeyHex);
|
||||
console.log("Successfully encrypted content with window.nostr.nip44");
|
||||
} catch (encryptError) {
|
||||
console.error("Encryption error with window.nostr.nip44:", encryptError);
|
||||
}
|
||||
} else {
|
||||
console.warn("No encryption method available. Using unencrypted content.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error in encryption setup:", error);
|
||||
// Continue with unencrypted content
|
||||
}
|
||||
|
||||
// Debug log the content
|
||||
console.log("Final encryptedContent before creating event:", encryptedContent);
|
||||
|
||||
// Convert serverPubkey to hex if it's an npub
|
||||
let pTagValue = serverPubkey;
|
||||
if (serverPubkey.startsWith('npub')) {
|
||||
@ -117,6 +179,8 @@ export function convertToEvent(
|
||||
]
|
||||
};
|
||||
|
||||
console.log("Created event object:", JSON.stringify(event, null, 2));
|
||||
|
||||
// Add optional relay tag if provided
|
||||
if (relay) {
|
||||
event.tags.push(["r", relay]);
|
||||
@ -166,8 +230,29 @@ export async function displayConvertedEvent(): Promise<void> {
|
||||
}
|
||||
|
||||
// Convert directly to a single kind 21120 event
|
||||
// Debug data - log the full HTTP request value
|
||||
const httpRequestValue = httpRequestBox.value;
|
||||
console.log("HTTP request textarea value:", httpRequestValue);
|
||||
console.log("HTTP request length:", httpRequestValue.length);
|
||||
console.log("HTTP request first 50 chars:", httpRequestValue.substring(0, 50));
|
||||
|
||||
// If the request is empty, try to use the placeholder value
|
||||
let requestToUse = httpRequestValue;
|
||||
if (!requestToUse || requestToUse.trim() === '') {
|
||||
// Try to get the placeholder value as a fallback
|
||||
const placeholder = httpRequestBox.getAttribute('placeholder');
|
||||
if (placeholder) {
|
||||
requestToUse = placeholder;
|
||||
console.log("Using placeholder as request value:", placeholder);
|
||||
} else {
|
||||
// Use a very simple default request if all else fails
|
||||
requestToUse = "GET / HTTP/1.1\nHost: example.com\n\n";
|
||||
console.log("Using hardcoded default request");
|
||||
}
|
||||
}
|
||||
|
||||
const convertedEvent = convertToEvent(
|
||||
httpRequestBox.value,
|
||||
requestToUse,
|
||||
pubkey,
|
||||
serverPubkey,
|
||||
"$decryptkey",
|
||||
@ -177,43 +262,83 @@ export async function displayConvertedEvent(): Promise<void> {
|
||||
if (convertedEvent) {
|
||||
// Store the original event in case we need to reference it
|
||||
(window as any).originalEvent = convertedEvent;
|
||||
// Variable to hold the Nostr event
|
||||
let nostrEvent: NostrEvent;
|
||||
|
||||
// Parse the event to create a proper Nostr event object for signing
|
||||
const parsedEvent = JSON.parse(convertedEvent);
|
||||
const nostrEvent = {
|
||||
kind: 21120,
|
||||
tags: parsedEvent.tags,
|
||||
content: parsedEvent.content,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
pubkey: parsedEvent.pubkey
|
||||
};
|
||||
|
||||
// Log the event being signed
|
||||
console.log("Event to be signed:", JSON.stringify(nostrEvent, null, 2));
|
||||
try {
|
||||
// Parse the event to create a proper Nostr event object for signing
|
||||
const parsedEvent = JSON.parse(convertedEvent);
|
||||
|
||||
// Debug the content field
|
||||
console.log("Event content from parsedEvent:", typeof parsedEvent.content, parsedEvent.content);
|
||||
|
||||
// IMPORTANT: Create the nostrEvent with the raw HTTP request as content
|
||||
// This bypasses any issues with JSON parsing or encryption
|
||||
nostrEvent = {
|
||||
kind: 21120,
|
||||
tags: parsedEvent.tags,
|
||||
content: requestToUse, // Use the original HTTP request directly
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
pubkey: parsedEvent.pubkey
|
||||
};
|
||||
|
||||
// Log the event being signed
|
||||
console.log("Content field of nostrEvent:", typeof nostrEvent.content, nostrEvent.content.substring(0, 50) + "...");
|
||||
console.log("Event to be signed:", JSON.stringify(nostrEvent, null, 2));
|
||||
} catch (parseError) {
|
||||
console.error("Error parsing event:", parseError);
|
||||
eventOutputPre.textContent = "Error: Could not parse event JSON. Please try again.";
|
||||
outputDiv.hidden = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nostrEvent) {
|
||||
eventOutputPre.textContent = "Error: Could not create event for signing";
|
||||
outputDiv.hidden = false;
|
||||
return;
|
||||
}
|
||||
|
||||
let signedEvent;
|
||||
|
||||
if (window.nostr) {
|
||||
try {
|
||||
// Try to sign with the NIP-07 extension
|
||||
signedEvent = await window.nostr.signEvent(nostrEvent);
|
||||
console.log("Event signed with extension:", signedEvent);
|
||||
} catch (error) {
|
||||
console.error("Error signing event with extension:", error);
|
||||
// Fall back to signing with nostr-tools
|
||||
if (secretKey) {
|
||||
signedEvent = nostrTools.finalizeEvent(nostrEvent, secretKey);
|
||||
} else {
|
||||
eventOutputPre.textContent = "Error: Could not sign event. No extension or private key available.";
|
||||
outputDiv.hidden = false;
|
||||
return;
|
||||
try {
|
||||
// Try to sign with NostrLogin in preferred order
|
||||
if (NostrLogin && NostrLogin.signEvent) {
|
||||
console.log("Using NostrLogin.signEvent to sign event");
|
||||
signedEvent = await NostrLogin.signEvent(nostrEvent);
|
||||
} else if (NostrLogin && NostrLogin.sign) {
|
||||
console.log("Using NostrLogin.sign to sign event");
|
||||
signedEvent = await NostrLogin.sign(nostrEvent);
|
||||
} else if (window.nostr) {
|
||||
// Fall back to NIP-07 extension
|
||||
console.log("Using NIP-07 extension to sign event");
|
||||
// When using the extension directly, ensure content is a string
|
||||
if (typeof nostrEvent.content !== 'string') {
|
||||
nostrEvent.content = String(nostrEvent.content);
|
||||
}
|
||||
signedEvent = await window.nostr.signEvent(nostrEvent);
|
||||
} else if (secretKey) {
|
||||
// Fall back to nostr-tools
|
||||
console.log("Using nostr-tools to sign event");
|
||||
signedEvent = nostrTools.finalizeEvent(nostrEvent, secretKey);
|
||||
} else {
|
||||
throw new Error("No signing method available");
|
||||
}
|
||||
} else if (secretKey) {
|
||||
// Sign with nostr-tools
|
||||
signedEvent = nostrTools.finalizeEvent(nostrEvent, secretKey);
|
||||
} else {
|
||||
eventOutputPre.textContent = "Error: Could not sign event. No extension or private key available.";
|
||||
|
||||
console.log("Event signed successfully");
|
||||
console.log("Event ID:", signedEvent.id);
|
||||
console.log("Content field type:", typeof signedEvent.content);
|
||||
if (typeof signedEvent.content === 'string') {
|
||||
console.log("Content length:", signedEvent.content.length);
|
||||
console.log("Content preview:", signedEvent.content.length > 50 ?
|
||||
signedEvent.content.substring(0, 50) + "..." :
|
||||
signedEvent.content);
|
||||
} else {
|
||||
console.log("Content is not a string:", signedEvent.content);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error signing event:", error);
|
||||
eventOutputPre.textContent = "Error: Could not sign event. " + String(error);
|
||||
outputDiv.hidden = false;
|
||||
return;
|
||||
}
|
||||
|
@ -1,34 +1,130 @@
|
||||
/* Styles for the HTTP to Nostr converter */
|
||||
|
||||
/* CSS Variables for themes */
|
||||
:root {
|
||||
/* Light theme (default) */
|
||||
--bg-primary: #f8f9fa;
|
||||
--bg-secondary: #ffffff;
|
||||
--bg-tertiary: #f1f8ff;
|
||||
--bg-info: #e2f0fd;
|
||||
--text-primary: #212529;
|
||||
--text-secondary: #495057;
|
||||
--text-tertiary: #6c757d;
|
||||
--border-color: #dee2e6;
|
||||
--accent-color: #0d6efd;
|
||||
--button-primary: #0d6efd;
|
||||
--button-hover: #0b5ed7;
|
||||
--button-success: #28a745;
|
||||
--button-success-hover: #218838;
|
||||
--button-login: #6c3483;
|
||||
--button-login-hover: #5b2c6f;
|
||||
--info-border: #0d6efd;
|
||||
--code-bg: #f8f9fa;
|
||||
}
|
||||
|
||||
/* Dark theme */
|
||||
[data-theme="dark"] {
|
||||
--bg-primary: #121212;
|
||||
--bg-secondary: #1e1e1e;
|
||||
--bg-tertiary: #252836;
|
||||
--bg-info: #1a2634;
|
||||
--text-primary: #e0e0e0;
|
||||
--text-secondary: #b0b0b0;
|
||||
--text-tertiary: #909090;
|
||||
--border-color: #333333;
|
||||
--accent-color: #3f87ff;
|
||||
--button-primary: #3f87ff;
|
||||
--button-hover: #2970e3;
|
||||
--button-success: #2a9745;
|
||||
--button-success-hover: #218838;
|
||||
--button-login: #7c44a3;
|
||||
--button-login-hover: #6c378f;
|
||||
--info-border: #3f87ff;
|
||||
--code-bg: #252525;
|
||||
}
|
||||
|
||||
/* General layout */
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f8f9fa;
|
||||
color: #212529;
|
||||
background-color: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
line-height: 1.6;
|
||||
transition: background-color 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
/* Headings */
|
||||
h1 {
|
||||
color: #343a40;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 2px solid #6c757d;
|
||||
border-bottom: 2px solid var(--border-color);
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #495057;
|
||||
color: var(--text-secondary);
|
||||
margin-top: 25px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
/* Theme toggle */
|
||||
.theme-toggle {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--bg-secondary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 30px;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.theme-toggle-icon {
|
||||
font-size: 18px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
/* Newer button style toggle */
|
||||
.theme-toggle-container {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.theme-toggle-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 30px;
|
||||
padding: 8px 12px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.theme-toggle-btn:hover {
|
||||
background-color: var(--accent-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.theme-toggle-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Info box */
|
||||
.info-box {
|
||||
background-color: #e2f0fd;
|
||||
border-left: 4px solid #0d6efd;
|
||||
background-color: var(--bg-info);
|
||||
border-left: 4px solid var(--info-border);
|
||||
padding: 10px 15px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 0 4px 4px 0;
|
||||
@ -39,9 +135,11 @@ input[type="text"], textarea {
|
||||
width: 100%;
|
||||
padding: 8px 10px;
|
||||
margin-bottom: 15px;
|
||||
border: 1px solid #ced4da;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
background-color: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
textarea {
|
||||
@ -49,8 +147,30 @@ textarea {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
/* Login container */
|
||||
.login-container {
|
||||
margin: 20px 0;
|
||||
padding: 15px;
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--border-color);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.login-status {
|
||||
margin-top: 10px;
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
#nostr-login-container {
|
||||
margin: 10px auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
button {
|
||||
background-color: #0d6efd;
|
||||
background-color: var(--button-primary);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
@ -61,7 +181,7 @@ button {
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0b5ed7;
|
||||
background-color: var(--button-hover);
|
||||
}
|
||||
|
||||
/* Server input section */
|
||||
@ -83,30 +203,30 @@ button:hover {
|
||||
.server-search-result {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
background-color: #ffffff;
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dee2e6;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
/* Output section */
|
||||
#output {
|
||||
margin-top: 30px;
|
||||
padding: 15px;
|
||||
background-color: #ffffff;
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dee2e6;
|
||||
border: 1px solid var(--border-color);
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #f8f9fa;
|
||||
background-color: var(--code-bg);
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
border: 1px solid #dee2e6;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
/* Publish container */
|
||||
@ -114,9 +234,9 @@ pre {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background-color: #f1f8ff;
|
||||
background-color: var(--bg-tertiary);
|
||||
border-radius: 4px;
|
||||
border: 1px solid #b3d7ff;
|
||||
border: 1px solid var(--accent-color);
|
||||
}
|
||||
|
||||
.publish-input-container {
|
||||
@ -129,13 +249,15 @@ pre {
|
||||
.publish-input {
|
||||
flex-grow: 1;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid #ced4da;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
background-color: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.publish-button {
|
||||
background-color: #28a745;
|
||||
background-color: var(--button-success);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 15px;
|
||||
@ -146,15 +268,15 @@ pre {
|
||||
}
|
||||
|
||||
.publish-button:hover {
|
||||
background-color: #218838;
|
||||
background-color: var(--button-success-hover);
|
||||
}
|
||||
|
||||
.publish-result {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
background-color: #ffffff;
|
||||
background-color: var(--bg-secondary);
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dee2e6;
|
||||
border: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
/* QR code container */
|
||||
@ -166,106 +288,15 @@ pre {
|
||||
#qrCode {
|
||||
margin: 0 auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Search results styling */
|
||||
.search-results-list {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.search-result-item {
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-result-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.result-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.result-npub {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.result-nip05 {
|
||||
font-size: 12px;
|
||||
color: #0d6efd;
|
||||
}
|
||||
|
||||
.use-npub-btn {
|
||||
align-self: flex-end;
|
||||
padding: 5px 10px;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
font-family: monospace;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
padding: 10px 15px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
|
||||
#output {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.qr-container {
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#qrCode {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
background-color: white;
|
||||
background-color: var(--bg-secondary);
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-info {
|
||||
margin-top: 8px;
|
||||
font-size: 14px;
|
||||
color: #555;
|
||||
color: var(--text-tertiary);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -274,6 +305,7 @@ button:hover {
|
||||
height: 300px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
background-color: white; /* QR codes need white background */
|
||||
}
|
||||
|
||||
.qr-frame {
|
||||
@ -293,132 +325,63 @@ button:hover {
|
||||
.qr-controls button {
|
||||
margin: 0 5px;
|
||||
padding: 8px 15px;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.qr-controls button:hover {
|
||||
background-color: #45a049;
|
||||
/* Search results styling */
|
||||
.search-results-list {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
background-color: var(--bg-secondary);
|
||||
}
|
||||
|
||||
.qr-error {
|
||||
background-color: #ffeeee;
|
||||
.search-result-item {
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid #ffcccc;
|
||||
border-radius: 4px;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
text-align: center;
|
||||
color: #cc0000;
|
||||
padding: 20px;
|
||||
.search-result-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.qr-error-container {
|
||||
padding: 20px;
|
||||
background-color: #f8f8f8;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
.result-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.qr-error-container h3 {
|
||||
color: #cc0000;
|
||||
margin-top: 0;
|
||||
.result-npub {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #f5f5f5;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
overflow-x: auto;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
.result-nip05 {
|
||||
font-size: 12px;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.info-box {
|
||||
background-color: #e7f3fe;
|
||||
border-left: 6px solid #2196F3;
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
/* NIP-05 lookup styles */
|
||||
.nip05-section {
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
border-left: 3px solid #4CAF50;
|
||||
}
|
||||
|
||||
.nip05-input-container {
|
||||
display: flex;
|
||||
.use-npub-btn {
|
||||
align-self: flex-end;
|
||||
padding: 5px 10px;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.nip05-input {
|
||||
flex-grow: 1;
|
||||
padding: 8px;
|
||||
margin-right: 8px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.nip05-button {
|
||||
white-space: nowrap;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 8px 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nip05-button:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
|
||||
.nip05-result {
|
||||
margin-top: 8px;
|
||||
font-size: 14px;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.nip05-success {
|
||||
color: #008800;
|
||||
}
|
||||
|
||||
.nip05-error {
|
||||
/* Error and success messages */
|
||||
.error-message {
|
||||
color: #cc0000;
|
||||
padding: 10px;
|
||||
background-color: rgba(204, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.use-pubkey-button {
|
||||
margin-left: 10px;
|
||||
font-size: 12px;
|
||||
padding: 3px 8px;
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.use-pubkey-button:hover {
|
||||
background-color: #45a049;
|
||||
.success-message {
|
||||
color: #008800;
|
||||
padding: 10px;
|
||||
background-color: rgba(0, 136, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
margin: 10px 0;
|
||||
}
|
321
package-lock.json
generated
Normal file
321
package-lock.json
generated
Normal file
@ -0,0 +1,321 @@
|
||||
{
|
||||
"name": "http-to-nostr-project",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "http-to-nostr-project",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"qrcode": "^1.5.4"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dijkstrajs": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
|
||||
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-locate": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-try": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"p-limit": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/pngjs": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
|
||||
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/qrcode": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz",
|
||||
"integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dijkstrajs": "^1.0.1",
|
||||
"pngjs": "^5.0.0",
|
||||
"yargs": "^15.3.1"
|
||||
},
|
||||
"bin": {
|
||||
"qrcode": "bin/qrcode"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-main-filename": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/which-module": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
|
||||
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "15.4.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
|
||||
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cliui": "^6.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^4.1.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^4.2.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^18.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "18.1.3",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
||||
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -22,5 +22,8 @@
|
||||
"converter"
|
||||
],
|
||||
"author": "",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"qrcode": "^1.5.4"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user