Skip to content

CLI/API: clip() passes documentElement to Defuddle, producing silently empty output #956

Description

@Horace1423

Summary

clip() in src/api.ts hands Defuddle the document element instead of the document. Defuddle returns an empty result for that input, so the CLI writes a note with every field blank — no error, no warning, exit code 0.

This is, I believe, the root cause of #745 (CLI: empty output and navigator error), which was closed as "the feature is still in progress". The navigator is not defined half of that report is separate; this issue is only about the silent empty output.

Reproduce

git clone --depth 1 https://github.com/obsidianmd/obsidian-clipper.git
cd obsidian-clipper && npm install && npm run build:cli

cat > /tmp/t.json <<'JSON'
{
  "schemaVersion": "0.1.0",
  "name": "min",
  "behavior": "create",
  "noteNameFormat": "{{title}}",
  "path": "Clippings",
  "noteContentFormat": "{{content}}",
  "properties": [
    {"name": "title", "value": "{{title}}", "type": "text"},
    {"name": "words", "value": "{{words}}", "type": "number"}
  ]
}
JSON

node dist/cli.cjs "https://en.wikipedia.org/wiki/Markdown" -t /tmp/t.json -o /tmp/out.md

Actual — 115 bytes, all fields empty:

---
title:
words: 0
---

Expectedtitle: "Markdown", words: 2671, ~33 KB of body.

Not URL-specific. Same result with --html on a locally saved page, and with MDN, so it is not a fetch or SPA problem.

Cause

src/api.ts:

const documentElement = doc.documentElement || doc;
const defuddle = new DefuddleClass(documentElement as unknown as Document, { url });

Defuddle expects a Document. With linkedom, doc.documentElement is truthy, so an HTMLHtmlElement is passed and parsing yields nothing. Direct check against defuddle@0.19.2 + linkedom@0.18:

document        => title: "Markdown"  words: 2671  contentLen: 47204
documentElement => title: ""          words: 0     contentLen: 0

The browser extension is unaffected because popup.ts does not go through api.ts.

Fix

-	const defuddle = new DefuddleClass(documentElement as unknown as Document, { url });
+	const defuddle = new DefuddleClass(doc as unknown as Document, { url });

With that one line, the reproduction above yields title: "Markdown", words: 2671, 33 KB body. The documentElement local becomes unused and can be dropped.

I'd also suggest treating an empty Defuddle result as an error rather than writing the note — a blank note that lands silently is worse than a failure, especially for scripted use.

Environment

  • obsidian-clipper main (package version 1.7.1), built via npm run build:cli
  • Node v22.22.2, npm 10.9.7, Linux
  • defuddle 0.19.2, linkedom 0.18.x

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions