Во-первых, давайте придерживаться узкого класса селекторов, включающего имена тегов, имена классов и идентификаторы, ничего необычного, например, E > F
или E + F
. Давайте также запретим комбинации имен классов (.class1.class2.class3
), иначе один элемент с 10 именами классов сгенерирует только 4 миллиона селекторов.
Каждый из наших полных селекторов состоит из простых селекторов, разделенных пробелами. Каждый простой селектор представляет собой комбинацию tag{0,1}id{0,1}class{0,n}
, то есть каждый элемент имеет ровно один тег, максимум один идентификатор, и может иметь произвольное количество имен классов. Это дает нам верхний предел 2 * 2 * (n + 1) простых селекторов для одного элемента.
Учитывая ссылку на элемент DOM, захватите его имя тега, ID и имена классов. Рассчитайте все возможные простые селекторы, как описано выше. Давайте назовем это множество A1. Переместите один шаг вверх по иерархии к его родителю, вычислите все простые селекторы для этого родительского элемента - это будет набор A2. Продолжайте, пока не дойдете до элемента html - набора Am. Теперь у вас будет список, состоящий из m элементов, каждый из которых представляет собой набор простых селекторов.
Теперь выберите некоторые из этих наборов и найдите их декартово произведение. Скажем, m = 5. Сколько комплектов вы можете выбрать? Набор A1 всегда присутствует, но другие являются необязательными. Для каждого из них вы либо выбираете, либо нет. Это похоже на двоичные числа:
0000 // 0, A1
0001 // 1, A1 x A2
0010 // 2, A1 x A3
0011 // 3, A1 x A2 x A3
0100 // 4, A1 x A4
...
Это означает, что у вас будет 2 ^ (м-1) декартовых произведений. Теперь вы можете конвертировать их в строки. Последний шаг - удаление дубликатов, рассмотрим этот пример:
<div>
<div>
<span></span>
</div>
</div>
Наши расчеты приведут к следующему списку:
span
div span // inner div
div span // outer div
div div span
Эти два div приводят к дублированию селекторов. Удалить те, и работа сделана.
Все шаги очень просты алгоритмически. Я уверен, что вы можете их выяснить, но если вы застряли где-то или вам нужны дополнительные разъяснения, не стесняйтесь спрашивать меня в комментариях.
UPDATE
Итак, я решил немного поиграть с ним и написал программу, вот список селекторов, которые генерирует ваш пример: http://pastie.org/1616164