今日已更新 166 条资讯 | 累计 40611 条内容
关于我们

标签:#java

找到 1263 篇相关文章

AI 资讯

How to convert a folder of PNGs to one PDF without uploading the files

A simple browser-local PNG-to-PDF workflow For this kind of job, the useful workflow is straightforward: Select the PNG, JPG, or JPEG files. Put the pages in the order they should appear. Choose a page size and margins if the document needs them. Export one PDF. The important detail is where the conversion happens. A browser-local PNG-to-PDF tool processes the images in the browser instead of uploading them to a conversion server. That makes it easier to keep control of source files while still producing one shareable PDF. When this is useful This workflow is handy for: combining screenshots into a bug report or handoff document; turning scanned pages into one file for email or printing; arranging portfolio images or design exports in a deliberate order; and collecting receipts or reference images without making a separate document first. Before exporting, check the page order and decide whether each page should match the image, A4, or US Letter. A preview is useful here: it catches a stray portrait page, an oversized margin, or a screenshot in the wrong position before the PDF is created. The tool I use for this I maintain PNG Binder , a free PNG-to-PDF converter for this specific workflow. It accepts up to 50 PNG, JPG, or JPEG images, lets you arrange them, and creates one PDF locally in the browser. It does not require an account, and the images are not sent to a conversion server. It creates an image-based PDF, so it does not perform OCR or rebuild text and tables. If that is the kind of result you need, try it and let me know whether page ordering, page settings, or browser compatibility could be improved. Disclosure: I am the maker and operator of PNG Binder.

2026-09-05 原文 →
AI 资讯

Validate Card Brands in Node.js with Luhn and credit-card-brand-detector

When a checkout form receives a card number, the first useful question is often not whether the payment will be approved. It is whether the input is structurally plausible and which network rules should be shown to the user. The open-source credit-card-brand-detector package provides that small client-side or server-side building block. It detects 11 brands, removes spaces and hyphens, and applies a Luhn checksum. It has zero runtime dependencies and exposes CommonJS functions for validation and brand detection. This tutorial builds a minimal Node.js check, verifies the result with known test numbers, and explains what this kind of validation cannot tell you. TL;DR Install version 1.0.1 , call validateCreditCard when you need both a boolean result and a brand, and call detectBrand when you only need the network name. The package does not contact a payment processor, authorize a transaction, tokenize data, or prove that a card exists. Prerequisites You need: Node.js 12 or newer. The package declares >=12.0.0 in its metadata. npm. A terminal and a small JavaScript file. The package is released under the MIT license . The examples below target the published npm package version 1.0.1 , which is also the version I installed for this walkthrough. Install the package Create a directory for the example and install the pinned version: mkdir card-check-example cd card-check-example npm init -y npm install credit-card-brand-detector@1.0.1 Pinning the version makes the example reproducible. If you use a different version later, check its README and package metadata before copying the behavior into a production application. Build the smallest useful check Create check-card.js : const { validateCreditCard , detectBrand , getBrand , } = require ( ' credit-card-brand-detector ' ); const formattedVisa = ' 4532 0151-1283-0366 ' ; const mastercard = ' 5555555555554444 ' ; console . log ( validateCreditCard ( formattedVisa )); console . log ( detectBrand ( mastercard )); console . log

2026-09-05 原文 →
AI 资讯

Blume: Zero-Config Docs Framework That Turns a Markdown Folder into an AI-Ready Website

Blume is an open-source documentation framework that converts Markdown into a complete documentation site. Built with Astro and Vite, it requires only Node.js and a single Markdown file for setup. The framework supports various configurations, offers automatic SEO features, and includes tools for document testing. It facilitates migration from other documentation systems. By Daniel Curtis

2026-09-05 原文 →
AI 资讯

Designing Type-Safe Multi-Calendar Primitives in TypeScript Without 'any'

Handling dates in JavaScript is notoriously error-prone. While ECMAScript's native Date object has well-documented pitfalls—uncontrolled mutability, 0-indexed months, and automatic local-timezone conversions—there is an even larger blind spot in existing libraries like date-fns , dayjs , and luxon : non-Gregorian calendar systems and regional legal date semantics. Global and regional enterprise applications (e.g., banking, fintech, tax compliance, healthcare, public sector, and international travel) frequently operate under official non-Gregorian legal rules: 🇹🇭 Thai Buddhist Era ( พ.ศ. = CE + 543) with official government numbering and Royal Gazette formatting presets. 🇯🇵 Japanese Imperial Era (Reiwa 令和, Heisei 平成, Showa 昭和) with exact historical day-of-event rollover boundaries (e.g., May 1, 2019 Reiwa 1 Gannen). 🇹🇼 Taiwan Minguo (民國紀年) used across municipal and legal filings. 🇸🇦 Islamic Hijri (Astronomical Umm al-Qura, Islamic Civil, and Tabular systems). 🇮🇷 Persian / Solar Hijri (Jalali Khayyami 33-year astronomical leap cycle). 🇮🇳 Indian National Saka Calendar adopted as the official civil calendar of India. To solve this without bloating runtime bundles, dragging in heavy astronomical dependencies, or resorting to loose string parsing and any , we engineered Chronera — an open-source, zero-dependency date and multi-calendar engine written in strict TypeScript. In this deep dive, we'll examine the architectural design decisions, mathematical foundations, and type-level techniques used to model complex multi-calendar domains safely. 1. The Architectural Dilemma: Monolithic Objects vs. Tagged Primitives Most date libraries wrap a native timestamp inside a single monolithic object. The instant you create a date to represent someone's birth date (e.g., 1995-05-15 ), the engine binds it to an hour, minute, second, and UTC timezone offset. When that object is serialized to JSON or transferred across servers in different timezones, classic off-by-one errors happen: //

2026-09-05 原文 →
AI 资讯

CodePen: CryptoCap Landing Page

Crypto landing page with a sleek dark/light mode toggle, stylish Chart.js market graph, and smooth scroll animations using sal.js. Built with Tailwind CSS for a pixel-perfect, fully responsive design. Design inspired by: https://www.figma.com/community/file/1047142300578798855/cryptocurrency-landing-page-dark-mode

2026-09-05 原文 →
AI 资讯

useEffect Fired Twice and It Found a Real Bug

useEffect fired twice, on mount, every single time, in development only. The API call inside it — a POST that created a resource — ran twice, and for about a day we had duplicate records showing up in a table that should have had exactly one insert per page load. The first reaction, and why it was wrong The instinct is to assume a bug — a rerender loop, a missing dependency, something actually broken. React 18's Strict Mode, in development, deliberately mounts, unmounts, and remounts every component once, specifically to surface effects that aren't properly cleaned up. It's not a bug in your code causing a double-fire; it's a bug in your code being caught by a feature built to catch exactly this. useEffect (() => { console . log ( ' mount ' ); // logs twice in dev, once in production const subscription = subscribeToUpdates (); // no cleanup — this is the actual problem Strict Mode is surfacing }, []); Production builds don't do this double-invocation — it's development-only, and specifically Strict-Mode-only, which is why the duplicate inserts we saw locally would eventually have shown up in production too, just less predictably, under a race condition instead of a guaranteed double-fire. Why this is a feature and not noise to suppress An effect that safely tolerates being mounted, torn down, and mounted again is an effect that correctly declares its dependencies and cleans up after itself — which is exactly the property you need for effects to behave correctly under React's concurrent features generally, not just under Strict Mode specifically. The double-invocation in development is a cheap, automatic test for that property, running on every single page load without you writing a test for it. The actual fix useEffect (() => { const subscription = subscribeToUpdates (); return () => subscription . unsubscribe (); // cleanup makes remounting safe }, []); For our specific case — a POST that shouldn't fire twice regardless of mount behavior — the deeper fix was recogn

2026-09-05 原文 →
AI 资讯

Stop changing your sprite sheet to fix animation speed

An eight-frame animation does not have a fixed duration. At 8 fps it lasts one second; at 12 fps it lasts two-thirds of a second; at 16 fps it lasts half a second. Before drawing or generating more frames, check whether the problem is missing poses or the time each pose stays on screen. We maintain FrameSprite, a browser workspace for game assets. This is a timing and export note, not a claim that a particular frame count makes AI animation reliable. The equations work with hand-drawn sprites too. Three numbers that are easy to mix up Source FPS describes how a recording was sampled. Frame count is the number of entries you put in an animation. Playback FPS controls how fast those entries advance in the game. A 24 fps source video can provide eight selected poses that you play at 12 fps. You do not need to preserve every source frame. For equal holds, forward playback and a speed multiplier of 1: duration_seconds = frame_count / playback_fps frame_hold_ms = 1000 / playback_fps fps_for_target = frame_count * 1000 / target_duration_ms Same eight frames Hold per frame Full loop 8 fps 125 ms 1.000 s 12 fps 83.333… ms 0.667 s 16 fps 62.5 ms 0.500 s You changed the cadence without changing one pixel of the sprite sheet. A test you can reproduce Use the public eight-frame sample . Keep the same frames, order, canvas and pivot for all three trials. Change only playback FPS between 8, 12 and 16. Check the animation alone at its intended game size. Run it beside actual movement or attack timing. If cadence improves but a foot or weapon still jumps, inspect the missing phase instead of raising FPS again. If every frame jumps by a small amount, inspect canvas and pivot alignment. If the pause happens only at the seam, look for an accidental duplicate endpoint. The sample makes the arithmetic test repeatable. It is not evidence that eight frames is the right budget for every character or action. Do not accumulate rounded timestamps At 24 fps, one hold is 41.666… milliseconds. St

2026-09-05 原文 →
开发者

What a Language Needs Before It Can Compile Itself

Code: Megapixel99/lambda-language lm is a small low-level language I wrote: static types, explicit memory, no closures, no garbage collector, and four independent backends that emit C, WebAssembly, ARM64 and bytecode for a VM. Its compiler is about 4,400 lines of JavaScript. The obvious next question is whether the language can compile itself, and the obvious first step is the lexer, which is 129 lines. In lm the same lexer is 355 lines. That ratio is the finding, because almost none of it is lm being a verbose language. Six specific absences account for nearly all of it, and writing them down was a planned milestone rather than an afterthought: the point of porting the lexer first was to find out what the language could not do while the port was still small enough to abandon. The one that cost the most src/lexer.js has a single advance(n) that moves pos , line and col together, called from 14 places. lm had no way to take the address of a scalar local, so a function could not mutate a caller's variable, and a function returning three values would need a struct allocated on every call. So advance does not exist. All 14 sites write pos += 1; col += 1; inline, and the newline case writes the three-line variant. That is the single largest source of the size difference, and it also caused the only correctness bug in the port. Column counting inside a string literal has to skip UTF-8 continuation bytes, and because the logic is inlined rather than centralised there is no one place to fix it. The two comment scanners over-count a column in exactly the same way. They get away with it only because a comment always ends at a newline, which resets the column before anything reads it. That is worth sitting with. A centralised advance would have been fixed once and been right in all three places. Instead the code is right in one place by correction and in two others by luck, and the luck is load-bearing: change what terminates a comment and two latent bugs become live ones. Dup

2026-09-05 原文 →
AI 资讯

Solid-Vue | The Minimalist Vue + Vite Web Frameworks (No relation to SolidJS or SolidStart at all)

Solid-Vue is a lightweight Vue + Vite framework for small and growing businesses. File-based routing, a built-in server layer powered by h3, and zero extra config to wire together. Features File-based routing — every file in src/pages becomes a route automatically, via unplugin-vue-router. A server, built in — src/server/api holds your API endpoints, served through h3 alongside your frontend. One dev server, one deploy. Vite underneath — instant startup and near-instant HMR. State management ready — Pinia is wired in out of the box. Extensible via add-ons — install Tailwind CSS, icon sets, form validation, i18n, and more with the companion solid-vue-cli. Quick start Don't install this package directly — scaffold a new project instead: npm create solid-vue@latest my-app cd my-app npm install npm run dev Usage vite.config.ts import { defineConfig } from ' vite ' import { solidVue } from ' solid-vue ' export default defineConfig ({ plugins : [ solidVue ({ mode : ' spa ' }) ] }) src/main.ts import { createSolidApp } from ' solid-vue/client ' import App from ' ./App.vue ' const { app , router } = createSolidApp ( App ) router . isReady (). then (() => { app . mount ( ' #app ' ) }) src/server/api/hello.ts import { defineEventHandler } from ' solid-vue/server ' export default defineEventHandler (() => { return { message : ' Hello from Solid-Vue! ' } }) Plugin options solidVue ({ mode : ' spa ' , // 'spa' | 'ssr' | 'ssg' — default: 'spa' apiPrefix : ' /api ' , // prefix for file-based API routes — default: '/api' optimizeCWV : true , // inject Core Web Vitals meta/preconnect tags — default: true }) Package exports Entry Use solid-vue The Vite plugin ( solidVue ), used in vite.config.ts solid-vue/client createSolidApp() — bootstraps Vue, Vue Router, and Pinia solid-vue/server Re-exported h3 utilities ( defineEventHandler , readBody , useSession , etc.) for your API routes Add-ons Add optional integrations to an existing project with the CLI: npx solid-vue add tailwind npx so

2026-09-05 原文 →
AI 资讯

Architecting Enterprise Angular with Signals: Zoneless Reactivity and 60fps Performance

Architecting Enterprise Angular with Signals: Zoneless Reactivity and 60fps Performance For nearly a decade, Angular relied on Zone.js to intercept asynchronous browser events and trigger top-down dirty checking across the entire component tree. In large enterprise dashboards displaying live telemetry, grid streams, and complex forms, this model leads directly to frame drops and memory leaks. With Angular 19+, fine-grained Signals provide a reactive paradigm where the framework tracks exact DOM dependencies at compile-time and updates only the precise DOM nodes that changed, unlocking 60fps zoneless execution . Architecture & Interview Cheat Sheet Feature Legacy RxJS / Zone.js Angular Signals (Modern) Change Detection Dirty-checks entire component tree Fine-grained single DOM node updates Memory Lifecycle Manual takeUntilDestroyed subscriptions Automatic graph cleanup without memory leaks Derivations Complex combineLatest / switchMap Lazy, memoized computed(() => ...) Zone.js Overhead Monkey-patches all browser async APIs 0 overhead ( provideExperimentalZonelessChangeDetection() ) 1: Clean Reactive State with Signals import { Component , computed , signal , effect , inject } from ' @angular/core ' ; export interface TelemetryPacket { id : string ; latencyMs : number ; status : ' healthy ' | ' degraded ' | ' critical ' ; } @ Component ({ selector : ' app-telemetry-monitor ' , standalone : true , template : ` <div class="card"> <h3>Live Ingestion Monitor</h3> <p>Total Packets: {{ packetCount() }}</p> <p>Average Latency: {{ averageLatency().toFixed(2) }}ms</p> <span [class.badge-warn]="isDegraded()"> {{ isDegraded() ? 'DEGRADED PERFORMANCE' : 'NOMINAL' }} </span> </div> ` }) export class TelemetryMonitorComponent { // Primary Writable Signal readonly packets = signal < TelemetryPacket [] > ([]); // Derived Computed Signals (Memoized, evaluated lazily on read) readonly packetCount = computed (() => this . packets (). length ); readonly averageLatency = computed (() => {

2026-09-05 原文 →
AI 资讯

The CORS Header Was Right There and the Browser Blocked It Anyway

The browser console showed exactly what CORS errors always show — a request blocked for violating the same-origin policy — except the response headers, visible in the network tab, clearly included Access-Control-Allow-Origin: * . The header the browser wanted was right there. The browser rejected the request anyway. The detail that's easy to miss in the network tab Chrome's network inspector, by default, coalesces duplicate header names into a single display line — so Access-Control-Allow-Origin: * shown once in the UI can actually mean the header was sent twice by the server, and the browser is showing you a merged, deduplicated view rather than the literal wire response. curl -s -D - https://api.example.com/data -o /dev/null | grep -i access-control Access-Control-Allow-Origin: * Access-Control-Allow-Origin: https://app.example.com Two separate headers, both valid individually, sent by two different layers that each thought they were the one responsible for CORS: our nginx reverse proxy had a blanket add_header Access-Control-Allow-Origin *; for general API access, and the application server behind it independently set a specific origin for authenticated routes. Neither config was wrong on its own. Together, they produced a response with the header appearing twice — and per the Fetch spec, a response with multiple Access-Control-Allow-Origin values is treated as invalid, so the browser blocks the request rather than guessing which one you meant. Why this is worse than a missing header A missing CORS header fails immediately, obviously, the same way every time. A duplicate header fails in a way that looks, from the response body alone, like the header is present and correct — because it is present, twice, which is precisely the state that trips the spec's validation. Every piece of evidence you'd normally check says "this should work," and it still doesn't. The fix Removed the blanket nginx header and let the application server be the single source of truth for COR

2026-09-04 原文 →
AI 资讯

The compiler was never what you wanted

You have an orders topic on a Kafka cluster, its values encoded with Avro against a schema in the Schema Registry . You want the orders worth more than fifty euros on a topic of their own, and you have decided to do it with Kafka Streams — a JVM library, your code, your deployment. The schema has five fields: { "type" : "record" , "name" : "Order" , "namespace" : "com.alginte.demo" , "fields" : [ { "name" : "orderId" , "type" : "string" }, { "name" : "customerId" , "type" : "string" }, { "name" : "item" , "type" : "string" }, { "name" : "quantity" , "type" : "int" }, { "name" : "priceEur" , "type" : "double" }]} You want one line of logic over them: quantity * priceEur > 50 . Here is everything standing between that line and a topic of big orders. Seven steps The route Confluent's own examples take, and many projects with them: Get the schema out of the registry and into your repository as an .avsc — or, if your team owns the schema in the repository and publishes it to the registry, the other way round. Whichever copy you call the source, there are now two that can disagree. Add the code generator to your build. Configure it — source and output directories, and the string type. Build , producing Order.java under target/generated-sources . Write the topology against the generated class. Package the application, with the schema, the class and the serde. Deploy it somewhere that runs a JVM. Steps 2 and 3 are this, once — in Maven, though Gradle's equivalent has the same shape: <plugin> <groupId> org.apache.avro </groupId> <artifactId> avro-maven-plugin </artifactId> <version> 1.12.1 </version> <executions><execution> <phase> generate-sources </phase> <goals><goal> schema </goal></goals> <configuration> <sourceDirectory> ${project.basedir}/src/main/avro </sourceDirectory> <!-- without this, string fields generate as CharSequence, not String; Confluent's own examples set it for the same reason --> <stringType> String </stringType> </configuration> </execution></executio

2026-09-04 原文 →
AI 资讯

Does That "Free Online PDF" Tool Upload Your File? How to Tell.

Most free online PDF tools work by uploading your document to a server, processing it there, and sending it back. For a lot of files that's fine. For a signed contract, a payslip, a medical form, or a scanned ID, it's the entire privacy problem: your document now lives on someone else's machine, subject to their logging, retention, and breach exposure. It doesn't have to work that way. A modern browser can split, merge, compress, sign, and even OCR a PDF without the file ever leaving your device — using libraries like pdf-lib , pdf.js , jsPDF and SheetJS that run entirely in JavaScript. How to tell an uploader from a client-side tool You don't have to trust a marketing claim. Two checks settle it: Watch the network. Open your browser's DevTools → Network tab, then run the tool on a file. If you see your file leave in a POST/PUT request, it uploaded. A client-side tool shows no upload of the document itself. Pull the plug. Load the page, then turn off Wi-Fi and try the tool again. A client-side tool keeps working offline. An uploader breaks the moment the network is gone. The honest tools pass both tests. If a site can't work offline, your file is going somewhere. The trade-offs, stated honestly Client-side processing isn't a free lunch, and any tool that pretends it is should make you suspicious: Memory. Very large PDFs are held in browser memory, so there's a ceiling a server wouldn't have. Speed. OCR in WebAssembly is slower than a server GPU. It's private, not fast. Fidelity. Converting PDF → Word transfers the text , not the layout — the same is true of every converter, but a client-side one can't hide it behind a server. Compression limits. A PDF shrinks by downsampling embedded images or rasterizing pages; a small or text-only PDF may not shrink at all, and rasterizing removes selectable text. We built 24 client-side PDF tools on exactly this principle and wrote down where each limit is, rather than papering over them. If you're evaluating any online PDF tool

2026-09-04 原文 →
AI 资讯

Twenty Years of jQuery: How a Little Library Rewired Web Development

jQuery, created by John Resig and released in 2006, is a JavaScript library that simplifies HTML manipulation, event handling, animation, and Ajax. It enabled easier web development by providing an accessible API across browsers. While its use has declined with the rise of modern frameworks, jQuery remains prevalent on a significant portion of websites today. By Daniel Curtis

2026-09-04 原文 →
AI 资讯

Protótipos: como a herança realmente funciona no JavaScript

Introdução Muitas linguagens como C#, Java, entre outras são descritas como orientadas a objeto, possibilitando o paradigma Programação Orientada a Objeto (POO). No entanto, quando falamos de JS, sabemos que por mais que existam objetos, ela é dita como uma linguagem orientada a protótipos, mas o que de fato isso significa, qual problema isso resolve e como muda a maneira como programamos? O problema Tanto a orientação a objeto quanto a orientação a protótipo lidam, entre outras coisas, com a questão de como a herança vai funcionar em determinada linguagem e é justamente nesse ponto que as duas abordagens mais se diferem. Em linguagens orientadas a objetos as classes de fato existem, contendo propriedades, métodos e servem como molde para a criação de objetos. Com isso, todo objeto criado a partir de uma classe herda suas propriedades e métodos ficando acessíveis para uso. Como não existem Classes de fato em JavaScript, a herança ocorre de maneira diferente, de objeto para objeto, ligados através da propriedade [[Prototype]] que possui uma referência ao seu protótipo, fazendo com que determinado objeto herde de seu protótipo propriedades e métodos que nunca foram definidos nele. Exemplo com array Quando criamos um array, seja de forma literal com [], ou de forma explícita com new Array(), o resultado final é o mesmo: um array cujo [[Prototype]] aponta para o Array.prototype. Essa propriedade .prototype possui um objeto contendo todas as propriedades e métodos que o [[Prototype]] referencia, possibilitando que todos os arrays possam usar métodos como push, pop, map, filter… Com isso, se irmos além e conferirmos o [[Prototype]] do Array.prototype vamos perceber que ele aponta para o Object.prototype que contém propriedades e métodos também disponível em todo essa cadeia que chamamos de prototype chain . Por fim, se tentarmos visualizar o protótipo do Object.prototype veremos que é null, pois ele representa o último elo dessa cadeia. Teste o código abaixo para ver na p

2026-09-04 原文 →
AI 资讯

AI Can Write Your Code. Can It Actually Debug It?

AI Can Write Your Code. Can It Actually Debug It? AI coding assistants have changed how developers write software. You can describe a feature, generate a function, refactor a component, write a test, or explain an unfamiliar codebase in seconds. But there is one part of software development that is still surprisingly difficult: figuring out why something broke. Writing code and investigating a failure are two very different problems. When an application crashes, the answer usually isn't sitting inside the error message. You have to reconstruct what happened. The Problem With "Just Read the Stack Trace" Consider this Node.js error: TypeError: Cannot read properties of undefined (reading 'email') at getUser (/app/services/user.js:42:18) at processRequest (/app/controllers/auth.js:87:12) at async handler (/app/routes/auth.js:31:5) The immediate problem appears obvious. Something is undefined. But what caused it? Maybe: A database query returned no user. An API returned an unexpected response. Authentication middleware failed. A promise returned an unexpected value. A user record exists but its profile doesn't. An earlier function silently produced invalid state. The stack trace tells you where the program finally failed . It doesn't necessarily tell you where the bug began . That's the difference between error reporting and debugging investigation. AI Coding vs AI Debugging Most AI coding workflows look something like this: Developer ↓ Prompt ↓ AI ↓ Code Debugging is different: Failure ↓ Error ↓ Stack trace ↓ Execution path ↓ Application state ↓ Root cause ↓ Fix The AI needs to reason across that chain. Simply asking: "What does this error mean?" usually produces a list of possible explanations. That's useful, but it's not necessarily an investigation. A better question is: "Given this failure and its context, what is the most likely root cause, what evidence supports it, and how can I reproduce it?" That's a much more interesting problem for AI. A Simple JavaScript De

2026-09-04 原文 →
AI 资讯

Safely parsing email files in the browser

An email file is not just text plus a few attachments. It can contain HTML, nested MIME parts, misleading filenames, inline resources, remote tracking pixels, malformed encodings, and enough data to exhaust a browser tab. Moving parsing into the browser removes an upload from the architecture, but it does not automatically make the viewer safe. It changes the security job: untrusted content is now being interpreted next to the user’s active web session. This is the checklist I use for a local EML and winmail.dat/TNEF reader. Treat every parsed field as untrusted The sender, subject, recipient, filename, MIME type, and message body all came from a file. Render headers and filenames as text, never by concatenating HTML. The same applies to errors. A parser exception can include a filename or fragment of malformed input. Showing that message verbatim may leak data into logs or turn it into markup. Map parser failures to stable error categories, then display a controlled explanation. Normalize into one internal model EML and TNEF have different container structures, but the UI should not contain two independent security implementations. Both parsers can produce a common message model: subject, sender, to, cc, date, plain body, sanitized HTML candidate, attachments[] { safe filename, MIME type, bytes, inline flag, content ID, content location } The normalization layer is the right place to enforce per-source limits and reject unsupported structures. The viewer and download code then work against the same constrained data regardless of input format. Sanitize HTML as hostile input Email HTML was designed for mail clients, not for direct insertion into an application DOM. A conservative policy removes: scripts and event handlers; forms and interactive controls; iframe , object , and embed elements; styles and CSS URLs; unsafe protocols; executable or unexpected embedded content. Use a maintained sanitizer with a pinned version, but do not stop at its default configuration.

2026-09-04 原文 →
AI 资讯

eBay's Browse API Doesn't Return Sold Listings. Here Is a Node.js Alternative

If you are building a pricing, resale, or inventory tool, active listings answer the wrong question. The price a seller asks for an item is not necessarily the price a buyer paid. eBay's public Browse API returns active inventory. Marketplace Insights covers sold history, but access is restricted. That leaves many developers maintaining search-page parsers or using a sold-data provider. This example uses CompSniper because it returns completed listings and a price summary through one GET request. Disclosure: I am Marc, the owner of CompSniper. Make one sold-listings request Node.js 20 and newer already include fetch , URLSearchParams , and request timeouts, so this example does not need an HTTP package. const params = new URLSearchParams ({ keyword : " sony wh-1000xm5 " , count : " 10 " , ebaySite : " ebay.com " , itemCondition : " used " , }); const response = await fetch ( `https://api.compsniper.com/v1/scrape? ${ params } ` , { headers : { Authorization : `Bearer ${ process . env . COMPSNIPER_API_KEY } ` , }, signal : AbortSignal . timeout ( 75 _000 ), }, ); const data = await response . json (); if ( ! response . ok ) { throw new Error ( data . error ?? `HTTP ${ response . status } ` ); } console . log ( " Listings: " , data . totalItems ); console . log ( " Median: " , data . summary . median , data . summary . currency ); console . log ( " Range: " , data . summary . p25 , " to " , data . summary . p75 ); for ( const item of data . items . slice ( 0 , 5 )) { console . log ( item . title , item . soldPrice , item . endedAt ); } Keep the API key in a server, worker, or serverless function. Do not place it in browser JavaScript. Select the buyer's marketplace The marketplace matters. A UK reseller normally wants UK sold listings and prices in pounds, not US listings in dollars. const params = new URLSearchParams ({ keyword : " iphone 15 pro -case -charger " , ebaySite : " ebay.co.uk " , count : " 100 " , itemCondition : " used " , minPrice : " 250 " , maxPrice :

2026-09-04 原文 →
AI 资讯

Namaste JavaScript — Complete Notes

Full interview-prep notes, ##Episode 1 through 29. Episode 1 : Execution Context ============================== Everything in JS happens inside the execution context. Imagine a sealed-off container inside which JS runs. It is an abstract concept that hold info about the env. within the current code is being executed. In the container the first component is memory component and the 2nd one is code component Memory component has all the variables and functions in key value pairs. It is also called Variable environment. Code component is the place where code is executed one line at a time. It is also called the Thread of Execution. JS is a synchronous, single-threaded language Synchronous:- In a specific synchronous order. Single-threaded:- One command at a time. Episode 2 : How JS is executed & Call Stack ============================================= When a JS program is ran, a global execution context is created. The execution context is created in two phases. Memory creation phase - JS will allocate memory to variables and functions. Code execution phase Let's consider the below example and its code execution steps: var n = 2 ; function square ( num ) { var ans = num * num ; return ans ; } var square2 = square ( n ); var square4 = square ( 4 ); The very first thing which JS does is memory creation phase, so it goes to line one of above code snippet, and allocates a memory space for variable 'n' and then goes to line two, and allocates a memory space for function 'square'. When allocating memory for n it stores 'undefined', a special value for 'n'. For 'square', it stores the whole code of the function inside its memory space. Then, as square2 and square4 are variables as well, it allocates memory and stores 'undefined' for them, and this is the end of first phase i.e. memory creation phase. Now, in 2nd phase i.e. code execution phase, it starts going through the whole code line by line. As it encounters var n = 2 , it assigns 2 to 'n'. Until now, the value of 'n' wa

2026-09-03 原文 →