/* * Copyright (C) 2021 Aravinth Manivannan * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ use std::{collections::HashMap, hash::Hash}; use crate::data::*; use crate::proxy::StringUtils; use get_post::*; #[derive(Eq, PartialEq)] enum PostitionType { Start, End, } struct Markup<'a, 'b> { markup: &'a GetPostPostContentBodyModelParagraphsMarkups, p: &'a GetPostPostContentBodyModelParagraphs, pos_type: PostitionType, gists: &'b Option>, } impl<'a, 'b> Markup<'a, 'b> { fn start( p: &GetPostPostContentBodyModelParagraphs, gists: &'b Option>, pindex: usize, in_oli: &mut bool, ) -> String { if p.type_ == "IMG" { let metadata = p.metadata.as_ref().unwrap(); format!( r#"
"#, metadata.original_width.as_ref().unwrap(), crate::V1_API_ROUTES.proxy.get_medium_asset(&metadata.id) ) } else if p.type_ == "P" { "

".into() } else if p.type_ == "PRE" { "

".into()
        } else if p.type_ == "BQ" {
            "
".into() } else if p.type_ == "H1" { "

".into() } else if p.type_ == "H2" { "

".into() } else if p.type_ == "H3" { if pindex == 0 { log::debug!("caught heading"); "".into() } else { "

".into() } } else if p.type_ == "H4" { "

".into() } else if p.type_ == "H5" { "

".into() } else if p.type_ == "H6" { "
".into() } else if p.type_ == "IFRAME" { let src = &p .iframe .as_ref() .unwrap() .media_resource .as_ref() .unwrap() .href; if src.contains("gist.github.com") { let gist_id = crate::data::Data::get_gist_id(src); let (_, gist) = gists .as_ref() .unwrap() .iter() .find(|(id, _)| id == gist_id) .as_ref() .unwrap(); let mut gists = String::default(); for file in &gist.files { gists += &format!( r#"
{}
"#, file.get_html_content() ); } format!( r#"
{gists} See gist on GitHub"#, &gist.html_url ) } else { format!(r#"".into() } } else if p.type_ == "OLI" { "".into() } else { "".into() }; if *in_oli { if p.type_ != "OLL" { *in_oli = false; format!("{resp}") } else { resp } } else { resp } } fn apply_markup(&self, pindex: usize) -> String { if self.markup.type_ == "A" { if let Some(anchor_type) = &self.markup.anchor_type { if anchor_type == "LINK" { if self.pos_type == PostitionType::Start { format!( r#""#, self.markup.href.as_ref().unwrap() ) } else { "".into() } } else if anchor_type == "USER" { if self.pos_type == PostitionType::Start { format!( r#""#, self.markup.user_id.as_ref().unwrap() ) } else { "".into() } } else { // log::error!("unknown markup.anchor_type: {:?} post id {}", anchor_type, id); if self.pos_type == PostitionType::Start { "".into() } else { "".into() } } } else { // log::error!("unknown markup.anchor_type: {:?} post id {}", anchor_type, id); if self.pos_type == PostitionType::Start { "".into() } else { "".into() } } } else if self.markup.type_ == "PRE" { if self.pos_type == PostitionType::Start { "
".into()
            } else {
                "
".into() } } else if self.markup.type_ == "EM" { if self.pos_type == PostitionType::Start { "".into() } else { "".into() } } else if self.markup.type_ == "STRONG" { if self.pos_type == PostitionType::Start { "".into() } else { "".into() } } else if self.markup.type_ == "CODE" { if self.pos_type == PostitionType::Start { "".into() } else { "".into() } } else { // log::error!("unknown markup.type_: {:?} post id {}", markup.type_, id); if self.pos_type == PostitionType::Start { log::info!("Unknown type"); r#"

From LibMedium: LibMedium is built by reverse engineering the Meduim's internal API. This post contains markup(formatting rules) that we are unaware of. Please report this URL on our bug tracker so that we can improve page rendering.
Alternatively, you can also email me at realaravinth at batsense dot net!

"# .into() } else { "".into() } } } } #[derive(Default)] struct PositionMap<'a, 'b> { map: HashMap>>, arr: Vec, } impl<'a, 'b> PositionMap<'a, 'b> { fn insert_if_not_exists(&mut self, pos: i64, m: Markup<'a, 'b>) { if let Some(markups) = self.map.get_mut(&pos) { markups.push(m); } else { self.map.insert(pos, vec![m]); self.arr.push(pos); } } } pub fn apply_markup<'b>( data: &PostResp, gists: &'b Option>, ) -> Vec { let mut paragraphs: Vec = Vec::with_capacity(data.content.body_model.paragraphs.len()); for (pindex, p) in data.content.body_model.paragraphs.iter().enumerate() { let mut pos = PositionMap::default(); if p.type_ == "H3" && pindex == 0 { log::debug!("FOUND TOP LEVEL H3. Breaking"); continue; } for m in p.markups.iter() { let start_markup = Markup { markup: &m, p, gists, pos_type: PostitionType::Start, }; pos.insert_if_not_exists(m.start, start_markup); let end_markup = Markup { markup: &m, p, gists, pos_type: PostitionType::End, }; pos.insert_if_not_exists(m.end, end_markup); } let mut cur = 0; fn incr_cur(cur: usize, point: i64) -> usize { let incr = point as usize - cur; let post_incr = cur + incr; log::debug!( "cur before incr: {cur}, incr by: {}, post incr: {}", incr, post_incr ); post_incr } let mut content = String::with_capacity(p.text.len()); let mut in_oli = false; content += &Markup::start(&p, &gists, pindex, &mut in_oli); pos.arr.sort(); if let Some(first) = pos.arr.get(0) { //content += p.text.substring(cur, *first as usize); content += p.text.slice(cur..*first as usize); cur = incr_cur(cur, *first); for point in pos.arr.iter() { //content.push(p.text.substring(start, start + point); // if *point != 0 { if cur != *point as usize { // content += p.text.substring(cur, *point as usize); content += p.text.slice(cur..*point as usize); } // } let pos_markups = pos.map.get(point).unwrap(); for m in pos_markups.iter() { // println!("{}", &m.apply_markup(pindex)); content += &m.apply_markup(pindex); } cur = incr_cur(cur, *point); } log::debug!("LAST"); content += p.text.slice(cur..); content += &Markup::end(&p, pindex, &mut in_oli); } else { log::debug!("LAST WITH NO MARKUP"); content += p.text.slice(cur..); content += &Markup::end(&p, pindex, &mut in_oli); } paragraphs.push(content); } paragraphs }