예제
KO

Sass/SCSS

Hwaro는 빌드 시점에 순수 Crystal로 구현된 내장 컴파일러로 SCSS를 컴파일합니다. dart-sass 바이너리 설치도, npm 툴체인도, C 라이브러리도 필요 없습니다 — 외부 의존성 없음이라는 Hwaro의 철학 그대로입니다.

빠른 시작

[sass]
enabled = true

SCSS 파일을 static/ 아래에 둡니다.

static/
├── css/
│   ├── _variables.scss   # partial — never published
│   ├── _mixins.scss      # partial — never published
│   └── style.scss        # entry — compiles to /css/style.css
// static/css/style.scss
@use "variables";
@use "mixins";

.card {
  color: variables.$primary;
  &:hover { color: variables.$accent; }

  @include mixins.respond(768px) {
    padding: 2rem;
  }
}

파셜이 아닌 모든 *.scss는 출력에서 같은 경로의 .css로 컴파일되므로(static/css/style.scss/css/style.css), 스타일시트 URL이 안정적으로 유지됩니다.

<link rel="stylesheet" href="{{ url_for(path="/css/style.css") }}">

규칙

설정

옵션 타입 기본값 설명
enabled bool false SCSS 컴파일 활성화
minify bool true 컴파일된 CSS 압축(에셋 파이프라인과 같은 압축기 사용)

지원 범위

Hwaro는 실용적인 SCSS 부분집합을 구현합니다 — 직접 작성하는 사이트 스타일시트에서 실제로 쓰이는 기능들입니다.

기능 지원
$variables !default / !global, 렉시컬 스코프와 섀도잉 지원
중첩 규칙 ✅ 셀렉터 목록 포함(카테시안 조합)
& 부모 셀렉터 &:hover, &.mod, BEM &__elem / &--mod
#{...} 보간 ✅ 셀렉터, 속성 이름, 값, at-규칙 서두, 문자열, url() — 내부에서 전체 표현식 평가
파셜 + @use ✅ 네임스페이스(colors.$primary), as x, as *, 1회 로드, with (...) 설정
@forward show / hide 필터, as prefix-*
@import(Sass 파일) ✅ 클래식 전역 병합 시맨틱, 순수 CSS 형태는 그대로 통과
@mixin / @include ✅ 기본값, 키워드 인자, 가변 인자 $args..., 스프레드, @content 블록
@function / @return ✅ 값 안에서 호출 가능한 사용자 함수, 기본값/키워드/가변 인자, 재귀
제어 흐름 @if / @else if / @else, @each(구조 분해 포함), @for(through/to, 내림차순), @while
SassScript 표현식 ✅ 산술(+ - * %), 비교, and/or/not, 문자열, 리스트, 맵 — /는 차이점 참고
내장 함수 sass:math, sass:string, sass:list, sass:map, sass:meta 부분집합 + 레거시 전역 이름(map-get, nth, if() 등)
@debug / @warn / @error @error는 위치 정보가 담긴 메시지로 빌드를 실패시킴
@at-root ✅ 셀렉터 형태와 블록 형태(with:/without: 쿼리는 제외)
규칙 안의 @media / @supports ✅ 중첩 밖으로 자동 버블링, 피처 값에서 표현식 평가
@keyframes, @font-face, 커스텀 속성 ✅ 올바르게 통과
순수 CSS ✅ 유효한 .css는 그대로 컴파일(공백 정규화)

알 수 없는 함수(calc(), var(), rgba(), clamp(), color-mix() 등)는 손대지 않고 그대로 통과합니다 — 인자는 평가됩니다(translate($x * 2, -50%) 동작).

@use "sass:math";
$breakpoints: (sm: 640px, md: 768px, lg: 1024px);

@function rem($px, $base: 16px) { @return math.div($px, $base) * 1rem; }

@mixin respond($name) {
  @if not map-has-key($breakpoints, $name) { @error "unknown breakpoint #{$name}"; }
  @media (min-width: map-get($breakpoints, $name)) { @content; }
}

@each $name, $bp in $breakpoints {
  .container-#{$name} { max-width: $bp - 24px; }
}
@for $i from 1 through 12 {
  .col-#{$i} { width: math.percentage(math.div($i, 12)); }
}
.hero {
  font-size: rem(28px);
  @include respond(md) { font-size: rem(40px); }
}

미지원 (아직)

@extend, 컬러 값과 color.* 함수, 단위 변환(pxcm), @at-root (with: ...) 쿼리, @forward ... with (...), @content(args) / using, math.random / unique-id()(빌드는 결정적이어야 합니다), 중첩 속성(font: { family: ... }), 들여쓰기 방식의 .sass 문법, 소스맵은 지원하지 않습니다.

미지원 지시문은 위치 정보가 담긴 오류와 함께 빌드를 실패시킵니다 — Hwaro는 조용히 깨진 CSS를 내보내지 않습니다.

Error [HWARO_E_CONTENT]: Sass: static/css/style.scss:14:3: @extend is not supported by hwaro's Sass subset (yet)

표현식 시맨틱

이 컴파일러의 첫 번째 의무는 순수 CSS 보장이므로, 표현식은 두 단계 정책을 따릅니다.

dart-sass와의 차이

오류

컴파일 실패는 콘텐츠 오류로 분류되며(종료 코드 5), path:line:column 위치 정보가 함께 표시됩니다.

Error [HWARO_E_CONTENT]: Sass: static/css/_mixins.scss:7:12: undefined variable: "$primry"

hwaro serve 중에는 오류가 브라우저 오버레이에 표시되고, 이전 출력은 디스크에 그대로 남습니다.

다른 기능과의 상호작용