언어부터 제품까지. 직접 만들고 운영합니다.

언어와 시스템, 웹 서비스와 인프라를 설계해 헤이즈캔버스와 헤이즈사운드, 헤이즈스토리를 움직이는 디지털 레이어를 만듭니다.

typeset-ko.tpz 문단의 줄을 나누는 두 방법 Topaz 5.21.3

앞에서부터 채움

문단 전체를 보고 줄을나누면 마지막 줄이짧게 남지 않고 줄마다길이가 고르게됩니다.

5 줄 · totalCost 730762850

문단 전체를 보고 나눔

문단 전체를 보고줄을 나누면 마지막줄이 짧게 남지않고 줄마다 길이가고르게 됩니다.

5 줄 · totalCost 98339632

한글 10pt · 빈칸 2.5pt · 한국어 금칙 · greedy / Knuth-Plass

실행하는 소스 보기소스 내려받기
import std.ioimport std.typeset {  BreakCluster, BreakPolicy, BreakMode, KinsokuRules, BreakOpportunity, Paragraph, Item,  Box, Penalty, BreakRule, DistanceGrid, CostModel, LineGeometry, JustificationPolicy,  JustificationMode, KnuthPlassPolicy, ParagraphPlan, PlanLine, classifyBreaks,  breakParagraph,}// HAZE adapter. First stdin line is width in millipoints, followed by the sentence.let hazeInput = io.readStdin().split("\n")let 줄너비 = hazeInput[0].toInt() ?? 100000// 너비는 1000분의 1포인트 단위입니다. 한글은 10포인트, 빈칸은 2.5포인트로 둡니다.function 글자(낱자: string) -> BreakCluster {    BreakCluster { text: 낱자, advance: if 낱자 == " " { 2500 } else { 10000 }, trackingAfter: 0 }}// 유니코드 줄바꿈 규칙(UAX #14)에 한국어 금칙(KLReq)을 더합니다. 줄에 들어가는 낱말은 쪼개지 않습니다.function 한국어규칙(글자들: Array<BreakCluster>) -> BreakPolicy {    BreakPolicy {        mode: BreakMode.Word, rules: KinsokuRules.Unicode16Ko,        forbidBefore: [], forbidAfter: [], boundaryAllowed: 글자들.map((c: BreakCluster) => true),        generatedHyphenEnds: [], protectFittingLatin: false, preserveShortWords: false,        narrowestWordTarget: 줄너비, bodyWordTarget: 줄너비    }}// 글자마다 상자 하나, 줄을 나눌 수 있는 자리마다 벌점 0을 둡니다. 마지막 자리에서는 반드시 줄을 끝냅니다.function 문단(글자들: Array<BreakCluster>, 자리들: Array<BreakOpportunity>) -> Paragraph {    let mut 항목: Array<Item> = []    for 번호 in 0..<글자들.length {        let 낱자 = 글자들[번호]        항목.push(Item.BoxItem(Box { unitIndex: 번호, text: 낱자.text, width: 낱자.advance, trackingAfter: 0 }))    }    for 자리 in 자리들 {        let 끝 = 자리.unitEnd == 글자들.length        항목.push(Item.PenaltyItem(Penalty {            unitEnd: 자리.unitEnd, width: 0, kind: 자리.kind, flagged: false,            rule: if 끝 { BreakRule.Forced } else { BreakRule.Allowed(0) }        }))    }    Paragraph {        grid: DistanceGrid.MilliPoint, items: 항목, costModel: CostModel.FixedPoint,        geometry: LineGeometry { bodyTarget: 줄너비, firstTarget: 줄너비, dropCapSpan: 0, dropCapInset: 0 },        justification: JustificationPolicy {            mode: JustificationMode.Unjustified, minGapCount: 0, minLineWidthRatioM: 0,            minFinalLineWidthRatioM: None, maxAdjustment: 0, maxGapAdjustment: 0, maxGapRatioR: 0,            latinSpacing: None, cjkStretchRatio: 0.0        },        knuthPlass: KnuthPlassPolicy {            toleranceR: 0, linePenalty: 0, fitnessDemerit: 0, flaggedDemerit: 0, finalFlaggedDemerit: 0        }    }}// 줄마다 글자를 이어 붙이고 줄 끝 빈칸은 뺍니다.function 줄글(글자들: Array<BreakCluster>, 계획: ParagraphPlan) -> string {    계획.lines        .map((줄: PlanLine) => 글자들.slice(줄.start, 줄.trimmedEndExclusive).map((c: BreakCluster) => c.text).join(""))        .join("\n")}let 문장 = hazeInput.slice(1, hazeInput.length).join("\n")let 글자들 = 문장.scalars().map(글자)let 결과 = classifyBreaks(글자들, 한국어규칙(글자들))    .flatMap((자리들: Array<BreakOpportunity>) => breakParagraph(문단(글자들, 자리들)))match 결과 {    case Ok(나눔) => {        // HAZE adapter. Return actual plan metrics and scalar boundaries.        io.writeLine("optimized {나눔.optimized.lines.length} {나눔.optimized.totalCost}")        for 줄 in 나눔.optimized.lines {            io.writeLine("{줄.start} {줄.trimmedEndExclusive} {줄.trimmedTextWidth}")        }        io.writeLine("greedy {나눔.greedy.lines.length} {나눔.greedy.totalCost}")        for 줄 in 나눔.greedy.lines {            io.writeLine("{줄.start} {줄.trimmedEndExclusive} {줄.trimmedTextWidth}")        }    }    case Err(오류) => io.writeLine("{오류}")}
  1. 01소스4,017 B
  2. 02검사
  3. 03실행
위 결과는 이 소스로 계산했습니다. 문장이나 너비를 바꾸면 브라우저에서 다시 계산합니다.런타임 topaz_wasm 5.21.3 · 커밋 b01d0c3 · Apache-2.0
직접 만든 언어
2토파즈 · 리스펙스
운영 중인 제품
14아래 목록 전부
여기서 실행하는 판
5.21.3이 페이지에서 도는 런타임
부문 사이트
4파크 캔버스 사운드 스토리

01언어

언어 둘을 직접 설계하고 관리합니다.

범용 프로그래밍 언어

토파즈

토파즈는 조판을 내장한 범용 프로그래밍 언어입니다. 같은 일을 하는 코드는 누가 써도 같은 모양입니다.

paragraph.tpz

import std.ioimport std.typeset { BreakCluster, BreakPolicy, BreakMode, KinsokuRules, classifyBreaks }let chars = "좋은 문장은 (규칙을 지켜) 줄을 나눕니다.".scalars()let width = 100000 // 100 pt, a fixed 10 pt character gridlet clusters = chars.map(ch => BreakCluster {  text: ch, advance: 10000, trackingAfter: 0 })let policy = BreakPolicy {  mode: BreakMode.Word, rules: KinsokuRules.Unicode16Ko,  forbidBefore: [], forbidAfter: [],  boundaryAllowed: chars.map(ch => true), generatedHyphenEnds: [],  protectFittingLatin: false, preserveShortWords: false,  narrowestWordTarget: width, bodyWordTarget: width}match classifyBreaks(clusters, policy) {  case Ok(points) => {    let mut start = 0    while start < chars.length {      let ends = points.filter(p => p.unitEnd > start && (p.unitEnd - start) * 10000 <= width)      let end = ends[ends.length - 1].unitEnd      io.writeLine(chars.slice(start, end).join("").trim())      start = end    }  };  case Err(error) => io.writeLine("{error}")}

실행 결과

좋은 문장은
(규칙을 지켜)
줄을 나눕니다.
topaz.ooo

업무 규칙 언어

리스펙스

리스펙스는 출판사의 표기 원칙 같은 업무 규칙을 코드로 쓰는 언어입니다. 파일과 네트워크에 손댈 수 없어서 어떤 프로그램에 넣어도 안전합니다.

royalties.lspx

; Split a book's royalty without rounding away a share.(define price 19900)(define copies 127)(define royalty-rate 1/10)(define author-share 2/3)(define (royalties price copies)  (let* ((pool (* price copies royalty-rate))         (author (* pool author-share))         (translator (- pool author)))    (list author translator)))(define payment (royalties price copies))(define author (car payment))(define translator (cadr payment))(list 'author author      'translator translator      'total (+ author translator)      'balanced (= (+ author translator)                   (* price copies royalty-rate)))

실행 결과

(author 505460/3 translator 252730/3 total 252730 balanced #t)
lispex.com

02제품

운영 중인 제품 열네 가지.

03구조

제품보다 시스템을 먼저 세웁니다.

  1. L4웹·앱디지털 접점브라우저와 데스크톱에서 곧바로 실행되는 웹 서비스와 도구
  2. L3시스템워크플로·도구복잡한 작업을 정리하는 아키텍처와 사내 워크플로 도구
  3. L2언어언어 실험생각한 규칙을 소프트웨어로 바꾸는 프로그래밍 언어와 런타임
  4. L1인프라호스팅·배포·자동화배포 자동화와 안정적인 서버 운영을 맡는 백엔드 인프라

운영 원칙

  1. 1제품보다 시스템을 먼저 세웁니다.
  2. 2쓸모를 먼저 증명하고 그다음에 확장합니다.
  3. 3우리가 쓸 도구로 시작해 바깥으로 내보냅니다.

04연결

세 부문이 쓰는 도구를 만듭니다.

  1. HAZE STORY조판 도구 아틀라스로 책의 지면을 짭니다.hazestory.com
  2. HAZE SOUND믹싱과 마스터링을 자동으로 처리하는 체인을 만듭니다.hazesound.com
  3. HAZE CANVAS사진과 영상을 모아 두는 아카이브 앱을 만듭니다.hazecanvas.com

운영 인프라

브랜드 허브
스튜디오헤이즈와 각 부문 웹사이트를 하나로 잇는 공유 허브
내부 도구
반복 작업을 줄이고 업무 흐름을 일정하게 지키는 사내 자동화 도구
배포 기반
콘텐츠 발행과 트래픽 처리를 안정적으로 유지하는 전송 인프라

즐겁게 파고든 실험이 결국
가장 단단한 시스템이 됩니다.