Changes
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..32a844d
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,53 @@
+cmake_minimum_required(VERSION 3.24)
+
+project(MacroDown LANGUAGES CXX VERSION 0.1.0)
+
+set(CMAKE_CXX_STANDARD 23)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
+
+# Strict compiler options
+if(MSVC)
+ add_compile_options(/W4 /WX)
+else()
+ add_compile_options(-Wall -Wextra -Wpedantic -Werror)
+endif()
+
+# Dependencies
+include(FetchContent)
+
+FetchContent_Declare(
+ googletest
+ URL https://github.com/google/googletest/archive/refs/heads/main.zip
+)
+
+FetchContent_Declare(
+ uni-algo
+ URL https://github.com/uni-algo/uni-algo/archive/refs/tags/v1.2.0.zip
+)
+
+# For Windows: Prevent overriding the parent project's compiler/linker settings
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+FetchContent_MakeAvailable(googletest uni-algo)
+
+# Source Configuration
+include_directories(include)
+
+# We will add source files explicitly to targets to avoid GLOB issues in larger projects,
+# but for now we will just list them manually or add a library target.
+# Let's create a core library for the logic to share between main and tests.
+
+add_library(macrodown_lib STATIC src/lib_placeholder.cpp)
+target_include_directories(macrodown_lib PUBLIC include)
+target_link_libraries(macrodown_lib PUBLIC uni-algo::uni-algo)
+
+add_executable(macrodown src/main.cpp)
+target_link_libraries(macrodown PRIVATE macrodown_lib)
+
+# Testing
+enable_testing()
+
+add_executable(macrodown_test tests/test_main.cpp)
+target_link_libraries(macrodown_test PRIVATE macrodown_lib GTest::gtest_main)
+target_include_directories(macrodown_test PRIVATE include)
+
diff --git a/design.md b/design.md
new file mode 100644
index 0000000..df10187
--- /dev/null
+++ b/design.md
@@ -0,0 +1,180 @@
+# MacroDown Design Document
+
+## 1. Overview
+MacroDown is a C++ Markdown processor that extends the CommonMark syntax with a TeX-like macro system. The core philosophy is that **all** markup elements (headers, emphasis, links) are treated as syntactic sugar for macro calls. The processor parses the document into a tree of macro invocations and evaluates them using a standard library of macro definitions to produce HTML.
+
+## 2. Architecture
+
+The system operates in a linear pipeline:
+
+```mermaid
+graph TD
+ Input[Source Text] --> BlockParser[Block Parsing (Phase 1)]
+ BlockParser --> BlockTree[Block Tree]
+ BlockTree --> InlineParser[Inline Parsing (Phase 2)]
+ InlineParser --> MacroAST[Macro Syntax Tree]
+ MacroAST --> Evaluator[Macro Evaluator]
+ Evaluator --> HTML[Output HTML]
+```
+
+### 2.1 The Macro System
+The core logic revolves around Macros.
+* **Definition Syntax**: `%def[name]{arg1, arg2, ...}{body}`
+ * Example: `%def[my_macro]{t1, t2}{It’s a %em{%t1} that is %t2.}`
+* **Call Syntax**: `%name{arg1}{arg2}...`
+ * Example: `%my_macro{test}{good}`
+* **Expansion**: The Evaluator recursively expands macros until only text remains.
+
+### 2.2 CommonMark Parsing Strategy
+We strictly follow the CommonMark "Appendix A" strategy:
+1. **Phase 1 (Block Structure)**: Analyze the document line-by-line to construct a tree of Blocks (Paragraphs, Lists, Blockquotes). This handles nesting and indentation.
+2. **Phase 2 (Inline Structure)**: Walk the Block tree and parse the text content of leaf blocks into Inline elements (Emphasis, Links, Code).
+3. **Transformation**: Convert the CommonMark Block/Inline tree into the unified **Macro AST**.
+ * `# Heading` $\rightarrow$ `%h1{Heading}`
+ * `*Bold*` $\rightarrow$ `%em{Bold}`
+
+## 3. Data Structures
+
+### 3.1 AST Nodes
+The final tree consists of these node types:
+
+```cpp
+enum class NodeType { Text, Macro };
+
+struct Node {
+ virtual ~Node() = default;
+ virtual NodeType type() const = 0;
+};
+
+struct TextNode : public Node {
+ std::string content;
+ NodeType type() const override { return NodeType::Text; }
+};
+
+struct MacroNode : public Node {
+ std::string name;
+ std::vector<std::unique_ptr<Node>> arguments; // Arguments are themselves ASTs
+ bool is_special = false; // For intrinsics like %def
+ NodeType type() const override { return NodeType::Macro; }
+};
+```
+
+### 3.2 Block Structure (Intermediate)
+During Phase 1, we use a structure mirroring CommonMark blocks to maintain state (open/closed blocks, list types).
+
+```cpp
+enum class BlockType {
+ Document,
+ Quote,
+ List,
+ ListItem,
+ FencedCode,
+ IndentedCode,
+ HtmlBlock,
+ Paragraph,
+ Heading,
+ ThematicBreak,
+ // ... potentially others
+};
+
+struct Block {
+ BlockType type;
+ std::vector<std::unique_ptr<Block>> children; // For container blocks
+ std::string literal_content; // For leaf blocks (raw text to be parsed later)
+ int level = 0; // For headings
+ // ... metadata for parsing state
+};
+```
+
+### 3.3 Unicode Strategy
+* **Library**: Use [uni-algo](https://github.com/uni-algo/uni-algo) for all Unicode-related operations.
+* **Storage**: All text will be stored in `std::string` assuming **UTF-8** encoding.
+* **Operations**:
+ * **Iteration**: Use `uni::iter::utf8` for safe code point traversal.
+ * **Properties**: Use `uni::is_space` and `uni::is_punct` (or equivalent category checks) to comply with CommonMark's definitions of whitespace and punctuation.
+ * **Optimization**: Byte-by-byte scanning will still be used for performance when looking for ASCII-only delimiters (`%`, `{`, `}`, `[`, `]`).
+
+## 4. Component Design
+
+### 4.1 Block Parser (`BlockParser`)
+* **Input**: Line iterator.
+* **Mechanism**:
+ * Maintains a stack of "Open" blocks.
+ * For each line, determines which open blocks match the line's indentation/markers.
+ * Closes unmatched blocks and opens new ones.
+ * Adds text to the currently open leaf block.
+* **Output**: Root `Block`.
+
+### 4.2 Inline Parser (`InlineParser`)
+* **Input**: `literal_content` string from a Block.
+* **Mechanism**:
+ * Scans for delimiters (`*`, `_`, `[`, `` ` ``, `!`).
+ * **Crucially**: Scans for the Macro start character `%`.
+ * Uses the "Delimiter Stack" algorithm from CommonMark spec to resolve emphasis nesting.
+* **Output**: Converts the block's text into a list of `Node`s (Text and MacroNodes).
+
+### 4.3 Evaluator (`Evaluator`)
+* **Environment**: A map `std::map<std::string, MacroDefinition>`.
+* **Mechanism**:
+ * Traverses the `MacroNode` tree.
+ * If it's a `TextNode`, append to output.
+ * If it's a `MacroNode`:
+ * Look up definition.
+ * Bind arguments.
+ * Parse the definition body (if it's a user macro) or execute C++ callback (if intrinsic).
+ * Recursively evaluate the result.
+
+## 5. The Standard Library
+The system will boot with a "Prelude" of defined macros to support Markdown features.
+
+| Markdown Element | Macro Signature | HTML Expansion |
+| :--- | :--- | :--- |
+| Header 1 | `%h1{content}` | `<h1>%content</h1>` |
+| Paragraph | `%p{content}` | `<p>%content</p>` |
+| Emphasis | `%em{content}` | `<em>%content</em>` |
+| Strong | `%strong{content}` | `<strong>%content</strong>` |
+| Link | `%link{url}{text}` | `<a href="%url">%text</a>` |
+| Image | `%img{url}{alt}` | `<img src="%url" alt="%alt" />` |
+| List Item | `%li{content}` | `<li>%content</li>` |
+| Unordered List | `%ul{content}` | `<ul>%content</ul>` |
+| Code | `%code{content}` | `<code>%content</code>` |
+| Blockquote | `%quote{content}` | `<blockquote>%content</blockquote>` |
+
+## 6. Implementation Plan
+
+### Phase 1: Core Setup
+* CMake build system.
+* `Node` class hierarchy.
+* Basic `Evaluator` for text-only nodes.
+
+### Phase 2: Macro Engine
+* Implement `%def`.
+* Implement parsing of `%call{args}`.
+* Unit tests for macro expansion logic.
+
+### Phase 3: Block Parsing
+* Implement the "Container Block" and "Leaf Block" logic.
+* Handle simple paragraphs and ATX headings (`#`).
+* Convert these Blocks into `%p` and `%h1` macros.
+
+### Phase 4: Inline Parsing
+* Implement `InlineParser` to handle text.
+* Add support for `*em*` and `**strong**` mapping to macros.
+* Integrate `%macro` parsing within normal text.
+
+### Phase 5: Standard Library & HTML
+* Implement the C++ callbacks or default definitions for the standard library macros.
+* Finalize `main.cpp` CLI.
+
+## 7. Build System
+* **CMake**: 3.24+
+## 8. Coding Conventions
+
+* **File Names**: `snake_case` (e.g., `macro_engine.h`, `block_parser.cpp`).
+* **Classes and Types**: `CapCase` (e.g., `MacroNode`, `BlockType`).
+* **Variables**: `snake_case` (e.g., `literal_content`, `is_special`).
+* **Global Constants**: `UPPER_CASE` (e.g., `MAX_RECURSION_DEPTH`).
+* **Functions**:
+ * `camelCase` for multi-word names (e.g., `evaluateMacro`).
+ * `lower case` for single-word names (e.g., `type()`, `evaluate()`).
+
diff --git a/include/block.h b/include/block.h
new file mode 100644
index 0000000..3645462
--- /dev/null
+++ b/include/block.h
@@ -0,0 +1,35 @@
+#ifndef MACRODOWN_BLOCK_H
+#define MACRODOWN_BLOCK_H
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace macrodown {
+
+enum class BlockType {
+ Document,
+ Quote,
+ List,
+ ListItem,
+ FencedCode,
+ IndentedCode,
+ HtmlBlock,
+ Paragraph,
+ Heading,
+ ThematicBreak
+};
+
+struct Block {
+ BlockType type;
+ std::vector<std::unique_ptr<Block>> children; // For container blocks
+ std::string literal_content; // For leaf blocks
+ int level = 0; // For headings
+ bool open = true;
+
+ Block(BlockType t) : type(t) {}
+};
+
+} // namespace macrodown
+
+#endif // MACRODOWN_BLOCK_H
diff --git a/include/macro_engine.h b/include/macro_engine.h
new file mode 100644
index 0000000..8f81a15
--- /dev/null
+++ b/include/macro_engine.h
@@ -0,0 +1,49 @@
+#ifndef MACRODOWN_MACRO_ENGINE_H
+#define MACRODOWN_MACRO_ENGINE_H
+
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+#include <functional>
+#include "nodes.h"
+
+namespace macrodown {
+
+using MacroCallback = std::function<std::string(const std::vector<std::string>&)>;
+
+struct MacroDefinition {
+ std::string name;
+ std::vector<std::string> arg_names;
+ std::string body; // Raw body for user-defined macros
+ MacroCallback callback; // For intrinsic macros
+ bool is_intrinsic = false;
+
+ MacroDefinition() = default;
+
+ // For user-defined macros
+ MacroDefinition(std::string n, std::vector<std::string> args, std::string b)
+ : name(std::move(n)), arg_names(std::move(args)), body(std::move(b)), is_intrinsic(false) {}
+
+ // For intrinsic macros
+ MacroDefinition(std::string n, MacroCallback cb)
+ : name(std::move(n)), callback(std::move(cb)), is_intrinsic(true) {}
+};
+
+class Evaluator {
+public:
+ Evaluator();
+
+ void define(const std::string& name, const std::vector<std::string>& args, const std::string& body);
+ void defineIntrinsic(const std::string& name, MacroCallback callback);
+
+ std::string evaluate(const Node& node);
+ std::string evaluateMacro(const MacroNode& macro);
+
+private:
+ std::map<std::string, MacroDefinition> macros_;
+};
+
+} // namespace macrodown
+
+#endif // MACRODOWN_MACRO_ENGINE_H
diff --git a/include/nodes.h b/include/nodes.h
new file mode 100644
index 0000000..24c4279
--- /dev/null
+++ b/include/nodes.h
@@ -0,0 +1,43 @@
+#ifndef MACRODOWN_NODES_H
+#define MACRODOWN_NODES_H
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace macrodown {
+
+enum class NodeType {
+ Text,
+ Macro
+};
+
+// Abstract Base Class
+struct Node {
+ virtual ~Node() = default;
+ virtual NodeType type() const = 0;
+};
+
+// Represents a raw text segment
+struct TextNode : public Node {
+ std::string content;
+
+ TextNode(std::string c) : content(std::move(c)) {}
+ NodeType type() const override { return NodeType::Text; }
+};
+
+// Represents a macro call: %name{arg1}{arg2}...
+struct MacroNode : public Node {
+ std::string name;
+ std::vector<std::unique_ptr<Node>> arguments;
+ bool is_special = false; // Intrinsic macros like %def
+
+ MacroNode(std::string n, bool special = false)
+ : name(std::move(n)), is_special(special) {}
+
+ NodeType type() const override { return NodeType::Macro; }
+};
+
+} // namespace macrodown
+
+#endif // MACRODOWN_NODES_H
diff --git a/prompts.md b/prompts.md
new file mode 100644
index 0000000..a970cba
--- /dev/null
+++ b/prompts.md
@@ -0,0 +1,54 @@
+You are about to implement a markdown processor in C++ called
+“MacroDown”. The main feature besides markdown is it will support
+macros (TeX-like). The processor will output standard HTML.
+
+The processor will implement the CommonMark syntax. Specifically you
+should implement the parsing strategy outline in
+https://spec.commonmark.org/0.31.2/#appendix-a-parsing-strategy.
+However with this processor, you should convert all the all the syntax
+elements (emphsized text, bold text, quotes, code, etc.) into macros,
+and contruct a syntax tree. At the last step, evaluate the macros into
+HTML. A macro is basically a function that can have arguments, and can
+expand into text and more macros. For example, I can define a macro
+
+```
+%def[my_macro]{t1, t2}{It’s a %em{%t1} that is %t2.}
+```
+
+This code should define a macro called `my_macro`. It takes two
+arguments, `t1` and `t2`, and it expand the body with these arguments.
+If I write in my document `%my_macro{test}{good}`, it should expand
+into `It’s a %em{test} that is good`, in which there’s another macro,
+`em`, which will in turn expand into something else. Of course `def`
+is a special case that is used to define macros.
+
+In short, the syntax to define a macro should be
+```
+%def[name]{arg1, arg2, ...}{body}
+```
+The syntax to call a macro should be
+```
+%name{arg1}{arg2}...
+```
+
+In order for a CommonMark document to parse into HTML in this way, we
+will need to have a “standard library” of macros that implements the
+basic markdown constructs like headings, emphasis, etc.
+
+Note that a MacroDown document will mostly look like a normal
+CommonMark file, but a writer could also write macros definitions and
+calls in it.
+
+Naming style:
+
+* `CapCase` for classes and types
+* `snake_case` for variables
+* `UPPER_CASE` for global constants
+* `camelCase` for functions. If the function name is just one word,
+ use lower case.
+* All file names should be `snake_case`.
+
+Unicode should be handled properly.
+
+Use Cmake as the build system. You can see an exmaple cmake file at
+https://github.com/MetroWind/planck-blog/blob/master/CMakeLists.txt.
diff --git a/src/lib_placeholder.cpp b/src/lib_placeholder.cpp
new file mode 100644
index 0000000..4510c59
--- /dev/null
+++ b/src/lib_placeholder.cpp
@@ -0,0 +1,6 @@
+#include "nodes.h"
+#include "block.h"
+
+namespace macrodown {
+ // Initial placeholder for library sources
+}
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..368f2b8
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,6 @@
+#include <iostream>
+
+int main() {
+ std::cout << "MacroDown: A C++ Macro-Markdown Processor" << std::endl;
+ return 0;
+}
diff --git a/tests/test_main.cpp b/tests/test_main.cpp
new file mode 100644
index 0000000..ebf5a57
--- /dev/null
+++ b/tests/test_main.cpp
@@ -0,0 +1,10 @@
+#include <gtest/gtest.h>
+
+TEST(SetupTest, BasicAssertions) {
+ EXPECT_EQ(1 + 1, 2);
+}
+
+int main(int argc, char **argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}