-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Expand file tree
/
Copy pathattribute_processor.dart
More file actions
80 lines (69 loc) · 2.57 KB
/
attribute_processor.dart
File metadata and controls
80 lines (69 loc) · 2.57 KB
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
// Copyright 2025 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:jaspr_content/jaspr_content.dart';
import '../markdown/attribute_syntax.dart';
/// A node-processing, page extension for Jaspr Content that looks for
/// attribute markers from [AttributeBlockSyntax] and [AttributeInlineSyntax],
/// to remove them and transfer their configured attributes.
class AttributeProcessor implements PageExtension {
const AttributeProcessor();
@override
Future<List<Node>> apply(Page page, List<Node> nodes) async {
return _processNodes(nodes);
}
List<Node> _processNodes(List<Node> nodes) {
final processedNodes = <Node>[];
for (var i = 0; i < nodes.length; i++) {
final node = nodes[i];
if (node is ElementNode && node.tag == 'attribute-marker') {
// Found an attribute marker,
// apply its attributes to the previous element.
if (i > 0 && processedNodes.isNotEmpty) {
final previousIndex = processedNodes.length - 1;
final previousNode = processedNodes[previousIndex];
if (previousNode is ElementNode) {
processedNodes[previousIndex] = _applyAttributesToElement(
previousNode,
node.attributes,
);
}
}
// Skip adding this marker to processed nodes (effectively removing it).
continue;
} else if (node is ElementNode) {
final nodeChildren = node.children;
final processedChildren = nodeChildren != null
? _processNodes(nodeChildren)
: null;
processedNodes.add(
ElementNode(node.tag, node.attributes, processedChildren),
);
} else {
processedNodes.add(node);
}
}
return processedNodes;
}
ElementNode _applyAttributesToElement(
ElementNode element,
Map<String, String> attributes,
) {
final newAttributes = Map<String, String>.of(element.attributes);
for (final entry in attributes.entries) {
if (entry.key == 'class') {
final existingClass = newAttributes['class'];
if (existingClass != null && existingClass.isNotEmpty) {
newAttributes['class'] = '$existingClass ${entry.value}';
} else {
newAttributes['class'] = entry.value;
}
} else {
// For other attributes (such as id),
// set them directly.
newAttributes[entry.key] = entry.value;
}
}
return ElementNode(element.tag, newAttributes, element.children);
}
}