mirror of
https://github.com/NohamR/pdfy.git
synced 2026-10-10 18:29:55 +00:00
Add better logging system
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import puppeteer from 'puppeteer'
|
||||
import logger from './logger.js'
|
||||
|
||||
const EXTENSION_DIR = path.resolve('./extension/reader-view')
|
||||
const MANIFEST_PATH = path.join(EXTENSION_DIR, 'manifest.json')
|
||||
@@ -8,7 +9,7 @@ const READABILITY_PATH = path.join(EXTENSION_DIR, 'data/inject/Readability.js')
|
||||
|
||||
export function checkExtension () {
|
||||
if (!fs.existsSync(MANIFEST_PATH)) {
|
||||
console.error(
|
||||
logger.error(
|
||||
`Extension not found at: ${EXTENSION_DIR}\n` +
|
||||
'Please extract the extension first:\n' +
|
||||
' mkdir -p extension/reader-view\n' +
|
||||
@@ -17,7 +18,7 @@ export function checkExtension () {
|
||||
process.exit(1)
|
||||
}
|
||||
if (!fs.existsSync(READABILITY_PATH)) {
|
||||
console.error(
|
||||
logger.error(
|
||||
`Readability.js not found at: ${READABILITY_PATH}\n` +
|
||||
'The extension may be incomplete. Please re-extract it.'
|
||||
)
|
||||
@@ -34,7 +35,7 @@ export function getExtensionDir () {
|
||||
}
|
||||
|
||||
export async function launchBrowser () {
|
||||
console.log(`Launching browser with extension: ${EXTENSION_DIR}`)
|
||||
logger.debug(`Launching browser with extension: ${EXTENSION_DIR}`)
|
||||
const browser = await puppeteer.launch({
|
||||
headless: true,
|
||||
ignoreDefaultArgs: [
|
||||
@@ -67,6 +68,6 @@ export async function discoverExtensionId (browser) {
|
||||
if (!extId) {
|
||||
throw new Error('Could not discover Reader View extension ID')
|
||||
}
|
||||
console.log(`Discovered extension ID: ${extId}`)
|
||||
logger.debug(`Discovered extension ID: ${extId}`)
|
||||
return extId
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@ program
|
||||
'-o, --output <path>',
|
||||
'output file path (default: ./output/<title>.pdf)'
|
||||
)
|
||||
.option(
|
||||
'-l, --log-level <level>',
|
||||
'logging level (fatal, error, warn, info, debug)'
|
||||
)
|
||||
.addHelpText(
|
||||
'after',
|
||||
`
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import logger from './logger.js'
|
||||
|
||||
export function loadPreferences (prefsPath) {
|
||||
if (!prefsPath || !fs.existsSync(prefsPath)) return {}
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(prefsPath, 'utf-8'))
|
||||
} catch (e) {
|
||||
console.warn(`Warning: could not parse preferences file: ${prefsPath}`)
|
||||
logger.warn(`Warning: could not parse preferences file: ${prefsPath}`)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
15
src/index.js
15
src/index.js
@@ -2,6 +2,7 @@ import process from 'node:process'
|
||||
import path from 'node:path'
|
||||
import { parseArgs, VALID_THEMES } from './cli.js'
|
||||
import { loadPreferences, readCustomCss } from './config.js'
|
||||
import logger from './logger.js'
|
||||
import {
|
||||
checkExtension,
|
||||
launchBrowser,
|
||||
@@ -37,20 +38,20 @@ async function main () {
|
||||
|
||||
const theme = opts.theme || preferences.mode || 'light'
|
||||
if (!VALID_THEMES.includes(theme)) {
|
||||
console.error(
|
||||
logger.error(
|
||||
`Invalid theme "${theme}". Valid themes: ${VALID_THEMES.join(', ')}`
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
preferences.mode = theme
|
||||
console.log(`Theme: ${theme}`)
|
||||
logger.info(`Theme: ${theme}`)
|
||||
|
||||
let customCss = null
|
||||
if (opts.css) {
|
||||
customCss = readCustomCss(path.resolve(opts.css))
|
||||
if (customCss !== null) {
|
||||
preferences['user-css'] = customCss
|
||||
console.log(`Custom CSS loaded: ${path.resolve(opts.css)}`)
|
||||
logger.info(`Custom CSS loaded: ${path.resolve(opts.css)}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +60,7 @@ async function main () {
|
||||
try {
|
||||
const extId = await discoverExtensionId(browser)
|
||||
|
||||
console.log(`Fetching article: ${url}`)
|
||||
logger.info(`Fetching article: ${url}`)
|
||||
const articlePage = await browser.newPage()
|
||||
await articlePage.goto(url, { waitUntil: 'networkidle0', timeout: 30000 })
|
||||
const article = await extractArticle(articlePage, getReadabilityPath())
|
||||
@@ -83,7 +84,7 @@ async function main () {
|
||||
'?id=1',
|
||||
`&url=${encodeURIComponent(url)}`
|
||||
].join('')
|
||||
console.log(`Opening Reader View: ${readerUrl}`)
|
||||
logger.debug(`Opening Reader View: ${readerUrl}`)
|
||||
|
||||
const readerPage = await browser.newPage()
|
||||
await readerPage.goto(readerUrl, { waitUntil: 'load', timeout: 30000 })
|
||||
@@ -109,11 +110,11 @@ async function main () {
|
||||
await pdfPage.close()
|
||||
} finally {
|
||||
await browser.close()
|
||||
console.log('Browser closed.')
|
||||
logger.info('Browser closed.')
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error('Fatal error:', err)
|
||||
logger.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
22
src/logger.js
Normal file
22
src/logger.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import pino from 'pino'
|
||||
|
||||
function resolveLevel () {
|
||||
if (process.env.LOG_LEVEL) return process.env.LOG_LEVEL
|
||||
const idx = process.argv.indexOf('--log-level')
|
||||
if (idx !== -1 && process.argv[idx + 1]) return process.argv[idx + 1]
|
||||
return 'info'
|
||||
}
|
||||
|
||||
const logger = pino({
|
||||
level: resolveLevel(),
|
||||
transport: {
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
colorize: true,
|
||||
translateTime: 'HH:MM:ss',
|
||||
ignore: 'pid,hostname'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default logger
|
||||
@@ -1,10 +1,11 @@
|
||||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import logger from './logger.js'
|
||||
|
||||
const HIGHLIGHT_CSS =
|
||||
'<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/default.min.css">'
|
||||
const HIGHLIGHT_JS =
|
||||
'<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"><script><script>hljs.highlightAll();<script>'
|
||||
'<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"><\/script><script>hljs.highlightAll();<\/script>'
|
||||
|
||||
export function getOutputFilename (title, outputDir) {
|
||||
const safe = title
|
||||
@@ -42,7 +43,7 @@ export function enhanceHtml (html, customCss) {
|
||||
|
||||
export async function generatePdf (page, html, outputPath) {
|
||||
await page.setContent(html, { waitUntil: 'networkidle0' })
|
||||
console.log(`Generating PDF: ${outputPath}`)
|
||||
logger.info(`Generating PDF: ${outputPath}`)
|
||||
await page.pdf({
|
||||
path: outputPath,
|
||||
format: 'A4',
|
||||
@@ -54,5 +55,5 @@ export async function generatePdf (page, html, outputPath) {
|
||||
right: '0mm'
|
||||
}
|
||||
})
|
||||
console.log(`PDF saved: ${outputPath}`)
|
||||
logger.info(`PDF saved: ${outputPath}`)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import fs from 'node:fs'
|
||||
import logger from './logger.js'
|
||||
|
||||
export async function extractArticle (page, readabilityPath) {
|
||||
const readabilitySource = fs.readFileSync(readabilityPath, 'utf-8')
|
||||
@@ -51,7 +52,7 @@ export async function extractArticle (page, readabilityPath) {
|
||||
if (!article) {
|
||||
throw new Error('Failed to extract article content with Readability')
|
||||
}
|
||||
console.log(
|
||||
logger.info(
|
||||
`Extracted article: ${article.title} (${article.length} chars, reading ${article.readingTimeMinsFast}-${article.readingTimeMinsSlow} min` +
|
||||
(article.published_time ? `, ${article.published_time}` : '') +
|
||||
')'
|
||||
@@ -90,7 +91,7 @@ export async function storeArticle (extPage, extId, articleId, article) {
|
||||
},
|
||||
{ id: articleId, article }
|
||||
)
|
||||
console.log('Article stored in extension IndexedDB')
|
||||
logger.debug('Article stored in extension IndexedDB')
|
||||
}
|
||||
|
||||
export async function setExtensionPreferences (page, extId, prefs) {
|
||||
@@ -105,11 +106,11 @@ export async function setExtensionPreferences (page, extId, prefs) {
|
||||
})
|
||||
})
|
||||
}, prefs)
|
||||
console.log(`Extension preferences set: ${Object.keys(prefs).length} key(s)`)
|
||||
logger.debug(`Extension preferences set: ${Object.keys(prefs).length} key(s)`)
|
||||
}
|
||||
|
||||
export async function waitForReaderView (page) {
|
||||
console.log('Waiting for Reader View to render article...')
|
||||
logger.debug('Waiting for Reader View to render article...')
|
||||
await page.waitForFunction(
|
||||
() => {
|
||||
const title = document.title
|
||||
@@ -126,7 +127,7 @@ export async function waitForReaderView (page) {
|
||||
},
|
||||
{ timeout: 60000 }
|
||||
)
|
||||
console.log('Article rendered.')
|
||||
logger.info('Article rendered.')
|
||||
}
|
||||
|
||||
export async function extractRenderedContent (page, baseUrl) {
|
||||
|
||||
Reference in New Issue
Block a user