|
7 | 7 |
|
8 | 8 | namespace jinja2
|
9 | 9 | {
|
| 10 | + |
| 11 | +template<typename F> |
| 12 | +struct FilterFactory |
| 13 | +{ |
| 14 | + static FilterPtr Create(FilterParams params) |
| 15 | + { |
| 16 | + return std::make_shared<F>(std::move(params)); |
| 17 | + } |
| 18 | + |
| 19 | + template<typename ... Args> |
| 20 | + static ExpressionFilter::FilterFactoryFn MakeCreator(Args&& ... args) |
| 21 | + { |
| 22 | + return [args...](FilterParams params) {return std::make_shared<F>(std::move(params), args...);}; |
| 23 | + } |
| 24 | +}; |
| 25 | + |
| 26 | +std::unordered_map<std::string, ExpressionFilter::FilterFactoryFn> s_filters = { |
| 27 | + {"attr", &FilterFactory<filters::Attribute>::Create}, |
| 28 | + {"batch", FilterFactory<filters::Slice>::MakeCreator(filters::Slice::BatchMode)}, |
| 29 | + {"camelize", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::CamelMode)}, |
| 30 | + {"capitalize", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::CapitalMode)}, |
| 31 | + {"default", &FilterFactory<filters::Default>::Create}, |
| 32 | + {"d", &FilterFactory<filters::Default>::Create}, |
| 33 | + {"dictsort", &FilterFactory<filters::DictSort>::Create}, |
| 34 | + {"escape", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::EscapeHtmlMode)}, |
| 35 | + {"escapecpp", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::EscapeCppMode)}, |
| 36 | + {"first", FilterFactory<filters::SequenceAccessor>::MakeCreator(filters::SequenceAccessor::FirstItemMode)}, |
| 37 | + {"float", FilterFactory<filters::ValueConverter>::MakeCreator(filters::ValueConverter::ToFloatMode)}, |
| 38 | + {"format", FilterFactory<filters::StringFormat>::MakeCreator(filters::StringFormat::PythonMode)}, |
| 39 | + {"groupby", &FilterFactory<filters::GroupBy>::Create}, |
| 40 | + {"int", FilterFactory<filters::ValueConverter>::MakeCreator(filters::ValueConverter::ToIntMode)}, |
| 41 | + {"join", &FilterFactory<filters::Join>::Create}, |
| 42 | + {"last", FilterFactory<filters::SequenceAccessor>::MakeCreator(filters::SequenceAccessor::LastItemMode)}, |
| 43 | + {"length", FilterFactory<filters::SequenceAccessor>::MakeCreator(filters::SequenceAccessor::LengthMode)}, |
| 44 | + {"list", FilterFactory<filters::ValueConverter>::MakeCreator(filters::ValueConverter::ToListMode)}, |
| 45 | + {"map", &FilterFactory<filters::Map>::Create}, |
| 46 | + {"max", FilterFactory<filters::SequenceAccessor>::MakeCreator(filters::SequenceAccessor::MaxItemMode)}, |
| 47 | + {"min", FilterFactory<filters::SequenceAccessor>::MakeCreator(filters::SequenceAccessor::MinItemMode)}, |
| 48 | + {"pprint", &FilterFactory<filters::PrettyPrint>::Create}, |
| 49 | + {"random", &FilterFactory<filters::Random>::Create}, |
| 50 | + {"reject", FilterFactory<filters::Tester>::MakeCreator(filters::Tester::RejectMode)}, |
| 51 | + {"rejectattr", FilterFactory<filters::Tester>::MakeCreator(filters::Tester::RejectAttrMode)}, |
| 52 | + {"replace", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::ReplaceMode)}, |
| 53 | + {"round", FilterFactory<filters::ValueConverter>::MakeCreator(filters::ValueConverter::RoundMode)}, |
| 54 | + {"reverse", FilterFactory<filters::SequenceAccessor>::MakeCreator(filters::SequenceAccessor::ReverseMode)}, |
| 55 | + {"select", FilterFactory<filters::Tester>::MakeCreator(filters::Tester::SelectMode)}, |
| 56 | + {"selectattr", FilterFactory<filters::Tester>::MakeCreator(filters::Tester::SelectAttrMode)}, |
| 57 | + {"slice", FilterFactory<filters::Slice>::MakeCreator(filters::Slice::SliceMode)}, |
| 58 | + {"sort", &FilterFactory<filters::Sort>::Create}, |
| 59 | + {"sum", FilterFactory<filters::SequenceAccessor>::MakeCreator(filters::SequenceAccessor::SumItemsMode)}, |
| 60 | + {"title", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::TitleMode)}, |
| 61 | + {"tojson", FilterFactory<filters::Serialize>::MakeCreator(filters::Serialize::JsonMode)}, |
| 62 | + {"toxml", FilterFactory<filters::Serialize>::MakeCreator(filters::Serialize::XmlMode)}, |
| 63 | + {"toyaml", FilterFactory<filters::
10000
Serialize>::MakeCreator(filters::Serialize::YamlMode)}, |
| 64 | + {"trim", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::TrimMode)}, |
| 65 | + {"truncate", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::TruncateMode)}, |
| 66 | + {"unique", FilterFactory<filters::SequenceAccessor>::MakeCreator(filters::SequenceAccessor::UniqueItemsMode)}, |
| 67 | + {"upper", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::UpperMode)}, |
| 68 | + {"wordcount", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::WordCountMode)}, |
| 69 | + {"wordwrap", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::WordWrapMode)}, |
| 70 | + {"underscorize", FilterFactory<filters::StringConverter>::MakeCreator(filters::StringConverter::UnderscoreMode)},}; |
| 71 | + |
| 72 | +extern FilterPtr CreateFilter(std::string filterName, CallParams params) |
| 73 | +{ |
| 74 | + auto p = s_filters.find(filterName); |
| 75 | + if (p == s_filters.end()) |
| 76 | + return FilterPtr(); |
| 77 | + |
| 78 | + return p->second(std::move(params)); |
| 79 | +} |
| 80 | + |
10 | 81 | namespace filters
|
11 | 82 | {
|
12 | 83 |
|
@@ -142,12 +213,43 @@ InternalValue GroupBy::Filter(const InternalValue& baseVal, RenderContext& conte
|
142 | 213 |
|
143 | 214 | Map::Map(FilterParams params)
|
144 | 215 | {
|
| 216 | + FilterParams newParams; |
| 217 | + |
| 218 | + if (params.kwParams.size() == 1 && params.posParams.empty() && params.kwParams.count("attribute") == 1) |
| 219 | + { |
| 220 | + newParams.kwParams["name"] = params.kwParams["attribute"]; |
| 221 | + newParams.kwParams["filter"] = std::make_shared<ConstantExpression>(std::string("attr")); |
| 222 | + } |
| 223 | + else |
| 224 | + { |
| 225 | + newParams = std::move(params); |
| 226 | + } |
145 | 227 |
|
| 228 | + ParseParams({{"filter", true}}, newParams); |
| 229 | + m_mappingParams.kwParams = m_args.extraKwArgs; |
| 230 | + m_mappingParams.posParams = m_args.extraPosArgs; |
146 | 231 | }
|
147 | 232 |
|
148 | 233 | InternalValue Map::Filter(const InternalValue& baseVal, RenderContext& context)
|
149 | 234 | {
|
150 |
| - return InternalValue(); |
| 235 | + InternalValue filterName = GetArgumentValue("filter", context); |
| 236 | + if (IsEmpty(filterName)) |
| 237 | + return InternalValue(); |
| 238 | + |
| 239 | + auto filter = CreateFilter(AsString(filterName), m_mappingParams); |
| 240 | + if (!filter) |
| 241 | + return InternalValue(); |
| 242 | + |
| 243 | + bool isConverted = false; |
| 244 | + auto list = ConvertToList(baseVal, isConverted); |
| 245 | + if (!isConverted) |
| 246 | + return InternalValue(); |
| 247 | + |
| 248 | + InternalValueList resultList; |
| 249 | + resultList.reserve(list.GetSize()); |
| 250 | + std::transform(list.begin(), list.end(), std::back_inserter(resultList), [filter, &context](auto& val) {return filter->Filter(val, context);}); |
| 251 | + |
| 252 | + return ListAdapter::CreateAdapter(std::move(resultList)); |
151 | 253 | }
|
152 | 254 |
|
153 | 255 | PrettyPrint::PrettyPrint(FilterParams params)
|
|
0 commit comments