Skip to main content

typub_adapter_hashnode/
config.rs

1use anyhow::Result;
2
3use typub_adapters_core::{
4    AdapterCapability, AdapterRegistrar, NodePolicy, NodePolicyAction, PlatformAdapter,
5    TaxonomyCapability, resolve_asset_strategy_from_config,
6};
7use typub_config::{Config, PlatformConfig};
8use typub_core::{
9    AssetStrategy, CapabilityGapBehavior, CapabilitySupport, MathDelimiters, MathRendering,
10};
11
12use crate::adapter::HashnodeAdapter;
13
14pub const ID: &str = "hashnode";
15
16pub const CAPABILITY: AdapterCapability = AdapterCapability {
17    id: ID,
18    name: "Hashnode",
19    short_code: "hn",
20    local_output: false,
21    requires_config: true,
22    taxonomy: TaxonomyCapability::new(
23        CapabilitySupport::Supported,
24        CapabilitySupport::Unsupported(CapabilityGapBehavior::WarnAndDegrade),
25        CapabilitySupport::Supported,
26        typub_core::DraftSupport::SeparateObjects,
27    ),
28    asset_strategies: &[AssetStrategy::External],
29    math_renderings: &[MathRendering::Latex], // MathJax expects LaTeX
30    math_delimiters: &[MathDelimiters::Brackets],
31    code_highlight: true,
32    notes: "Tags synced (max 5); internal links resolved from local status DB. Math via MathJax.",
33    node_policy: NodePolicy {
34        raw: NodePolicyAction::Sanitize,
35        unknown: NodePolicyAction::Drop,
36    },
37};
38
39pub fn resolve_strategy(platform_config: Option<&PlatformConfig>) -> Result<AssetStrategy> {
40    resolve_asset_strategy_from_config(platform_config, &CAPABILITY)
41}
42
43pub fn create(config: &Config) -> Result<Box<dyn PlatformAdapter>> {
44    Ok(Box::new(HashnodeAdapter::new(config)?))
45}
46
47pub fn register(registrar: &mut AdapterRegistrar) -> Result<()> {
48    registrar.register_factory(ID, create)?;
49    registrar.register_capability(ID, CAPABILITY)?;
50    Ok(())
51}
52
53#[cfg(test)]
54#[allow(clippy::expect_used)]
55mod tests {
56    use super::*;
57    use std::collections::HashMap;
58
59    #[test]
60    fn test_resolve_strategy_default() {
61        let result = resolve_strategy(None).expect("resolve");
62        assert_eq!(result, AssetStrategy::External);
63    }
64
65    #[test]
66    fn test_resolve_strategy_invalid_value() {
67        let cfg = PlatformConfig {
68            enabled: true,
69            asset_strategy: Some("invalid".into()),
70            published: None,
71            theme: None,
72            internal_link_target: None,
73            math_rendering: None,
74            math_delimiters: None,
75            extra: HashMap::new(),
76        };
77        let err = resolve_strategy(Some(&cfg)).expect_err("invalid should fail");
78        assert!(err.to_string().contains("Invalid asset strategy"));
79    }
80
81    #[test]
82    fn test_resolve_strategy_disabled_platform() {
83        let cfg = PlatformConfig {
84            enabled: false,
85            asset_strategy: Some("external".into()),
86            published: None,
87            theme: None,
88            internal_link_target: None,
89            math_rendering: None,
90            math_delimiters: None,
91            extra: HashMap::new(),
92        };
93        let result = resolve_strategy(Some(&cfg)).expect("resolve");
94        assert_eq!(result, AssetStrategy::External);
95    }
96
97    #[test]
98    fn test_resolve_strategy_unsupported() {
99        let cfg = PlatformConfig {
100            enabled: true,
101            asset_strategy: Some("upload".into()),
102            published: None,
103            theme: None,
104            internal_link_target: None,
105            math_rendering: None,
106            math_delimiters: None,
107            extra: HashMap::new(),
108        };
109        let err = resolve_strategy(Some(&cfg)).expect_err("should fail");
110        assert!(err.to_string().contains("does not support"));
111    }
112}