crx_manifest_parser/lib.rs
1//! # crx-manifest-parser
2//!
3//! Parse a Chrome / Chromium **Manifest V3** `manifest.json` string into a
4//! strongly-typed [`Manifest`] struct exposing the fields an extension
5//! security scanner actually cares about:
6//!
7//! - `name`, `version`, `description`, `manifest_version`
8//! - `permissions` and `optional_permissions` (named API tokens)
9//! - `host_permissions` (match-patterns granting site access)
10//! - `content_scripts` (the script + match list, the biggest cross-origin
11//! exposure surface)
12//!
13//! The crate is pure Rust, **zero-dependency** (no `serde`, no `serde_json`),
14//! `#![forbid(unsafe_code)]`, and carries its own minimal JSON value parser
15//! so a manifest can be decoded in any sandboxed or `#[no_std]`-adjacent
16//! context without dragging in a JSON library.
17//!
18//! This is the manifest-decode layer behind the
19//! [**zovo.one**](https://zovo.one/) Chrome-extension privacy & security
20//! scanner.
21//!
22//! ## Quick example
23//!
24//! ```
25//! use crx_manifest_parser::Manifest;
26//!
27//! let json = r#"{
28//! "manifest_version": 3,
29//! "name": "My Extension",
30//! "version": "1.4.2",
31//! "permissions": ["activeTab", "storage"],
32//! "host_permissions": ["https://*.example.com/*"],
33//! "content_scripts": [
34//! {
35//! "matches": ["https://*.example.com/*"],
36//! "js": ["content.js"]
37//! }
38//! ]
39//! }"#;
40//!
41//! let manifest = Manifest::from_json(json).expect("valid manifest");
42//! assert_eq!(manifest.name.as_deref(), Some("My Extension"));
43//! assert_eq!(manifest.version.as_deref(), Some("1.4.2"));
44//! assert_eq!(manifest.manifest_version, Some(3));
45//! assert_eq!(manifest.permissions, ["activeTab", "storage"]);
46//! assert_eq!(manifest.host_permissions, ["https://*.example.com/*"]);
47//! assert_eq!(manifest.content_scripts.len(), 1);
48//! ```
49
50#![forbid(unsafe_code)]
51
52mod json;
53mod parse;
54
55pub use parse::{ContentScript, Manifest};
56
57// Re-export the minimal JSON value model so downstream callers can inspect a
58// raw field without re-parsing.
59pub use json::{Json, ParseError};