diff --git a/src/ddoc/macros.d b/src/ddoc/macros.d
index b6fe1bd..f74d602 100644
--- a/src/ddoc/macros.d
+++ b/src/ddoc/macros.d
@@ -169,7 +169,7 @@ shared static this()
* To undefine hardwired macros, just set them to an empty string: $(D macros["B"] = "";).
* output = An object satisfying $(D std.range.isOutputRange), usually a $(D std.array.Appender).
*/
-void expand(O)(Lexer input, in string[string] macros, O output) if (isOutputRange!(O,
+void expand(O)(Lexer input, in string[string] macros, O output, bool removeUnknown = true) if (isOutputRange!(O,
string))
{
// First, we need to turn every embedded code into a $(D_CODE)
@@ -183,7 +183,16 @@ void expand(O)(Lexer input, in string[string] macros, O output) if (isOutputRang
{
auto mac = Lexer(matchParenthesis(input), true);
if (!mac.empty)
- expandMacroImpl(mac, macros, output);
+ {
+ if (!expandMacroImpl(mac, macros, output) && !removeUnknown)
+ {
+ output.put("$");
+ output.put("(");
+ foreach (val; mac)
+ output.put(val.text);
+ output.put(")");
+ }
+ }
}
else
output.put("$");
@@ -197,12 +206,12 @@ void expand(O)(Lexer input, in string[string] macros, O output) if (isOutputRang
}
/// Ditto
-string expand(Lexer input, string[string] macros)
+string expand(Lexer input, string[string] macros, bool removeUnknown = true)
{
import std.array : appender;
auto app = appender!string();
- expand(input, macros, app);
+ expand(input, macros, app, removeUnknown);
return app.data;
}
@@ -222,6 +231,14 @@ unittest
assert(r == exp, r);
}
+unittest
+{
+ auto lex = Lexer(`$(B this) $(UNKN $(B is)) unknown!`);
+ immutable r = expand(lex, [`B` : `$0`], false);
+ immutable exp = `this $(UNKN $(B is)) unknown!`;
+ assert(r == exp, r);
+}
+
/**
* Expand a macro, and write the result to an $(D OutputRange).
*
@@ -439,20 +456,20 @@ bool parseKeyValuePair(ref Lexer lexer, ref KeyValuePair[] pairs)
private:
// upperArgs is a string[11] actually, or null.
-void expandMacroImpl(O)(Lexer input, in string[string] macros, O output)
+bool expandMacroImpl(O)(Lexer input, in string[string] macros, O output)
{
import std.conv : text;
//debug writeln("Expanding: ", input.text);
// Check if the macro exist and get it's value.
if (input.front.type != Type.word)
- return;
+ return false;
string macroName = input.front.text;
//debug writeln("[EXPAND] Macro name: ", input.front.text);
string macroValue = lookup(macroName, macros);
// No point loosing time if the macro is undefined.
if (macroValue is null)
- return;
+ return false;
//debug writeln("[EXPAND] Macro value: ", macroValue);
input.popFront();
@@ -460,7 +477,7 @@ void expandMacroImpl(O)(Lexer input, in string[string] macros, O output)
if (input.empty && macroName == "BODY")
{
output.put(lookup("BODY", macros));
- return;
+ return true;
}
// Collect the arguments
@@ -472,10 +489,11 @@ void expandMacroImpl(O)(Lexer input, in string[string] macros, O output)
// First pass
auto argOutput = appender!string();
if (!replaceArgs(macroValue, arguments, argOutput))
- return;
+ return true;
// Second pass
replaceMacs(argOutput.data, macros, output);
+ return true;
}
unittest