동적 테마 생성을 위한 규칙 기반 프레임워크

12월에 저는 Firefox의 테마 API에 대한 소개를 했습니다. 이는 animated themes, macOS-style overscroll 또는 interactive theme editors와 같은 많은 것들을 할 수 있게 해주지만 몇 가지 한계가 있습니다. 전통적인 CSS와 비교해서 동적 테마 API의 한 가지 문제는 기본 동적 테마를 만들기 위해선 JavaScript와 WebExtension API를 알아야 한다는 점입니다.

이 문제를 해결하기 위해 간단한 테마 “규칙”을 사용하여 동적 테마를 사용하는 간단한 시스템으로 실험을 진행하였습니다. “규칙”은 테마 이름 쌍을 나타내는 JavaScript 조건 문자열로 구성되어 있습니다. 여기 있습니다: https://github.com/nt1m/theming-rules

이 boilerplate는 WebExtension 리스너를 설정하고 다른 API와 연동하기 위해 동적 테마에 필요한 모든 복잡한 작업을 처리하여 우리가 동적 테마 설정에 집중할 수 있게 해줍니다.

위의 저장소를 클론하여 시작합시다. 모든 설정은 boilerplate의 config.js 파일에 위치합니다. 이 파일을 열면 아래와 같은 코드를 보시게 될 것입니다:

// The default theme: used when no rule is matched
const DEFAULT_THEME = "bright";

// The theming rules: priority is given to the bottom-most rule
const RULES = [
    ["privatebrowsing", "shady"],
    ["(hour >= 21) || (hour < 9)", "shady"]
];

이런 경우, “shady” 테마는 사생활 보호 탭에서 저녁 9시부터 아침 9시까지 사용됩니다. 다른 모든 경우에서는 “bright” 기본 테마가 사용됩니다.

좀 더 복잡하게 config.js 파일을 수정해 봅시다:

// The default theme: used when no rule is matched
onst DEFAULT_THEME = "bright";

// The theming rules: priority is given to the bottom-most rule
const RULES = [
    ["privatebrowsing", "shady"],
    ["(hour >= 21) || (hour < 9)", "shady"],
    ["privatebrowsing && ((hour >= 21) || (hour < 9))", "bright"]
];

어떤 동작을 할지 예상이 되십니까?

힌트입니다: 규칙에는 “우선순위” 개념이 있어, 하나 이상의 규칙이 만족하면 가장 아래의 규칙이 사용됩니다.

이 경우에는, “bright” 테마는 밤 시간의 사생활 보호 창과 낮 시간 동안에 사용됩니다. “shady” 테마는 낮 시간의 사생활 보호 창과 밤 시간에 사용됩니다. 휴!

사용하실 수 있는 몇 가지 프로퍼티가 더 있습니다:

  • inactive_window
  • privatebrowsing
  • container
  • domain
  • protocol
  • year
  • month
  • date
  • day
  • hour
  • minutes
  • seconds

이 글의 후반부에서 여러분만의 프로퍼티를 정의하는 방법을 알려드리겠습니다.

이전 예제에서 사용된 “bright”와 “shady” 테마를 포함해, 이런 테마들은 표준 WebExtension 테마 형식으로 정의되어 있고, config.js 파일에도 있습니다:

const THEMES = {
    bright: {
        images: {
            headerURL: ""
        },
        colors: {
            accentcolor: "#dedede",
            textcolor: "#000",
            toolbar_text: "#000",
            toolbar: "#f8f8f8",
        }
    },
    shady: {
        images: {
            headerURL: ""
        },
        colors: {
            accentcolor: "#000",
            textcolor: "#ddd",
            toolbar_text: "#ccc",
            toolbar: "#3a3a3a"
        }
    }
};

유즈 케이스: 프로토콜 기반 브라우저 스타일링

이제 시스템에 대한 소개를 했으니, 유용한 예제를 만들어 봅시다: 현재 탭이 HTTP 페이지인지 HTTPS 페이지인지 여부에 따라 브라우저를 스타일링 해봅시다.

먼저 HTTP와 HTTPS 테마의 외관을 정의할겁니다. HTTP 사이트는 빨강, HTTPS 사이트는 초록을 사용합시다:

insecure: {
    images: {
        headerURL: ""
    },
    colors: {
        accentcolor: "red",
        textcolor: "black",
        toolbar: "pink",
        toolbar_text: "black"
    }
},
secure: {
    images: {
        headerURL: ""
    },
    colors: {
        accentcolor: "green",
        textcolor: "white",
        toolbar: "lightgreen",
        toolbar_text: "black"
    }
}

 

이제 규칙을 정의합시다:

// The default theme: used when no rule is matched
const DEFAULT_THEME = "bright";
// The theming rules: priority is given to the bottom-most rule
const RULES = [
    ["protocol == 'http:'", "insecure"],
    ["protocol == 'https:'", "secure"]
];

…됐습니다! “bright”를 기본 테마로 유지하고 있는것에 유의하시기 바랍니다. 이는 file://와 같이 extension에 테마가 적용되지 않는 다른 프로토콜이 존재하기 때문입니다.

예제는 다음과 같이 나타납니다:

더 많은 프로퍼티 추가하기

여러분은 특별한 키워드인 privatebrowsing, hour 그리고 protocol 를 알아채셨을 수도 있습니다. 이는 내장된 프로퍼티이며 다음과 같은 형태로 정의되어 있습니다:

privatebrowsing: {
    type: "boolean",
    async get(tab) {
        return tab.incognito;
    }
},
protocol: {
    type: "string",
    async get(tab) {
        return new URL(tab.url).protocol;
    }
},
hour: {
    type: "integer",
    async get(tab) {
        return (new Date(Date.now())).getHours();
    }
}

각 프로퍼티 정의는 WebExtension Tab object (무시하도록 선택 가능)를 사용하며, 하나의 값을 반환합니다.

모든 내장 프로퍼티 정의는 properties.js 파일에서 확인하실 수 있습니다.

여러분만의 프로퍼티 추가를 원하십니까? 프로퍼티 추가는 프로퍼티 정의 추가와 같이 간단합니다. 쿠키 API를 사용하여 현재 탭 도메인에 대한 쿠키의 수를 반환하는 에제입니다:


cookies: {
    type: "integer",
    async get(tab) {
        let cookies = await browser.cookies.getAll({
            domain: new URL(tab.url).hostname
        });
        return cookies.length;
    }
}

쿠키의 수에 따라 탭의 스타일을 다르게 설정하도록 활용할 수 있습니다.

프로퍼티 정의는 아주 유연하며, XHR을 통해 현재 날씨를 반환하거나 페이지의 추적자수를 반환하는 프로퍼티를 설정할수도 있습니다. 이는 여러분의 상상에 달려있습니다 🙂

한번 시도해보세요!

WebExtinsion API에 대한 깊은 지식을 필요로하지 않는 동적 테마를 생성하는 아주 간단한 방법이 필요하든, 상황별 UI 기능을 빠르게 프로토타이핑하기 위한 간단한 방법이 필요하든, 이는 여러분에게 가장 적합한 도구입니다!

이 시스템을 사용하는데에는 아주 많은 가능성이 있으며, 여러분이 무엇을 만들어 낼 수 있을지 기대됩니다.

저장소입니다: https://github.com/nt1m/theming-rules.

댓글이나 Github 이슈에 여러분의 경험을 자유롭게 공유해주세요.

이 글은 Tim NguyenA rule-based framework to create dynamic themes의 한국어 번역입니다.

작성자: Seul Gi Choi

Open Source // Web // Javascript // Map engineer

Seul Gi Choi가 작성한 문서들…


댓글이 없습니다.

댓글 쓰기