1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// autocorrect: false
/*!
Automatically add whitespace between CJK (Chinese, Japanese, Korean) and half-width characters (alphabetical letters, numerical digits and symbols).

## Features

- Auto add spacings between CJK (Chinese, Japanese, Korean) and English words.
- HTML content support.

## Example

Use `autocorrect::format` to format plain text.

```rust
extern crate autocorrect;

fn main() {
    println!("{}", autocorrect::format("长桥 LongBridge App 下载"));
    // => "长桥 LongBridge App 下载"

    println!("{}", autocorrect::format("Ruby 2.7 版本第 1 次发布"));
    // => "Ruby 2.7 版本第 1 次发布"

    println!("{}", autocorrect::format("于 3 月 10 日开始"));
    // => "于 3 月 10 日开始"

    println!("{}", autocorrect::format("包装日期为2013年3月10日"));
    // => "包装日期为2013年3月10日"

    println!("{}", autocorrect::format("全世界已有数百家公司在生产环境中使用 Rust,以达到快速、跨平台、低资源占用的目的。"));
    // => "全世界已有数百家公司在生产环境中使用 Rust,以达到快速、跨平台、低资源占用的目的。"

    println!("{}", autocorrect::format("既に、世界中の数百という企業が Rust を採用し、高速で低リソースのクロスプラットフォームソリューションを実現しています。"));
    // => "既に、世界中の数百という企業が Rust を採用し、高速で低リソースのクロスプラットフォームソリューションを実現しています。"

    println!("{}", autocorrect::format("전 세계 수백 개의 회사가 프로덕션 환경에서 Rust 를 사용하여 빠르고, 크로스 플랫폼 및 낮은 리소스 사용량을 달성했습니다."));
    // => "전 세계 수백 개의 회사가 프로덕션 환경에서 Rust 를 사용하여 빠르고, 크로스 플랫폼 및 낮은 리소스 사용량을 달성했습니다."
}
```
*/

#[macro_use]
extern crate lazy_static;

/// Create a regex for supports:
///
/// - `\p{CJK}`: `\p{Han}|\p{Hangul}|\p{Katakana}|\p{Hiragana}|\p{Bopomofo}`
/// - `\p{CJ}`: `\p{Han}|\p{Katakana}|\p{Hiragana}|\p{Bopomofo}`
macro_rules! regexp {
    ($arg:tt) => {{
        regexp!("{}", $arg)
    }};
    ($($arg:tt)*) => {{
        let reg_str = format!($($arg)*);

        let mut rule_str = String::from(reg_str).replace(
            r"\p{CJK}",
            r"\p{Han}|\p{Hangul}|\p{Katakana}|\p{Hiragana}|\p{Bopomofo}",
        );

         rule_str = String::from(rule_str).replace(
            r"\p{CJK_N}",
            r"\p{Han}\p{Hangul}\p{Katakana}\p{Hiragana}\p{Bopomofo}",
        );

        rule_str = String::from(rule_str).replace(
            r"\p{CJ}",
            r"\p{Han}|\p{Katakana}|\p{Hiragana}|\p{Bopomofo}",
        );

        rule_str = String::from(rule_str).replace(
            r"\p{CJ_N}",
            r"\p{Han}\p{Katakana}\p{Hiragana}\p{Bopomofo}",
        );

        // println!("{}", rule_str);
        let res = regex::Regex::new(&rule_str).unwrap();
        res
    }};
}

/// Creates a `HashMap` containing the given arguments.
///
/// ## Example
///
/// ```ignore
/// let items = map! {
///    "a" => "hello",
///    "b" => "world",
/// };
/// ```
#[allow(unused)]
macro_rules! map {
    {$($key:expr => $value:expr),+ $(,)?} => {{
        let mut m = HashMap::new();
        $(
            m.insert($key, $value);
        )+
        m
    }};
    () => (
        HashMap::new()
    );
}

/// Asserts that two JSON values are equal by use `serde_json` parse.
/// This will ignore the whitespaces and newlines.
///
/// ## Example
///
/// ```ignore
/// assert_json_eq!(r#"{"a": 1}"#, r#"{ "a": 1 }"#);
/// ```
#[allow(unused)]
#[track_caller]
macro_rules! assert_json_eq {
    ($expected:expr, $actual:expr) => {{
        let expected = $expected;
        let actual = $actual;

        let expect_json = serde_json::from_str(expected).unwrap_or(serde_json::Value::default());
        let result = serde_json::from_str(actual.as_str()).unwrap_or(serde_json::Value::default());
        assert_eq!(expect_json, result);
    }};
}

/// Create a Vec<String> from a multiple line text.
///
/// This will split by `\n`.
#[allow(unused)]
#[track_caller]
macro_rules! cases {
    ($text:tt) => {{
        let cases = indoc::indoc!($text);
        cases.trim().split("\n").collect::<Vec<&str>>()
    }};
}

mod code;
mod diff;
mod format;
mod keyword;
mod result;
mod rule;
mod serde_any;

pub mod config;
pub mod ignorer;

pub use code::{format_for, get_file_extension, is_support_type, lint_for};
pub use config::Config;
pub use format::*;
pub use result::{json, rdjson, FormatResult, LineResult, LintResult, Severity};
pub use rule::{halfwidth, spellcheck};

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_format() {
        assert_eq!("Hello 世界。", format("Hello世界."));
    }

    #[test]
    fn test_format_for() {
        assert_eq!("Hello 世界。", format_for("Hello世界.", "text").out);
    }
}