Metafetch finds the share image it was missing, and stops erasing the one you had
Direct Fetch read og:image one way, in one place. Now it checks all five places pages keep a share image, and never blanks a stored one.
Why Care?
Metafetch fills a note's frontmatter from a URL so the note can become a card, and a card's image is what makes it worth looking at. Direct Fetch from Script, the provider with no API key and no rate limit, was coming back without the image on pages that plainly had one. Worse, a page without an image made it write og_image: null over an image the note already had.
What's New?
Share images from five places, in order:
og:image(and its:url/:secure_urlforms),twitter:image(and:src),itemprop="image"microdata,<link rel="image_src">, and the JSON-LD image. Open Graph and Twitter keys are read under eitherproperty=orname=, quoted or not.No more blanking. A field the page doesn't supply keeps the note's value.
Cite Wide's extractor fixes, copied back: apostrophes, named entities, the real favicon, more author sources with a plausibility filter, and bot-check pages treated as failures.
Settings in Obsidian's settings search, on the 1.13 declarative API. Requires Obsidian 1.13.
103 tests, and lint-clean under the community review bot's rules.
What the 50 empty notes told us
Before changing anything we pulled every vault note that had been fetched but had no og_image, and fetched each page again.
Most really have no image. Founders Fund, semver.org, Moonshot AI, Apache Flink and others publish an
og:titleand noog:image. Empty is the right answer there; no extractor change would help.One wrote it as
name="og:image". Filmora. The spec saysproperty, the page saysname, and the browser-side unfurlers accept both, so we do too.Minified HTML drops the quotes. electronjs.org writes
<meta property=og:url content=https://electronjs.org/>. The old pattern required quotes, so every tag written that way was invisible to it.Several now extract fine. Those pages added an image after the note was fetched. Re-running the command fills them in, and it no longer erases anything on the pages that still have none.
Under the hood
src/services/directFetchService.tsis now Cite Wide's extractor (copied, not imported; each plugin ships standalone), adapted back to Metafetch'sOpenGraphData, plusextractImage()and agetMetaEither()lookup that checks both attributes. Tag attributes are parsed quote-aware, anddata-name=is not mistaken forname=.main.tswritestitle,description, andimageonly when the page supplied them. Theog_image: nullplaceholder is kept for notes that never had one.A junk title (from Cite Wide's list: "Just a moment...", "Client Challenge", "Page not found", and others) raises
DirectFetchError('BLOCKED_PAGE'), and the note is left untouched.The settings tab returns
getSettingDefinitions().display(), the unused second settings tab, and anobsidian.d.tsshim that shadowed Obsidian's real types with older signatures are gone.loadSettings()merges onto astructuredCloneof the defaults.The tests run through
scripts/run-tests.mjs: esbuild bundlestests/*.test.tswithobsidianaliased to a stub, thennode --testruns them.tests/direct-fetch-command.test.tsdrives the real command against a stubbed note and page.manifest.json0.2.0,minAppVersion1.13.0.
What's Next
Release 0.2.0 through the attested workflow.
Cite Wide's extractor also returns the publisher's app icon, logo, mask icon, and brand color. Metafetch now parses them but writes only the favicon. Writing the rest would need new field-name settings, so that's a separate decision.
Six more plugins to take through the same migration.