3

I am bashing my head against the wall. We have Python code that has to be migrated to one of our servers. The servers, for different reasons, have no Python, so my task was or is to migrate it. I chose Rust because I like the language, want to learn it, and it can generate a simple executable. The whole experience has been very educational, but I guess I am hitting my limit here.

I need to manipulate some HTML by updating links and wrapping some code in confluence code syntax macros. To do this, I have been using lol_html crate, whose internals are kind of hard to understand as a newbie, but I think it is my best shot.

Here is my code:

async fn transform_content(base_directory:&str, content: &String, mapping_dict: &HashMap<String, String>) -> Result<String, Box<dyn Error>> {
  let buffer_codes = std::rc::Rc::new( std::cell::RefCell::new( String::new()));
  let element_content_handlers = vec![

  element!("a.xref[href]", |el| {
      let href = el
          .get_attribute("href")
          .unwrap();

      let mapping_href = format!("{}/{}", base_directory, href);

      let page_id = mapping_dict.get(&mapping_href);
      if page_id.is_none() {
          println!("Warning - no mapping for xref link '{:?}'",
              mapping_href);
      } else {
          let confluence_href = format!("/confluence/pages/viewpage.action?pageId={}", page_id.unwrap());
          el.set_attribute("href", &confluence_href).unwrap();
      }

      Ok(())
  })

  , element!("div.codewrapper>pre code", |code_el| {
      // buffer_codes.borrow_mut().clear();
      let buffer = buffer_codes.clone();

      let language_class = code_el
          .get_attribute("class")
          .unwrap();

      let language_code = language_class.replace("lang-", "")
          .split_whitespace()
          .next()
          .unwrap()
          .to_string();

      if language_code == DOCFX_LANGUAGE_CSHARP {
          let lang = "c#";
          let code_block = buffer.borrow();
          let code_macro_content = format!("
          <ac:structured-macro xmlns:ac=\"urn:ac\"
          ac:name=\"code\">
          <ac:parameter ac:name=\"language\">{}</ac:parameter>
          <ac:plain-text-body><![CDATA[{}]]></ac:plain-text-body>
          </ac:structured-macro>",
              lang, code_block
          );
          code_el.replace(&code_macro_content, ContentType::Html);
        }
          Ok(())
      })

      , text!("div.codewrapper>pre code", |code| { 
          buffer_codes.borrow_mut().push_str(code.as_str());
          //  println!("{}", code.as_str());
          Ok(())
      })

  ];

  // Define rewrite rules to change elements
  let output = rewrite_str(
      &content,
      RewriteStrSettings {
          element_content_handlers,
          ..RewriteStrSettings::default()
      }
  ).unwrap();

  Ok(output)
}

The code compiles and makes some changes (the href update is flawless), but the code replacement execution is shifted, which means that the first [div pre>code] element gets no content (as I assume there is nothing in the buffer), the second element is actually the first, and so on.

How can I fix this?

E_net4
  • 27,810
  • 13
  • 101
  • 139
HammerTime
  • 31
  • 2

0 Answers0