Initial commit
[yaffs-website] / node_modules / node-sass / src / libsass / src / sass_util.cpp
1 #include "sass.hpp"
2 #include "node.hpp"
3
4 namespace Sass {
5
6
7   /*
8     # This is the equivalent of ruby's Sass::Util.paths.
9     #
10     # Return an array of all possible paths through the given arrays.
11     #
12     # @param arrs [NodeCollection<NodeCollection<Node>>]
13     # @return [NodeCollection<NodeCollection<Node>>]
14     #
15     # @example
16     #   paths([[1, 2], [3, 4], [5]]) #=>
17     #     # [[1, 3, 5],
18     #     #  [2, 3, 5],
19     #     #  [1, 4, 5],
20     #     #  [2, 4, 5]]
21
22    The following is the modified version of the ruby code that was more portable to C++. You
23    should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
24
25     def paths(arrs)
26         // I changed the inject and maps to an iterative approach to make it easier to implement in C++
27       loopStart = [[]]
28
29       for arr in arrs do
30         permutations = []
31         for e in arr do
32           for path in loopStart do
33             permutations.push(path + [e])
34           end
35         end
36         loopStart = permutations
37       end
38     end
39   */
40   Node paths(const Node& arrs, Context& ctx) {
41
42     Node loopStart = Node::createCollection();
43     loopStart.collection()->push_back(Node::createCollection());
44
45     for (NodeDeque::iterator arrsIter = arrs.collection()->begin(), arrsEndIter = arrs.collection()->end();
46         arrsIter != arrsEndIter; ++arrsIter) {
47
48       Node& arr = *arrsIter;
49
50       Node permutations = Node::createCollection();
51
52       for (NodeDeque::iterator arrIter = arr.collection()->begin(), arrIterEnd = arr.collection()->end();
53         arrIter != arrIterEnd; ++arrIter) {
54
55         Node& e = *arrIter;
56
57         for (NodeDeque::iterator loopStartIter = loopStart.collection()->begin(), loopStartIterEnd = loopStart.collection()->end();
58           loopStartIter != loopStartIterEnd; ++loopStartIter) {
59
60           Node& path = *loopStartIter;
61
62           Node newPermutation = Node::createCollection();
63           newPermutation.got_line_feed = arr.got_line_feed;
64           newPermutation.plus(path);
65           newPermutation.collection()->push_back(e);
66
67           permutations.collection()->push_back(newPermutation);
68         }
69       }
70
71       loopStart = permutations;
72     }
73
74     return loopStart;
75   }
76
77
78   /*
79   This is the equivalent of ruby sass' Sass::Util.flatten and [].flatten.
80   Sass::Util.flatten requires the number of levels to flatten, while
81   [].flatten doesn't and will flatten the entire array. This function
82   supports both.
83
84   # Flattens the first `n` nested arrays. If n == -1, all arrays will be flattened
85   #
86   # @param arr [NodeCollection] The array to flatten
87   # @param n [int] The number of levels to flatten
88   # @return [NodeCollection] The flattened array
89
90   The following is the modified version of the ruby code that was more portable to C++. You
91   should be able to drop it into ruby 3.2.19 and get the same results from ruby sass.
92
93   def flatten(arr, n = -1)
94     if n != -1 and n == 0 then
95       return arr
96     end
97
98     flattened = []
99
100     for e in arr do
101       if e.is_a?(Array) then
102         flattened.concat(flatten(e, n - 1))
103       else
104         flattened << e
105       end
106     end
107
108     return flattened
109   end
110   */
111   Node flatten(Node& arr, Context& ctx, int n) {
112     if (n != -1 && n == 0) {
113       return arr;
114     }
115
116     Node flattened = Node::createCollection();
117     if (arr.got_line_feed) flattened.got_line_feed = true;
118
119     for (NodeDeque::iterator iter = arr.collection()->begin(), iterEnd = arr.collection()->end();
120         iter != iterEnd; iter++) {
121         Node& e = *iter;
122
123       // e has the lf set
124       if (e.isCollection()) {
125
126         // e.collection().got_line_feed = e.got_line_feed;
127         Node recurseFlattened = flatten(e, ctx, n - 1);
128
129         if(e.got_line_feed) {
130                  flattened.got_line_feed = e.got_line_feed;
131           recurseFlattened.got_line_feed = e.got_line_feed;
132         }
133
134         for(auto i : (*recurseFlattened.collection())) {
135           if (recurseFlattened.got_line_feed) {
136
137             i.got_line_feed = true;
138           }
139           flattened.collection()->push_back(i);
140         }
141
142       } else {
143         flattened.collection()->push_back(e);
144       }
145     }
146
147     return flattened;
148   }
149 }