From 97180c197835dc6dcefee2473466ce915ec3889b Mon Sep 17 00:00:00 2001 From: Jan Range Date: Fri, 24 May 2024 18:56:10 +0200 Subject: [PATCH 1/8] add frontmatter and re-order files --- assets/schema.png | Bin 0 -> 49358 bytes src/attribute.rs | 150 ++++++++++++++++++++++++++++++++++++ src/datamodel.rs | 25 ++++-- src/lib.rs | 6 +- src/markdown/attribute.rs | 73 ------------------ src/markdown/frontmatter.rs | 65 ++++++++++++++++ src/markdown/object.rs | 49 ------------ src/markdown/parser.rs | 65 +++++++++++++--- src/object.rs | 104 +++++++++++++++++++++++++ 9 files changed, 392 insertions(+), 145 deletions(-) create mode 100644 assets/schema.png create mode 100644 src/attribute.rs delete mode 100644 src/markdown/attribute.rs create mode 100644 src/markdown/frontmatter.rs delete mode 100644 src/markdown/object.rs create mode 100644 src/object.rs diff --git a/assets/schema.png b/assets/schema.png new file mode 100644 index 0000000000000000000000000000000000000000..e9a65824ceeb4f7da90012fd974843840ec81549 GIT binary patch literal 49358 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

-$Qkex4X`prfDIT$E(4P5z1Rd@ z#pk`b*S~Q;6U!xNy)ZMQ{{M@}O{4*G|Hhx3yPN0!{2B_a$NwKQ%*66P{Y|xl2(b5{ zVILwQ#vB9?A)u)aFb@ZD>6-MR&jP!wF<`4h`JbFRIZ*@!=GV4DU<}_RbCUoaw3lHs z4&qWzxx%29(<}kvdnu=B=7)m<+6vtO#KQmg9jkqp+X?~O^xt>98mrh5`K9iekg@1X z@IRYKb9)Wzo7kdq--ax*PfkvXN=oW6>PW(9ZN=iEHaquo@6Z>wb(=yOS0e@oEdk$) z%&>@|00%E8V{RV3f*m^4bmc}@%0(wk@aK=}cb#;qOAauzeUVNf=Zxn8zDK$3^5h11 zz#-h+YXG#ivNIYI1GD@2vdU^N!5`W0L;-7)6fz$F@ExKXoPM%nz_AH7pjoT_JZrp% z?U6`Vg@*&9e^)cwJy4r4h>lkTwy&0kX#S^4`&rIeiEyU?Uv}=_Q#2TGdZ_v0x42tUaq2wv|8ne--f zE|TL;MaZ5#K6x{)x^8dXGi*egmJKS3>O1gs^jn$ ZD${`coAuVrH74+-ci9kDc, + pub docstring: String, + pub options: Vec, + pub term: Option, + pub required: bool, +} + +impl Attribute { + pub fn new(name: String, required: bool) -> Self { + Attribute { + name, + dtypes: Vec::new(), + docstring: String::new(), + options: Vec::new(), + is_array: false, + term: None, + required, + } + } + + pub fn set_docstring(&mut self, docstring: String) { + self.docstring = docstring; + } + + pub fn add_option(&mut self, option: AttrOption) { + if option.key.to_lowercase() == "type" { + self.set_dtype(option.value); + return; + } else if option.key.to_lowercase() == "term" { + self.term = Some(option.value); + return; + } + + self.options.push(option); + } + + fn set_dtype(&mut self, dtype: String) { + if dtype.ends_with("[]") { + self.is_array = true; + self.dtypes.push(dtype.trim_end_matches("[]").to_string()); + return; + } + + self.dtypes.push(dtype); + } + + pub fn to_json_schema(&self) -> String { + serde_json::to_string_pretty(&self).unwrap() + } +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct AttrOption { + key: String, + value: String, +} + +impl AttrOption { + pub fn new(key: String, value: String) -> Self { + Self { + key: key.to_lowercase(), + value, + } + } + + pub fn key(&self) -> &str { + &self.key + } + + pub fn value(&self) -> &str { + &self.value + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_attribute_new() { + let attr = Attribute::new("name".to_string(), false); + assert_eq!(attr.name, "name"); + assert_eq!(attr.dtypes.len(), 0); + assert_eq!(attr.docstring, ""); + assert_eq!(attr.options.len(), 0); + assert_eq!(attr.is_array, false); + assert_eq!(attr.term, None); + assert_eq!(attr.required, false); + } + + #[test] + fn test_attribute_set_docstring() { + let mut attr = Attribute::new("name".to_string(), false); + attr.set_docstring("This is a test".to_string()); + assert_eq!(attr.docstring, "This is a test"); + assert_eq!(attr.required, false); + } + + #[test] + fn test_attribute_add_type_option() { + let mut attr = Attribute::new("name".to_string(), false); + let option = AttrOption::new("type".to_string(), "string".to_string()); + attr.add_option(option); + assert_eq!(attr.dtypes.len(), 1); + assert_eq!(attr.dtypes[0], "string"); + } + + #[test] + fn test_attribute_add_term_option() { + let mut attr = Attribute::new("name".to_string(), false); + let option = AttrOption::new("term".to_string(), "string".to_string()); + attr.add_option(option); + assert_eq!(attr.term, Some("string".to_string())); + } + + #[test] + fn test_attribute_add_option() { + let mut attr = Attribute::new("name".to_string(), false); + let option = AttrOption::new("description".to_string(), "This is a test".to_string()); + attr.add_option(option); + assert_eq!(attr.options.len(), 1); + assert_eq!(attr.options[0].key, "description"); + assert_eq!(attr.options[0].value, "This is a test"); + } + + #[test] + fn test_attribute_set_dtype() { + let mut attr = Attribute::new("name".to_string(), false); + attr.set_dtype("string".to_string()); + assert_eq!(attr.dtypes.len(), 1); + assert_eq!(attr.dtypes[0], "string"); + assert_eq!(attr.is_array, false); + } + + #[test] + fn test_attribute_set_array_dtype() { + let mut attr = Attribute::new("name".to_string(), false); + attr.set_dtype("string[]".to_string()); + assert_eq!(attr.dtypes.len(), 1); + assert_eq!(attr.dtypes[0], "string"); + assert_eq!(attr.is_array, true); + } +} diff --git a/src/datamodel.rs b/src/datamodel.rs index 6faa7cd..f7385d5 100644 --- a/src/datamodel.rs +++ b/src/datamodel.rs @@ -1,7 +1,10 @@ use std::{error::Error, fs, path::Path}; -use crate::markdown::object; -use crate::schema; +use serde::{Deserialize, Serialize}; + +use crate::markdown::frontmatter::FrontMatter; +use crate::object::Object; +use crate::{markdown, schema}; // Data model // @@ -25,15 +28,21 @@ use crate::schema; // * `json_schema` - Generate a JSON schema from the data model // * `json_schema_all` - Generate JSON schemas for all objects in the data model // * `sdrdm_schema` - Generate a SDRDM schema from the data model -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] pub struct DataModel { - pub objects: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub name: Option, + pub objects: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub config: Option, } impl DataModel { - pub fn new() -> Self { + pub fn new(name: Option, config: Option) -> Self { DataModel { + name, objects: Vec::new(), + config, } } @@ -124,7 +133,7 @@ impl DataModel { panic!("No objects found in the markdown file"); } - return serde_json::to_string_pretty(&self.objects).unwrap(); + return serde_json::to_string_pretty(&self).unwrap(); } // Parse a markdown file and create a data model @@ -148,8 +157,8 @@ impl DataModel { } let contents = fs::read_to_string(path)?; - let objects: Vec = serde_json::from_str(&contents)?; + let model: DataModel = serde_json::from_str(&contents)?; - Ok(DataModel { objects }) + Ok(model) } } diff --git a/src/lib.rs b/src/lib.rs index b3c493f..53590ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,10 @@ +pub mod attribute; pub mod datamodel; +pub mod object; pub mod primitives; pub mod schema; - pub mod markdown { - pub mod attribute; - pub mod object; + pub mod frontmatter; pub mod parser; } diff --git a/src/markdown/attribute.rs b/src/markdown/attribute.rs deleted file mode 100644 index 90dad7c..0000000 --- a/src/markdown/attribute.rs +++ /dev/null @@ -1,73 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize, Debug)] -pub struct Attribute { - pub name: String, - #[serde(rename = "multiple")] - pub is_array: bool, - pub dtypes: Vec, - pub docstring: String, - pub options: Vec, -} - -impl Attribute { - pub fn new(name: String) -> Self { - Attribute { - name, - dtypes: Vec::new(), - docstring: String::new(), - options: Vec::new(), - is_array: false, - } - } - - pub fn set_docstring(&mut self, docstring: String) { - self.docstring = docstring; - } - - pub fn add_option(&mut self, option: AttrOption) { - if option.key.to_lowercase() == "type" { - self.set_dtype(option.value); - return; - } else { - self.options.push(option); - } - } - - fn set_dtype(&mut self, dtype: String) { - if dtype.ends_with("[]") { - self.is_array = true; - self.dtypes.push(dtype.trim_end_matches("[]").to_string()); - return; - } - - self.dtypes.push(dtype); - } - - pub fn to_json_schema(&self) -> String { - serde_json::to_string_pretty(&self).unwrap() - } -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct AttrOption { - key: String, - value: String, -} - -impl AttrOption { - pub fn new(key: String, value: String) -> Self { - Self { - key: key.to_lowercase(), - value, - } - } - - pub fn key(&self) -> &str { - &self.key - } - - pub fn value(&self) -> &str { - &self.value - } -} diff --git a/src/markdown/frontmatter.rs b/src/markdown/frontmatter.rs new file mode 100644 index 0000000..79b04f0 --- /dev/null +++ b/src/markdown/frontmatter.rs @@ -0,0 +1,65 @@ +use std::collections::HashMap; + +use gray_matter::{engine::YAML, Matter}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct FrontMatter { + #[serde(default = "default_id_field", rename = "id-field")] + id_field: bool, + prefixes: Option>, + nsmap: Option>, +} + +impl Default for FrontMatter { + fn default() -> Self { + FrontMatter { + id_field: default_id_field(), + prefixes: None, + nsmap: None, + } + } +} + +fn default_id_field() -> bool { + true +} + +pub fn parse_frontmatter(content: &str) -> FrontMatter { + let matter = Matter::::new(); + let result = matter.parse(content); + result + .data + .expect("Could not extract frontmatter pod") + .deserialize() + .expect("Could not deserialize frontmatter") +} + +#[cfg(test)] +mod tests { + + use std::path::Path; + + use super::*; + + #[test] + fn test_parse_frontmatter() { + // Arrange + let path = Path::new("tests/data/model.md"); + let content = std::fs::read_to_string(path).expect("Could not read file"); + + // Act + let frontmatter = parse_frontmatter(&content); + + // Assert + assert_eq!(frontmatter.id_field, true); + assert_eq!( + frontmatter.prefixes.unwrap().get("schema").unwrap(), + "http://schema.org/" + ); + assert_eq!( + frontmatter.nsmap.unwrap().get("tst").unwrap(), + "http://example.com/test/" + ); + } +} diff --git a/src/markdown/object.rs b/src/markdown/object.rs deleted file mode 100644 index 6bb9808..0000000 --- a/src/markdown/object.rs +++ /dev/null @@ -1,49 +0,0 @@ -use serde::{Deserialize, Serialize}; -use serde_with::skip_serializing_none; - -use crate::markdown::attribute::Attribute; - -#[derive(Serialize, Deserialize, Debug)] -pub enum ObjectType { - Object, - Enum, -} - -#[skip_serializing_none] -#[derive(Serialize, Deserialize, Debug)] -pub struct Object { - pub name: String, - pub attributes: Vec, - pub docstring: String, - pub object_type: ObjectType, - pub term: Option, -} - -impl Object { - pub fn new(name: String, object_type: ObjectType, term: Option) -> Self { - Object { - name, - attributes: Vec::new(), - docstring: String::new(), - object_type, - term, - } - } - - pub fn add_attribute(&mut self, attribute: Attribute) { - self.attributes.push(attribute); - } - - pub fn set_docstring(&mut self, docstring: String) { - self.docstring = docstring; - } - - pub fn get_last_attribute(&mut self) -> &mut Attribute { - self.attributes.last_mut().unwrap() - } - - pub fn create_new_attribute(&mut self, name: String) { - let attribute = Attribute::new(name); - self.attributes.push(attribute); - } -} diff --git a/src/markdown/parser.rs b/src/markdown/parser.rs index 0142968..6c784ef 100644 --- a/src/markdown/parser.rs +++ b/src/markdown/parser.rs @@ -5,23 +5,27 @@ use std::path::Path; use pulldown_cmark::{Event, Parser, Tag}; use regex::Regex; +use crate::attribute; use crate::datamodel::DataModel; -use crate::markdown::attribute; -use crate::markdown::object; +use crate::object; + +use super::frontmatter::parse_frontmatter; pub fn parse_markdown(path: &Path) -> Result> { if !path.exists() { return Err("File does not exist".into()); } - let mut model = DataModel::new(); let content = fs::read_to_string(path).expect("Could not read file"); + let config = parse_frontmatter(content.as_str()); let parser = Parser::new(&content); let mut iterator = parser.into_iter(); let mut objects = Vec::new(); + let mut model = DataModel::new(None, Some(config)); + while let Some(event) = iterator.next() { - process_event(&mut iterator, &mut objects, event); + process_event(&mut iterator, &mut objects, event, &mut model); } model.objects = objects; @@ -29,21 +33,42 @@ pub fn parse_markdown(path: &Path) -> Result> { return Ok(model); } -pub fn process_event(iterator: &mut Parser, objects: &mut Vec, event: Event) { +pub fn process_event( + iterator: &mut Parser, + objects: &mut Vec, + event: Event, + model: &mut DataModel, +) { match event { + Event::Start(Tag::Heading(level)) if level == 1 => { + // Get the title of the data model + model.name = Some(extract_name(iterator)); + } Event::Start(Tag::Heading(level)) if level == 3 => { let object = process_object_heading(iterator); objects.push(object); } Event::Start(Tag::List(None)) => { - let attr_strings = extract_attribute(iterator); + // When the last object has no attributes, we need to parse + // the initial attribute in the list here + let last_object = objects.last_mut().unwrap(); + if !last_object.has_attributes() { + iterator.next(); + let (required, attr_name) = extract_attr_name_required(iterator); + let attribute = attribute::Attribute::new(attr_name, required); + objects.last_mut().unwrap().add_attribute(attribute); + return; + } + + // Every other match within this list will be an option for the last attribute + let attr_strings = extract_attribute_options(iterator); for attr_string in attr_strings { distribute_attribute_options(objects, attr_string); } } Event::Start(Tag::Item) => { - let attr_string = extract_name(iterator); - let attribute = attribute::Attribute::new(attr_string); + let (required, attr_string) = extract_attr_name_required(iterator); + let attribute = attribute::Attribute::new(attr_string, required); objects.last_mut().unwrap().add_attribute(attribute); } _ => {} @@ -61,9 +86,24 @@ fn process_object_heading(iterator: &mut Parser) -> object::Object { fn extract_name(iterator: &mut Parser) -> String { if let Some(Event::Text(text)) = iterator.next() { return text.to_string(); - } else { - return String::new(); } + + panic!("Could not extract name: Got {:?}", iterator.next().unwrap()); +} + +fn extract_attr_name_required(iterator: &mut Parser) -> (bool, String) { + // If it is a non required field, the name will be in the next event + if let Some(Event::Text(text)) = iterator.next() { + return (false, text.to_string()); + } + + // If it is a required field, the name will be in the next event + let text = iterator.next().unwrap(); + if let Event::Text(text) = text { + return (true, text.to_string()); + } + + panic!("Could not extract name: Got {:?}", text); } fn extract_object_term(heading: &String) -> Option { @@ -82,7 +122,7 @@ fn extract_object_term(heading: &String) -> Option { Some(term.to_string()) } -fn extract_attribute(iterator: &mut Parser) -> Vec { +fn extract_attribute_options(iterator: &mut Parser) -> Vec { let mut options = Vec::new(); while let Some(next) = iterator.next() { match next { @@ -115,6 +155,7 @@ fn distribute_attribute_options( attr_string: String, ) -> Option<()> { if attr_string.contains(":") { + // This is an option let (key, value) = process_option(&attr_string); add_option_to_last_attribute(objects, key, value); return None; @@ -123,7 +164,7 @@ fn distribute_attribute_options( objects .last_mut() .unwrap() - .create_new_attribute(attr_string); + .create_new_attribute(attr_string, false); return None; } diff --git a/src/object.rs b/src/object.rs new file mode 100644 index 0000000..064f5aa --- /dev/null +++ b/src/object.rs @@ -0,0 +1,104 @@ +use serde::{Deserialize, Serialize}; +use serde_with::skip_serializing_none; + +use crate::attribute::Attribute; + +#[derive(Serialize, Deserialize, Debug)] +pub enum ObjectType { + Object, + Enum, +} + +#[skip_serializing_none] +#[derive(Serialize, Deserialize, Debug)] +pub struct Object { + pub name: String, + pub attributes: Vec, + pub docstring: String, + pub object_type: ObjectType, + pub term: Option, +} + +impl Object { + pub fn new(name: String, object_type: ObjectType, term: Option) -> Self { + Object { + name, + attributes: Vec::new(), + docstring: String::new(), + object_type, + term, + } + } + + pub fn add_attribute(&mut self, attribute: Attribute) { + self.attributes.push(attribute); + } + + pub fn set_docstring(&mut self, docstring: String) { + self.docstring = docstring; + } + + pub fn get_last_attribute(&mut self) -> &mut Attribute { + self.attributes.last_mut().unwrap() + } + + pub fn create_new_attribute(&mut self, name: String, required: bool) { + let attribute = Attribute::new(name, required); + self.attributes.push(attribute); + } + + pub fn has_attributes(&self) -> bool { + self.attributes.len() > 0 + } + + pub fn set_name(&mut self, name: String) { + self.name = name; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_create_new_object() { + let object = Object::new("Person".to_string(), ObjectType::Object, None); + assert_eq!(object.name, "Person"); + assert_eq!(object.attributes.len(), 0); + assert_eq!(object.docstring, ""); + assert_eq!(object.term, None); + } + + #[test] + fn test_add_attribute() { + let mut object = Object::new("Person".to_string(), ObjectType::Object, None); + let attribute = Attribute::new("name".to_string(), false); + object.add_attribute(attribute); + assert_eq!(object.attributes.len(), 1); + assert_eq!(object.attributes[0].name, "name"); + } + + #[test] + fn test_set_docstring() { + let mut object = Object::new("Person".to_string(), ObjectType::Object, None); + object.set_docstring("This is a person object".to_string()); + assert_eq!(object.docstring, "This is a person object"); + } + + #[test] + fn test_get_last_attribute() { + let mut object = Object::new("Person".to_string(), ObjectType::Object, None); + let attribute = Attribute::new("name".to_string(), false); + object.add_attribute(attribute); + let last_attribute = object.get_last_attribute(); + assert_eq!(last_attribute.name, "name"); + } + + #[test] + fn test_create_new_attribute() { + let mut object = Object::new("Person".to_string(), ObjectType::Object, None); + object.create_new_attribute("name".to_string(), false); + assert_eq!(object.attributes.len(), 1); + assert_eq!(object.attributes[0].name, "name"); + } +} From 77af7292cca73cd2500e05c31dfd532486cc8c14 Mon Sep 17 00:00:00 2001 From: Jan Range Date: Fri, 24 May 2024 18:56:39 +0200 Subject: [PATCH 2/8] add cli and jinja templates --- src/bin/cli.rs | 130 +++++++++++++++++++++++++++++++ templates/markdown.jinja | 15 ++++ templates/python-dataclass.jinja | 36 +++++++++ templates/shacl.jinja | 24 ++++++ templates/xml-schema.jinja | 37 +++++++++ 5 files changed, 242 insertions(+) create mode 100644 src/bin/cli.rs create mode 100644 templates/markdown.jinja create mode 100644 templates/python-dataclass.jinja create mode 100644 templates/shacl.jinja create mode 100644 templates/xml-schema.jinja diff --git a/src/bin/cli.rs b/src/bin/cli.rs new file mode 100644 index 0000000..3b4ebd2 --- /dev/null +++ b/src/bin/cli.rs @@ -0,0 +1,130 @@ +use clap::{Parser, ValueEnum}; +use lazy_static::lazy_static; +use mdmodels::{datamodel::DataModel, markdown::parser::parse_markdown}; +use minijinja::{context, Environment}; +use std::path::PathBuf; + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Args { + #[arg(short, long)] + input: PathBuf, + + #[arg(short, long)] + output: Option, + + #[arg(short, long)] + template: Templates, + + #[arg(short, long)] + root: Option, +} + +#[derive(Debug, ValueEnum, Clone)] +enum Templates { + PythonDataclass, + XmlSchema, + Markdown, + Shacl, + JsonSchema, +} + +lazy_static! { + static ref PYTHON_TYPE_MAPS: std::collections::HashMap = { + let mut m = std::collections::HashMap::new(); + m.insert("string".to_string(), "str".to_string()); + m.insert("integer".to_string(), "int".to_string()); + m.insert("boolean".to_string(), "bool".to_string()); + m + }; + static ref SHACL_TYPE_MAPS: std::collections::HashMap = { + let mut m = std::collections::HashMap::new(); + m.insert("float".to_string(), "double".to_string()); + m + }; +} + +fn main() -> Result<(), minijinja::Error> { + // Parse the command line arguments + let args = Args::parse(); + + // Parse the markdown model + let (mut model, object_names) = parse_markdown_model(&args.input); + + // Render the template + let rendered = match args.template { + Templates::JsonSchema => { + model.json_schema(args.root.expect("Root object name is required")) + } + _ => render_jinja_template(&args, &mut model, object_names)?, + }; + + match args.output { + Some(ref output) => { + std::fs::write(output, rendered).expect("Failed to write output"); + } + None => { + println!("{}", rendered); + } + } + + Ok(()) +} + +fn parse_markdown_model(path: &PathBuf) -> (DataModel, Vec) { + let model = parse_markdown(path).expect("Failed to parse markdown"); + let object_names = model + .objects + .iter() + .map(|o| o.name.clone()) + .collect::>(); + + (model, object_names) +} + +fn render_jinja_template( + args: &Args, + model: &mut DataModel, + object_names: Vec, +) -> Result { + // Load the template + let mut env = Environment::new(); + minijinja_embed::load_templates!(&mut env); + let template = match args.template { + Templates::PythonDataclass => env.get_template("python-dataclass.jinja").unwrap(), + Templates::XmlSchema => env.get_template("xml-schema.jinja").unwrap(), + Templates::Markdown => env.get_template("markdown.jinja").unwrap(), + Templates::Shacl => env.get_template("shacl.jinja").unwrap(), + Templates::JsonSchema => env.get_template("json-schema.jinja").unwrap(), + }; + + // Type conversions + match args.template { + Templates::Shacl => convert_model_types(model, &SHACL_TYPE_MAPS), + Templates::PythonDataclass => convert_model_types(model, &PYTHON_TYPE_MAPS), + _ => {} + } + + // Render the template + template.render(context! { + objects => model.objects, + object_names => object_names, + title => model.name, + }) +} + +fn convert_model_types( + model: &mut DataModel, + type_map: &std::collections::HashMap, +) { + for object in &mut model.objects { + for attribute in &mut object.attributes { + attribute.dtypes = attribute + .dtypes + .iter() + .map(|t| type_map.get(t).unwrap_or(t)) + .map(|t| t.to_string()) + .collect(); + } + } +} diff --git a/templates/markdown.jinja b/templates/markdown.jinja new file mode 100644 index 0000000..ac932c6 --- /dev/null +++ b/templates/markdown.jinja @@ -0,0 +1,15 @@ +# {{ title }} +{% for object in objects %} +### {{ object.name }} +{{ object.docstring }} +{%- for attribute in object.attributes %} +- {{attribute.name}} + - Type: {% for dtype in attribute.dtypes -%} {{dtype}}{% if not loop.last %}, {% endif %}{% endfor -%} + {%- if attribute.term %} + - Term: {{ attribute.term }} + {%- endif %} + {%- for option in attribute.options %} + - {{ option.key }}: {{ option.value }} + {%- endfor -%} +{%- endfor %} +{% endfor %} diff --git a/templates/python-dataclass.jinja b/templates/python-dataclass.jinja new file mode 100644 index 0000000..4fad560 --- /dev/null +++ b/templates/python-dataclass.jinja @@ -0,0 +1,36 @@ +## This is a generated file. Do not modify it manually! +from __future__ import annotations +from dataclasses import dataclass, field +from dataclasses_json import config, dataclass_json +from typing import List, Optional + +{% for object in objects %} +@dataclass_json +@dataclass +class {{ object.name }}: + {%- for attribute in object.attributes %} + {%- if attribute.multiple is true %} + {{ attribute.name }}: List[{{ attribute.dtypes[0] }}] + {%- else %} + {{ attribute.name }}: Optional[{{ attribute.dtypes[0] }}] = None + {%- endif %} + {%- endfor %} + + __type__: list[str] = field( + metadata=config(field_name="@type"), + default_factory = lambda: [ + "ex:{{ object.name }}", + {%- if object.term -%}"{{ object.term }}"{%- endif %} + ], + ) + __context__: dict[str, str | dict] = field( + metadata=config(field_name="@context"), + default_factory = lambda: { + {%- for attribute in object.attributes %} + {%- if attribute.term %} + "{{ attribute.name }}": "{{ attribute.term }}", + {%- endif %} + {%- endfor %} + } + ) +{% endfor %} diff --git a/templates/shacl.jinja b/templates/shacl.jinja new file mode 100644 index 0000000..5ddaefa --- /dev/null +++ b/templates/shacl.jinja @@ -0,0 +1,24 @@ +@prefix sh: . +@prefix xsd: . +@prefix ex: . +{% for object in objects %} +ex:{{ object.name }}Shape + a sh:NodeShape ; + sh:targetClass ex:{{ object.name }} ; + {% for attribute in object.attributes %} + {%- if attribute.term %} + sh:property [ + sh:path {{ attribute.term }} ; + {%- if attribute.dtypes[0] in object_names %} + sh:node ex:{{ attribute.dtypes[0] }}Shape ; + {%- else %} + sh:datatype xsd:{{ attribute.dtypes[0] }} ; + {%- endif %} + {%- if attribute.multiple is false %} + sh:minCount 0 ; + sh:maxCount 1 ; + {%- endif %} + ] {%- if not loop.last -%};{%- else -%}.{% endif %} + {%- endif %} + {%- endfor %} +{% endfor %} diff --git a/templates/xml-schema.jinja b/templates/xml-schema.jinja new file mode 100644 index 0000000..b85cff0 --- /dev/null +++ b/templates/xml-schema.jinja @@ -0,0 +1,37 @@ + + + + + {%- for object in object_names %} + + {%- endfor %} + {% for object in objects%} + + + + {%- for attribute in object.attributes %} + {%- if attribute.dtypes | length == 1 %} + {%- if attribute.dtypes[0] in object_names %} + + {%- else %} + + {%- endif %} + {%- else %} + + + + {%- for dtype in attribute.dtypes %} + {%- if dtype in object_names %} + + {%- else %} + + {%- endif %} + {%- endfor %} + + + {%- endif %} + {%- endfor %} + + + {% endfor %} + From cf786be48b0cf41026434114f40e778303968251 Mon Sep 17 00:00:00 2001 From: Jan Range Date: Fri, 24 May 2024 18:56:55 +0200 Subject: [PATCH 3/8] add term manually --- src/schema.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/schema.rs b/src/schema.rs index 28c7ba3..3ffdaea 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -2,9 +2,9 @@ use std::collections::HashSet; use serde_json::json; -use crate::markdown::attribute; -use crate::markdown::attribute::AttrOption; -use crate::markdown::object; +use crate::attribute; +use crate::attribute::AttrOption; +use crate::object; use crate::primitives::PrimitiveTypes; static DEFINITIONS_KEY: &str = "definitions"; @@ -79,6 +79,11 @@ fn process_primitive( let name = &attribute.name; properties[name] = create_property(&name); + match attribute.term { + Some(ref term) => properties[name]["term"] = json!(term), + None => (), + } + set_primitive_dtype(properties, attribute, primitive); set_options(&mut properties[name], &attribute.options); } @@ -119,6 +124,13 @@ fn process_reference( let name = &attribute.name; properties[name] = create_property(&name); + match attribute.term { + Some(ref term) => { + properties[name]["term"] = json!(term); + } + None => {} + } + set_ref_dtype(properties, attribute, reference); set_options(&mut properties[name], &attribute.options); } From 290ed2d794a5c38d75dd00258c50621038ba29ad Mon Sep 17 00:00:00 2001 From: Jan Range Date: Fri, 24 May 2024 18:57:02 +0200 Subject: [PATCH 4/8] update tests --- tests/data/expected_sdrdm_schema.json | 122 +++++++++++++++----------- tests/data/model.md | 5 +- tests/integration_tests.rs | 39 ++++---- 3 files changed, 96 insertions(+), 70 deletions(-) diff --git a/tests/data/expected_sdrdm_schema.json b/tests/data/expected_sdrdm_schema.json index a9ad8a7..acb01f1 100644 --- a/tests/data/expected_sdrdm_schema.json +++ b/tests/data/expected_sdrdm_schema.json @@ -1,55 +1,73 @@ -[ - { - "name": "Test", - "attributes": [ - { - "name": "name", - "multiple": false, - "dtypes": ["string"], - "docstring": "", - "options": [{ "key": "term", "value": "schema:hello" }] - }, - { - "name": "number", - "multiple": false, - "dtypes": ["float"], - "docstring": "", - "options": [{ "key": "term", "value": "schema:one" }] - }, - { - "name": "test2", - "multiple": false, - "dtypes": ["Test2"], - "docstring": "", - "options": [{ "key": "term", "value": "schema:something" }] - } - ], - "docstring": "", - "object_type": "Object" +{ + "name": "Test", + "config": { + "id-field": true, + "prefixes": { + "schema": "http://schema.org/" + }, + "nsmap": { + "tst": "http://example.com/test/" + } }, - { - "name": "Test2", - "attributes": [ - { - "name": "names", - "multiple": true, - "dtypes": ["string"], - "docstring": "", - "options": { - "term": "schema:hello" + "objects": [ + { + "name": "Test", + "attributes": [ + { + "name": "name", + "multiple": false, + "dtypes": ["string"], + "docstring": "", + "options": [], + "term": "schema:hello", + "required": true + }, + { + "name": "number", + "multiple": false, + "dtypes": ["float"], + "docstring": "", + "options": [], + "term": "schema:one", + "required": false + }, + { + "name": "test2", + "multiple": false, + "dtypes": ["Test2"], + "docstring": "", + "options": [], + "term": "schema:something", + "required": false } - }, - { - "name": "number", - "multiple": false, - "dtypes": ["float"], - "docstring": "", - "options": { - "term": "schema:one" + ], + "docstring": "", + "object_type": "Object" + }, + { + "name": "Test2", + "attributes": [ + { + "name": "names", + "multiple": true, + "dtypes": ["string"], + "docstring": "", + "options": [], + "term": "schema:hello", + "required": false + }, + { + "name": "number", + "multiple": false, + "dtypes": ["float"], + "docstring": "", + "options": [], + "term": "schema:one", + "required": false } - } - ], - "docstring": "", - "object_type": "Object" - } -] + ], + "docstring": "", + "object_type": "Object" + } + ] +} diff --git a/tests/data/model.md b/tests/data/model.md index c986f7d..7a816a3 100644 --- a/tests/data/model.md +++ b/tests/data/model.md @@ -1,6 +1,9 @@ --- +id-field: true prefixes: schema: http://schema.org/ +nsmap: + tst: http://example.com/test/ --- # Test @@ -9,7 +12,7 @@ prefixes: ### Test -- name +- __name__ - Type: string - Term: schema:hello - number diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 4500fbb..0b88b31 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1,10 +1,10 @@ -extern crate sdrdm; +extern crate mdmodels; #[cfg(test)] mod tests { use std::path::Path; - use sdrdm::{self, markdown::parser::parse_markdown}; + use mdmodels::{self, markdown::parser::parse_markdown}; #[test] fn test_parse() { @@ -78,19 +78,22 @@ mod tests { // Act let schema = model.json_schema("Test".to_string()); + let schema: serde_json::Value = serde_json::from_str(&schema).unwrap(); // Assert let expected_schema = std::fs::read_to_string("tests/data/expected_json_schema.json").unwrap(); + // Parse with serde_json + let expected_schema: serde_json::Value = serde_json::from_str(&expected_schema).unwrap(); - assert_eq!(schema.trim(), expected_schema.trim()); + assert_eq!(schema, expected_schema); } #[test] #[should_panic] fn test_json_schema_no_objects() { // Arrange - let model = sdrdm::datamodel::DataModel::new(); + let model = mdmodels::datamodel::DataModel::new(None, None); // Act model.json_schema("Test".to_string()); @@ -107,27 +110,29 @@ mod tests { model.json_schema("Test3".to_string()); } - // #[test] - // fn test_sdrdm_schema() { - // // Arrange - // let path = Path::new("tests/data/model.md"); - // let model = parse_markdown(path).expect("Could not parse markdown"); + #[test] + fn test_sdrdm_schema() { + // Arrange + let path = Path::new("tests/data/model.md"); + let model = parse_markdown(path).expect("Could not parse markdown"); - // // Act - // let schema = model.sdrdm_schema(); + // Act + let schema = model.sdrdm_schema(); + let schema: serde_json::Value = serde_json::from_str(&schema).unwrap(); - // // Assert - // let expected_schema = - // std::fs::read_to_string("tests/data/expected_sdrdm_schema.json").unwrap(); + // Assert + let expected_schema = + std::fs::read_to_string("tests/data/expected_sdrdm_schema.json").unwrap(); + let expected_schema: serde_json::Value = serde_json::from_str(&expected_schema).unwrap(); - // assert_eq!(schema.trim(), expected_schema.trim()); - // } + assert_eq!(schema, expected_schema); + } #[test] #[should_panic] fn test_sdrdm_schema_no_objects() { // Arrange - let model = sdrdm::datamodel::DataModel::new(); + let model = mdmodels::datamodel::DataModel::new(None, None); // Act model.sdrdm_schema(); From 6dd4bb0b9214a445584fa8557c88a18c71fb3179 Mon Sep 17 00:00:00 2001 From: Jan Range Date: Fri, 24 May 2024 18:57:17 +0200 Subject: [PATCH 5/8] build template env --- build.rs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 build.rs diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..d35d8dc --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + minijinja_embed::embed_templates!("templates"); +} From 5393831f50b4ebbe5b73653c1115696651eebd8c Mon Sep 17 00:00:00 2001 From: Jan Range Date: Fri, 24 May 2024 18:57:27 +0200 Subject: [PATCH 6/8] update deps --- Cargo.lock | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 16 +++- 2 files changed, 217 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c09d88b..351390d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,55 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "autocfg" version = "1.2.0" @@ -75,6 +124,52 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "core-foundation-sys" version = "0.8.6" @@ -101,7 +196,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn", ] @@ -147,6 +242,18 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "gray_matter" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7188a951c53316d94711b3d944c28cf79968685d295cbe782494e8811fc75554" +dependencies = [ + "serde", + "serde_json", + "toml", + "yaml-rust", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -159,6 +266,12 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hex" version = "0.4.3" @@ -216,6 +329,12 @@ dependencies = [ "serde", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itoa" version = "1.0.11" @@ -231,24 +350,67 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "log" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "mdmodels" +version = "0.1.0" +dependencies = [ + "clap", + "gray_matter", + "lazy_static", + "minijinja", + "minijinja-embed", + "pulldown-cmark", + "regex", + "serde", + "serde_json", + "serde_with", +] + [[package]] name = "memchr" version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "minijinja" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7165d0e94806d52ad5295e4b54a95176d831814840bc067298ca647e1c956338" +dependencies = [ + "serde", +] + +[[package]] +name = "minijinja-embed" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a97808f66af2d75ba83d43f67cec8c30122773017d2dccebae9d6d7bb33116" + [[package]] name = "num-conv" version = "0.1.0" @@ -341,17 +503,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" -[[package]] -name = "sdrdm" -version = "0.1.0" -dependencies = [ - "pulldown-cmark", - "regex", - "serde", - "serde_json", - "serde_with", -] - [[package]] name = "serde" version = "1.0.198" @@ -420,6 +571,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "2.0.60" @@ -462,6 +619,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "unicase" version = "2.7.0" @@ -483,6 +649,12 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "version_check" version = "0.9.4" @@ -552,6 +724,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.5" @@ -615,3 +796,12 @@ name = "windows_x86_64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml index 40f6139..5db6468 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,7 @@ [package] -name = "sdrdm" +name = "mdmodels" +authors = ["Jan Range "] +description = "A tool to generate models, code and schemas from markdown files" version = "0.1.0" edition = "2021" @@ -9,3 +11,15 @@ pulldown-cmark = "0.8.0" serde_json = { "version" = "1.0.116", features = ["preserve_order"] } regex = "1.10.4" serde_with = "3.8.0" +minijinja = "2.0.1" +minijinja-embed = "2.0.1" +clap = { version = "4.5.4", features = ["cargo", "derive"] } +lazy_static = "1.4.0" +gray_matter = "0.2.7" + +[build-dependencies] +minijinja-embed = "2.0.1" + +[[bin]] +name = "md-models" +path = "src/bin/cli.rs" From 34ff52832075eb9067f688b406b8fe0054ff6b75 Mon Sep 17 00:00:00 2001 From: Jan Range Date: Fri, 24 May 2024 18:57:35 +0200 Subject: [PATCH 7/8] update readme --- README.md | 57 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index affcd46..8d804c2 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,52 @@ > [!IMPORTANT] > This is a work in progress and does not cover all featurs yet, but it is already usable. -# sdRDM: Markdown Data Model parser for Rust +# Markdown Models ![Build Status](https://github.com/JR-1991/sdrdm.rs/actions/workflows/test.yml/badge.svg) -This is a markdown parser and converter for Rust that can be used to parse markdown data model files and convert them to different JSON schema and the sdRDM format used for code generation. +![schema-illustration](assets/schema.png) -## Data model +This is a markdown parser and converter for Rust that can be used to parse markdown data model files and convert them to various formats, schemes and programming languages. -Contains a list of objects that represent the data model -written in the markdown format +## Installation -### Examples +In order to install the command line tool, you can use the following command: -```rust -let model = DataModel::parse("data_model.md"); +```bash +git clone https://github.com/JR-1991/md-models +cd md-models +cargo install --path . +``` + +## Command line usage + +The command line tool can be used to convert markdown files to various formats. The following command will convert a markdown file to Python code: -// Generate a JSON schema for the object named "ObjectName" -let json_schema = model.json_schema("ObjectName"); +```bash +md-models -i model.md -o lib.py -l python-dataclass +``` -// Generate a JSON schema for all objects in the data model -// and save them to a file -model.json_schema_all("path/to/dir"); +This will read the input file `model.md` and write the output to `lib.py` using the Python dataclass template. For an overview of all available templates, you can use the following command: -// Generate a SDRDM schema for the object named "ObjectName" -let sdrdm_schema = model.sdrdm_schema(); +```bash +md-models --help ``` -### Fields +## Available templates + +The following templates are available: + +- `python-dataclass`: Python dataclass implementation with JSON-LD support +- `xml-schema`: XML schema definition +- `json-schema`: JSON schema definition +- `shacl`: SHACL shapes definition -* `objects` - A list of objects -### Methods +## ToDo's -* `new` - Create a new data model -* `parse` - Parse a markdown file and create a data model -* `json_schema` - Generate a JSON schema from the data model -* `json_schema_all` - Generate JSON schemas for all objects in the data model -* `sdrdm_schema` - Generate a SDRDM schema from the data model +- [ ] Python PyDantic template +- [ ] SQL template +- [ ] Python SQLModel template +- [ ] File validation (XML, JSON, SHACL etc.) +- [ ] Python bindings using PyO3 From 9bd5ef2e6484f6caaf4ede2d44212d976566fc42 Mon Sep 17 00:00:00 2001 From: Jan Range Date: Fri, 24 May 2024 19:00:54 +0200 Subject: [PATCH 8/8] update image --- README.md | 4 +++- assets/schema.png | Bin 49358 -> 47873 bytes 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8d804c2..ed3c5e6 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ ![Build Status](https://github.com/JR-1991/sdrdm.rs/actions/workflows/test.yml/badge.svg) -![schema-illustration](assets/schema.png) +

+ +

This is a markdown parser and converter for Rust that can be used to parse markdown data model files and convert them to various formats, schemes and programming languages. diff --git a/assets/schema.png b/assets/schema.png index e9a65824ceeb4f7da90012fd974843840ec81549..b8a799eb414d32b2138b4e2a24623d6302e46d09 100644 GIT binary patch literal 47873 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 literal 49358 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

-$Qkex4X`prfDIT$E(4P5z1Rd@ z#pk`b*S~Q;6U!xNy)ZMQ{{M@}O{4*G|Hhx3yPN0!{2B_a$NwKQ%*66P{Y|xl2(b5{ zVILwQ#vB9?A)u)aFb@ZD>6-MR&jP!wF<`4h`JbFRIZ*@!=GV4DU<}_RbCUoaw3lHs z4&qWzxx%29(<}kvdnu=B=7)m<+6vtO#KQmg9jkqp+X?~O^xt>98mrh5`K9iekg@1X z@IRYKb9)Wzo7kdq--ax*PfkvXN=oW6>PW(9ZN=iEHaquo@6Z>wb(=yOS0e@oEdk$) z%&>@|00%E8V{RV3f*m^4bmc}@%0(wk@aK=}cb#;qOAauzeUVNf=Zxn8zDK$3^5h11 zz#-h+YXG#ivNIYI1GD@2vdU^N!5`W0L;-7)6fz$F@ExKXoPM%nz_AH7pjoT_JZrp% z?U6`Vg@*&9e^)cwJy4r4h>lkTwy&0kX#S^4`&rIeiEyU?Uv}=_Q#2TGdZ_v0x42tUaq2wv|8ne--f zE|TL;MaZ5#K6x{)x^8dXGi*egmJKS3>O1gs^jn$ ZD${`coAuVrH74+-ci9kDc