All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fernice.flare.style.stylesheet.RulesIterator.kt Maven / Gradle / Ivy

/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

package org.fernice.flare.style.stylesheet

import org.fernice.flare.dom.Device
import org.fernice.flare.style.QuirksMode
import org.fernice.std.Kleenean
import java.util.*

class RulesIterator(
    private val device: Device,
    private val quirksMode: QuirksMode,
    private val condition: C,
    private val stack: LinkedList>,
) : Iterator {

    override fun hasNext(): Boolean {
        return stack.isNotEmpty() && stack.any { it.hasNext() }
    }

    override fun next(): CssRule {
        while (stack.isNotEmpty()) {
            val iterator = stack.peek()
            if (!iterator.hasNext()) {
                stack.pop()
                continue
            }
            val rule = iterator.next()

            val (children, effective) = children(rule, device, quirksMode, condition)
            if (effective != Effective.True) continue

            if (children != null) {
                stack.push(children)
            }

            return rule
        }
        throw NoSuchElementException()
    }

    fun skipChildren() {
        stack.pop()
    }

    companion object {

        fun  of(
            device: Device,
            quirksMode: QuirksMode,
            condition: C,
            rules: Iterator,
        ): RulesIterator {
            val stack = LinkedList>()
            stack.push(rules)
            return RulesIterator(
                device,
                quirksMode,
                condition,
                stack,
            )
        }

        fun children(
            rule: CssRule,
            device: Device,
            quirksMode: QuirksMode,
            condition: NestedRuleIterationCondition,
        ): Pair?, Effective> {
            return when (rule) {
                is CssRule.Style -> {
                    rule.styleRule.rules?.iterator() to Effective.True
                }

                is CssRule.Media -> {
                    val effective = condition.isMediaEffective(rule.mediaRule, device, quirksMode)
                    if (effective == Effective.False) {
                        return null to Effective.False
                    }
                    rule.mediaRule.rules.iterator() to effective
                }
            }
        }
    }
}

interface NestedRuleIterationCondition {
    fun isMediaEffective(
        rule: MediaRule,
        device: Device,
        quirksMode: QuirksMode,
    ): Effective
}

object EffectiveRules : NestedRuleIterationCondition {
    override fun isMediaEffective(
        rule: MediaRule,
        device: Device,
        quirksMode: QuirksMode,
    ): Effective {
        return when (rule.condition.matches(device, quirksMode)) {
            Kleenean.True -> Effective.True
            else -> Effective.False
        }
    }
}

object PotentiallyEffectiveRules : NestedRuleIterationCondition {
    override fun isMediaEffective(
        rule: MediaRule,
        device: Device,
        quirksMode: QuirksMode,
    ): Effective {
        return when (rule.condition.matches(device, quirksMode)) {
            Kleenean.True -> Effective.True
            Kleenean.False -> Effective.False
            Kleenean.Unknown -> Effective.Indeterminable(rule.condition)
        }
    }
}


sealed class Effective {
    data object True : Effective()
    data object False : Effective()
    data class Indeterminable(val condition: EffectiveCondition) : Effective()
}

interface EffectiveCondition {

    /**
     * Returns whether the condition is effective. [Kleenean.Unknown] is returned, if the
     * condition is indeterminable for the given parameters.
     */
    fun matches(
        device: Device,
        quirksMode: QuirksMode,
    ): Kleenean
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy