Ответ 1
Во-первых, давайте придерживаться узкого класса селекторов с именами тегов, именами классов и идентификаторами, ничего необычного, как E > F
или E + F
. Пусть также запрещают комбинации имен классов (.class1.class2.class3
), иначе один элемент с 10 именами классов будет генерировать только 4 миллиона селекторов.
Каждый из наших полных селекторов состоит из простых селекторов, разделенных пробелами. Каждый простой селектор представляет собой комбинацию tag{0,1}id{0,1}class{0,n}
- то есть каждый элемент имеет ровно один тег, не более одного идентификатора, и может иметь произвольное число имен классов. Это дает нам верхний предел 2 * 2 * (n + 1) простых селекторов для одного элемента.
Учитывая ссылку на элемент DOM, возьмите его имя тега, идентификатор и имена классов. Вычислите все возможные простые селекторы, как описано выше. Позволяет вызвать этот набор 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 ^ (m-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