Federated blogging application, thanks to ActivityPub https://joinplu.me
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

157 lines
4.6 KiB

  1. use rsass;
  2. use ructe::Ructe;
  3. use std::process::{Command, Stdio};
  4. use std::{ffi::OsStr, fs::*, io::Write, path::*};
  5. fn compute_static_hash() -> String {
  6. //"find static/ -type f ! -path 'static/media/*' | sort | xargs stat -c'%n %Y' | openssl dgst -r"
  7. let find = Command::new("find")
  8. .args(&["static/", "-type", "f", "!", "-path", "static/media/*"])
  9. .stdout(Stdio::piped())
  10. .spawn()
  11. .expect("failed find command");
  12. let sort = Command::new("sort")
  13. .stdin(find.stdout.unwrap())
  14. .stdout(Stdio::piped())
  15. .spawn()
  16. .expect("failed sort command");
  17. let xargs = Command::new("xargs")
  18. .args(&["stat", "-c'%n %Y'"])
  19. .stdin(sort.stdout.unwrap())
  20. .stdout(Stdio::piped())
  21. .spawn()
  22. .expect("failed xargs command");
  23. let mut sha = Command::new("openssl")
  24. .args(&["dgst", "-r"])
  25. .stdin(xargs.stdout.unwrap())
  26. .output()
  27. .expect("failed openssl command");
  28. sha.stdout.resize(64, 0);
  29. String::from_utf8(sha.stdout).unwrap()
  30. }
  31. fn main() {
  32. Ructe::from_env()
  33. .expect("This must be run with cargo")
  34. .compile_templates("templates")
  35. .expect("compile templates");
  36. compile_themes().expect("Theme compilation error");
  37. recursive_copy(&Path::new("assets").join("icons"), &Path::new("static"))
  38. .expect("Couldn't copy icons");
  39. recursive_copy(&Path::new("assets").join("images"), &Path::new("static"))
  40. .expect("Couldn't copy images");
  41. create_dir_all(&Path::new("static").join("media")).expect("Couldn't init media directory");
  42. let cache_id = &compute_static_hash()[..8];
  43. println!("cargo:rerun-if-changed=target/deploy/plume-front.wasm");
  44. copy("target/deploy/plume-front.wasm", "static/plume-front.wasm")
  45. .and_then(|_| read_to_string("target/deploy/plume-front.js"))
  46. .and_then(|js| {
  47. write(
  48. "static/plume-front.js",
  49. js.replace(
  50. "\"plume-front.wasm\"",
  51. &format!("\"/static/cached/{}/plume-front.wasm\"", cache_id),
  52. ),
  53. )
  54. })
  55. .ok();
  56. println!("cargo:rustc-env=CACHE_ID={}", cache_id)
  57. }
  58. fn compile_themes() -> std::io::Result<()> {
  59. let input_dir = Path::new("assets").join("themes");
  60. let output_dir = Path::new("static").join("css");
  61. let themes = find_themes(input_dir)?;
  62. for theme in themes {
  63. compile_theme(&theme, &output_dir)?;
  64. }
  65. Ok(())
  66. }
  67. fn find_themes(path: PathBuf) -> std::io::Result<Vec<PathBuf>> {
  68. let ext = path.extension().and_then(OsStr::to_str);
  69. if metadata(&path)?.is_dir() {
  70. Ok(read_dir(&path)?.fold(vec![], |mut themes, ch| {
  71. if let Ok(ch) = ch {
  72. if let Ok(mut new) = find_themes(ch.path()) {
  73. themes.append(&mut new);
  74. }
  75. }
  76. themes
  77. }))
  78. } else if (ext == Some("scss") || ext == Some("sass"))
  79. && !path.file_name().unwrap().to_str().unwrap().starts_with('_')
  80. {
  81. Ok(vec![path.clone()])
  82. } else {
  83. Ok(vec![])
  84. }
  85. }
  86. fn compile_theme(path: &Path, out_dir: &Path) -> std::io::Result<()> {
  87. let name = path
  88. .components()
  89. .skip_while(|c| *c != Component::Normal(OsStr::new("themes")))
  90. .skip(1)
  91. .filter_map(|c| {
  92. c.as_os_str()
  93. .to_str()
  94. .unwrap_or_default()
  95. .splitn(2, '.')
  96. .next()
  97. })
  98. .collect::<Vec<_>>()
  99. .join("-");
  100. let dir = path.parent().unwrap();
  101. let out = out_dir.join(name);
  102. create_dir_all(&out)?;
  103. // copy files of the theme that are not scss
  104. for ch in read_dir(&dir)? {
  105. recursive_copy(&ch?.path(), &out)?;
  106. }
  107. // compile the .scss/.sass file
  108. let mut out = File::create(out.join("theme.css"))?;
  109. out.write_all(
  110. &rsass::compile_scss_file(path, rsass::OutputStyle::Compressed)
  111. .expect("SCSS compilation error"),
  112. )?;
  113. Ok(())
  114. }
  115. fn recursive_copy(path: &Path, out_dir: &Path) -> std::io::Result<()> {
  116. if metadata(path)?.is_dir() {
  117. let out = out_dir.join(path.file_name().unwrap());
  118. create_dir_all(out.clone())?;
  119. for ch in read_dir(path)? {
  120. recursive_copy(&ch?.path(), &out)?;
  121. }
  122. } else {
  123. println!("cargo:rerun-if-changed={}", path.display());
  124. let ext = path.extension().and_then(OsStr::to_str);
  125. if ext != Some("scss") && ext != Some("sass") {
  126. copy(path, out_dir.join(path.file_name().unwrap()))?;
  127. }
  128. }
  129. Ok(())
  130. }