|
5 | 5 | use std::fs::File; |
6 | 6 | use std::io::{BufReader, BufWriter, Read, Write}; |
7 | 7 | use std::ops::Index; |
8 | | -use std::path::PathBuf; |
| 8 | +use std::path::{Path, PathBuf}; |
9 | 9 | use std::str::FromStr; |
10 | 10 | use clap::Parser; |
11 | 11 | use regex::{Captures, Regex}; |
@@ -47,27 +47,33 @@ enum BuildMode { |
47 | 47 | Static, |
48 | 48 | } |
49 | 49 |
|
50 | | -fn main() { |
51 | | - let args: Args = Args::parse().validate().unwrap(); |
52 | | - println!("{args:?}", args = &args); |
53 | | - let mut input = BufReader::new(File::open(&args.input_file).expect("failed to open input file")); |
54 | | - let input_content = { |
55 | | - let mut buf = String::new(); |
56 | | - input.read_to_string(&mut buf).unwrap(); |
57 | | - buf |
58 | | - }; |
| 50 | +struct BuildContext<'ctx> { |
| 51 | + mode: BuildMode, |
| 52 | + input_file: &'ctx Path, |
| 53 | +} |
59 | 54 |
|
60 | | - let input_content = { |
| 55 | +trait PreProcessor { |
| 56 | + fn transform(&self, build_context: &BuildContext<'_>, content: String) -> String; |
| 57 | +} |
| 58 | + |
| 59 | +/** |
| 60 | +* insert inter-link or file content directly |
| 61 | +* tag syntax: {{link or include|<relative path of markdown from root document>}} |
| 62 | +*/ |
| 63 | +struct LinkOrInclude; |
| 64 | + |
| 65 | +impl PreProcessor for LinkOrInclude { |
| 66 | + fn transform(&self, build_context: &BuildContext<'_>, input_content: String) -> String { |
61 | 67 | let pattern = Regex::from_str(r#"\{\{link or include\|./((?:\w+/)+)(\w+\.md)\}\}"#).unwrap(); |
62 | 68 | pattern.replace_all(input_content.as_str(), |captures: &Captures| { |
63 | 69 | let file_path = captures.index(1); |
64 | 70 | let file_name = captures.index(2); |
65 | 71 | println!("including: {file_path}/{file_name}"); |
66 | 72 | let full_file_path = format!("{file_path}{file_name}"); |
67 | | - match args.build_mode { |
| 73 | + match build_context.mode { |
68 | 74 | BuildMode::Dynamic => format!("This section is migrated. Please see [{file_name}](./{full_file_path})"), |
69 | 75 | BuildMode::Static => { |
70 | | - let mut cloned_path = args.input_file.clone(); |
| 76 | + let mut cloned_path = build_context.input_file.to_path_buf(); |
71 | 77 | cloned_path.pop(); |
72 | 78 | let target_path = cloned_path.join(file_path).join(file_name); |
73 | 79 | println!("{target_path}", target_path = &target_path.to_str().unwrap()); |
@@ -97,8 +103,27 @@ fn main() { |
97 | 103 | } |
98 | 104 | } |
99 | 105 | }).to_string() |
| 106 | + } |
| 107 | +} |
| 108 | + |
| 109 | +fn main() { |
| 110 | + let mut args: Args = Args::parse().validate().unwrap(); |
| 111 | + println!("{args:?}", args = &args); |
| 112 | + let mut input = BufReader::new(File::open(&args.input_file).expect("failed to open input file")); |
| 113 | + let input_content = { |
| 114 | + let mut buf = String::new(); |
| 115 | + input.read_to_string(&mut buf).unwrap(); |
| 116 | + buf |
100 | 117 | }; |
101 | 118 |
|
| 119 | + let build_context = BuildContext { |
| 120 | + mode: args.build_mode, |
| 121 | + input_file: &mut args.input_file, |
| 122 | + }; |
| 123 | + |
| 124 | + let input_content = LinkOrInclude.transform(&build_context, input_content); |
| 125 | + let input_content = LinkOrInclude.transform(&build_context, input_content); |
| 126 | + |
102 | 127 | let mut output = BufWriter::new(File::options().write(true).create(true).truncate(true).open(args.output_file).unwrap()); |
103 | 128 | output.write_all(input_content.as_bytes()).expect("could not write output to destination"); |
104 | 129 | } |
0 commit comments