EditContext API

W3C 작업 초안

이 문서에 대한 자세한 정보
이 버전:
https://www.w3.org/TR/2025/WD-edit-context-20251112/
최신 공개 버전:
https://www.w3.org/TR/edit-context/
최신 편집자 초안:
https://w3c.github.io/edit-context/
히스토리:
https://www.w3.org/standards/history/edit-context/
커밋 히스토리
편집자:
(Microsoft)
이전 편집자:
(Microsoft) -
(Microsoft) -
(Microsoft) -
피드백:
GitHub w3c/edit-context (풀 리퀘스트, 새 이슈, 오픈 이슈)
public-editing-tf@w3.org 제목에 [edit-context] … 메시지 주제 … 포함 (아카이브)
참여
우리는 GitHub에 있습니다.
버그를 신고하세요.
커밋 히스토리.
메일링 리스트.

개요

EditContext는 작성자가 텍스트 입력 과정에 더 직접적으로 참여할 수 있도록 하는 API입니다.

이 문서의 상태

이 섹션은 문서가 공개된 시점의 상태를 설명합니다. 현재 W3C 발행물 목록과 이 기술 보고서의 최신 개정판은 W3C 표준 및 초안 색인에서 확인할 수 있습니다.

이 문서는 Web Editing Working Group에서 권고안 절차를 통해 작업 초안으로 발행된 것입니다.

작업 초안으로 발행된 것이 W3C 및 회원의 승인됨을 의미하지는 않습니다.

이 문서는 초안이며 언제든지 업데이트, 교체 또는 폐기될 수 있습니다. 진행 중인 작업 외의 용도로 인용하는 것은 부적절합니다.

이 문서는 W3C 특허 정책 하에 운영되는 그룹에서 작성되었습니다. W3C그룹 산출물에 관한 특허 공개 목록 을 공개하며, 해당 페이지에는 특허 공개 방법도 안내되어 있습니다. 실제로 본인이 본질적 권리(Essential Claim(s))를 포함한다고 생각하는 특허를 알고 있다면 W3C 특허 정책 6장에 따라 정보를 공개해야 합니다.

이 문서는 2025년 8월 18일 W3C 프로세스 문서에 따라 관리됩니다.

1. 소개

1.1 배경 및 동기

이 절은 비규범적입니다.

현대 운영체제는 음성-텍스트 변환, 가상 키보드, 필기 인식 등 다양한 방식으로 텍스트를 생성하는 메커니즘을 제공합니다. 앱이 이러한 다양한 소스에서의 텍스트 입력을 소비하려면, 먼저 현재 편집 가능한 텍스트에 대한 뷰를 운영체제에 제공해야 합니다. 편집 가능한 텍스트의 뷰는 앱(서로 다른 다양한 문서 모델을 가짐)과 텍스트 소스(서로 다른 다양한 입력 방법을 가짐) 모두가 이해할 수 있는 공통 언어를 제공합니다. 앱과 입력 소스는 모두, 텍스트 입력 과정을 용이하게 하기 위해 상대가 처리할 수 있는 이벤트로서 공통 뷰의 상태에 대한 원하는 변경을 표현함으로써 서로 통신합니다.

이 문서의 목적상, 텍스트의 생산자는 텍스트 입력 방법으로 알려져 있습니다. 텍스트를 소비하려는 앱이 제공하는 뷰는 텍스트 편집 컨텍스트라고 합니다. 운영체제가 제공하는 서비스로서, 텍스트 편집 컨텍스트 내의 텍스트 편집을 텍스트 입력 방법들이 수행할 수 있도록 돕는 것을 텍스트 입력 서비스라고 합니다.

그림 1 많은 텍스트 입력 방법텍스트 입력 서비스를 사용하여 많은 앱과 그들의 텍스트 편집 컨텍스트를 통해 통신하는 모습.

다음은 텍스트 입력 과정의 전형적인 흐름을 더 자세히 설명한 것입니다:

  1. 사용자가 앱의 편집 가능한 영역에 포커스를 둡니다.
  2. 앱은 텍스트 입력 서비스에서 정한 표준에 따라 자신의 편집 가능한 영역을 설명하는 텍스트 편집 컨텍스트를 생성하고, 해당 텍스트 편집 컨텍스트텍스트 입력 서비스에 제공합니다.
  3. 텍스트 입력 서비스는 사용자로부터 텍스트 입력을 캡처하기 위한 사용자 인터페이스를 제공하도록 텍스트 입력 방법을 트리거하고, 앱이 생성한 텍스트 편집 컨텍스트를 해당 텍스트 입력 방법에 제공합니다.
  4. 텍스트 입력 방법은 사용자 경험을 맞춤화하는 데 도움을 받기 위해 텍스트 편집 컨텍스트에서 선택 위치 및 주변 텍스트를 읽습니다.
  5. 텍스트 입력 방법은 또한 선택 영역과 편집 가능한 영역이 위치한 화면 좌표를 읽어, 편집 중인 텍스트 옆에 사용자 인터페이스를 적절히 배치할 수 있습니다.
  6. 사용자는 텍스트 입력 방법 사용자 인터페이스와 상호작용하여 어떤 텍스트 입력 방법 고유의 방식으로 텍스트를 입력합니다.
  7. 텍스트 입력 방법은 사용자의 입력에 대한 응답으로, 텍스트 편집 컨텍스트에서 텍스트 및 선택 영역에 대한 원하는 수정 사항을 설명합니다.
  8. 앱은 자신의 텍스트 편집 컨텍스트에 대한 원하는 수정 사항을 설명하는 이벤트를 처리하고, 그 결과를 사용자에게 렌더링합니다.
그림 2 텍스트 입력의 전형적인 흐름을 보여주는 시퀀스 다이어그램.

기존 사용자 에이전트는 이 텍스트 입력 과정의 세부 사항을 처리하므로, 저자의 책임은 문서의 어떤 요소가 편집 가능한 영역을 나타내는지 선언하는 것으로 끝납니다. 저자는 input 요소, textarea 요소, contenteditable 요소를 사용하거나, designMode 속성을 "on"으로 설정하여 문서 전체를 편집 가능으로 표시함으로써 편집 가능한 영역을 표현합니다.

문서의 편집 가능한 영역이 포커스되면, 사용자 에이전트는 해당 편집 가능한 영역의 내용과 그 안에서의 선택 위치로부터 텍스트 편집 컨텍스트를 자동으로 생성합니다. 텍스트 입력 방법이 텍스트를 생성하면, 사용자 에이전트는 자신의 텍스트 편집 컨텍스트에 대해 발생한 이벤트들을 DOM 및 스타일 수정의 집합으로 변환합니다. 이 중 저자가 처리할 수 있는 기존 이벤트로 설명되는 것은 일부에 불과합니다.

정교한 편집 경험을 만들고자 하는 저자는 현재의 접근 방식으로 인해 어려움을 겪을 수 있습니다. 예를 들어, 텍스트와 선택 영역이 canvas에 렌더링되는 경우 사용자 에이전트는 텍스트 입력 과정을 구동할 텍스트 편집 컨텍스트를 생성할 수 없습니다. 저자는 화면 밖의 편집 가능한 요소를 사용하는 방식으로 이를 보완하지만, 이 접근 방식은 접근성에 부정적인 영향을 주고 입력 경험을 저하시킬 뿐 아니라, 화면 밖의 편집 가능한 요소의 텍스트 위치를 canvas 내의 해당 텍스트와 동기화하기 위한 복잡한 코드를 필요로 합니다.

이 EditContext API의 도입으로, 저자는 텍스트 입력을 위한 프로토콜에 더 직접적으로 참여할 수 있으며 위에서 설명한 함정을 피할 수 있습니다.

1.2 EditContext 모델

텍스트 입력 서비스텍스트 편집 컨텍스트는 여러 운영체제 전반에서 텍스트 입력의 공통적인 측면을 나타내는 추상화입니다. EditContext텍스트 편집 컨텍스트의 JavaScript 반영입니다. 텍스트 입력 서비스에 의해 텍스트 편집 컨텍스트에 변경이 발생하면, 그 변경은 활성 EditContext에 대해 디스패치되는 이벤트의 형태로 저자에게 비동기적으로 반영됩니다. 저자가 활성 EditContext에 변경을 가하면, 그 변경은 다음 라이프사이클 업데이트 동안 텍스트 편집 컨텍스트에 반영됩니다.

1.2.1 EditContext 상태

텍스트 편집 컨텍스트EditContext는 모두 앞서 언급한 업데이트에서 교환되는 정보를 담고 있는 텍스트 상태를 갖습니다. 텍스트 상태는 다음으로 구성됩니다:

  • 텍스트는 편집 가능한 콘텐츠를 나타내는 DOMString입니다. 초기 값은 빈 문자열입니다.
  • 선택 시작텍스트에서 선택이 시작되는 오프셋을 가리킵니다. 초기 값은 0입니다.
  • 선택 끝텍스트에서 선택이 끝나는 오프셋을 가리킵니다. 초기 값은 0입니다. 선택 끝은 "역방향" 선택(문서 순서의 반대)의 경우 선택 시작보다 작을 수 있습니다.
  • 조합 중은 활성 조합이 있는지 여부를 나타냅니다. 초기 값은 false입니다.
  • 조합 시작텍스트에서 현재 조합 중인 텍스트의 시작 위치를 나타내는 오프셋을 가리킵니다. 초기 값은 0입니다.
  • 조합 끝텍스트에서 현재 조합 중인 텍스트의 끝 위치를 나타내는 오프셋을 가리킵니다. 초기 값은 0입니다. 조합 끝은 항상 조합 시작보다 크거나 같아야 합니다.
  • 텍스트 형식텍스트 형식의 배열입니다. 배열은 초기에는 비어 있습니다.
  • 컨트롤 경계DOMRect로, 텍스트가 표시되는 뷰포트 영역을 설명합니다. 이는 클라이언트 좌표계에 있으며, 초기 x, y, width, height는 모두 0입니다.
  • 선택 경계DOMRect로, 선택의 위치를 설명합니다. 이는 클라이언트 좌표계에 있으며, 초기 x, y, width, height는 모두 0입니다.
  • 코드포인트 사각형 시작 인덱스텍스트로의 오프셋이며, 코드포인트 사각형 배열의 첫 번째 멤버가 위치를 보고하는 첫 번째 코드포인트 이전의 위치를 나타냅니다.
  • 코드포인트 사각형은 각 코드포인트의 경계 상자를 정의하는 DOMRect의 배열입니다. 배열은 초기에는 비어 있습니다.

텍스트 형식텍스트 범위에 적용되어야 하는 장식 속성을 나타내는 구조체입니다. 구조체는 다음을 포함합니다:

  • 범위 시작텍스트로의 오프셋이며, 장식되어야 하는 첫 번째 코드포인트 이전의 위치를 나타냅니다.
  • 범위 끝텍스트로의 오프셋이며, 장식되어야 하는 마지막 코드포인트 이후의 위치를 나타냅니다.
  • 밑줄 스타일은 장식된 텍스트 범위의 선호 밑줄 스타일인 UnderlineStyle입니다.
  • 밑줄 두께는 장식된 텍스트 범위의 선호 밑줄 두께인 UnderlineThickness입니다.
참고

코드포인트 사각형은 사용자 에이전트가 위치 정보를 위해 텍스트 범위를 질의할 수 있는 수단을 제공합니다. 텍스트 입력 서비스는 이 정보를 컨트롤 경계선택 경계와 함께 사용하여, 텍스트 입력 방법이 사용자 인터페이스를 올바르게 표시할 수 있도록 지원합니다. 예를 들어, 이 정보는 조합 중인 텍스트 옆에 IME 창을 배치하는 데 사용될 수 있습니다. 서로 다른 플랫폼은 텍스트 입력 서비스의 질의를 충족하기 위해 서로 다른 위치를 캐시해야 할 수 있습니다. 사용자 에이전트는 CharacterBoundsUpdateEvent를 발화하여 어떤 위치가 필요한지 나타냅니다.

컨트롤 경계, 선택 경계, 그리고 코드포인트 사각형클라이언트 좌표계로 제공됩니다. 이는 2차원 직교 좌표계(x, y)로 정의되며, 원점은 레이아웃 뷰포트의 좌상단 모서리이고, x축은 레이아웃 뷰포트의 우상단 방향을 가리키며, y축은 레이아웃 뷰포트의 좌하단 방향을 가리킵니다. 클라이언트 좌표계의 단위는 CSS 픽셀입니다.

참고

EditContext 경계는 클라이언트 좌표로 정의되므로, 페이지의 특정 콘텐츠를 나타내는 좌표는 콘텐츠 자체가 문서에서의 위치를 바꾸지 않더라도 사용자가 문서를 스크롤함에 따라 변하게 됩니다. 저자가 이를 고려하고자 할 수 있는 시나리오는 사용자가 활성 조합을 가진 상태에서 페이지를 스크롤하는 경우입니다. 저자가 EditContext의 경계 정보(예: 스크롤 이벤트 리스너 중)를 업데이트하지 않으면, 조합이 진행되는 동안 IME 창이 더 이상 조합 중인 텍스트와 맞지 않을 수 있습니다.

하지만 일부 플랫폼은 활성 조합 중에는 IME 창을 조정하지 않으므로, 조합 중간에 경계 정보를 업데이트하더라도 IME 창이 닫혔다가 다시 열릴 때까지 재배치된다는 것을 보장하지는 않습니다.

1.2.2 연결 및 활성화

EditContext연결된 요소HTMLElement를 가집니다. 요소는 해당 요소의 editContext 속성에 EditContext를 할당함으로써 EditContext연결된 요소가 됩니다. HTMLElement는 최대 하나의 EditContext와만 연결될 수 있습니다.

참고

EditContext는 자신의 연결된 요소를 살아 있게 유지하므로, 개발자는 요소의 editContext 속성에 EditContext를 할당하면 해당 속성이 지워지거나 EditContext가 가비지 컬렉션될 때까지 요소가 가비지 컬렉션되지 않게 된다는 점을 알아야 합니다.

EditContext연결된 요소부모편집 가능하지 않고, 또한 Document이면서 designMode 속성이 "on"인 것도 아니라면, 연결된 요소EditContext 편집 호스트가 됩니다. EditContext 편집 호스트편집 호스트의 한 유형이며, 그 동작은 1.2.3 EditContext 편집 호스트에 대한 차이점에 설명되어 있습니다.

참고

여기에는 몇 가지 함의가 있습니다. 첫째, 이미 contenteditable로 인해 편집 호스트인 요소가 EditContext연결된 요소가 되면, 그 요소는 EditContext 편집 호스트가 됩니다. 즉, 요소에 EditContextcontenteditable이 둘 다 설정되어 있다면, EditContext 동작이 "우선"합니다.

둘째, 요소가 편집 가능하지만 편집 호스트는 아닌 경우(즉, 편집 호스트의 하위 트리에 있는 자식인 경우), EditContext연결된 요소가 되는 것은 그 요소에 아무런 영향을 미치지 않습니다. 이는 contenteditable의 동작과 유사합니다. 즉, 편집 가능하지만 편집 호스트가 아닌 요소에 contenteditable을 "true"로 설정해도 효과가 없습니다. 이러한 규칙들을 종합하면, 편집 가능한 노드 트리는 EditContext 동작 또는 비-EditContext 동작 중 하나를 따르게 되며, 동작들을 혼합할 수는 없음을 시사합니다.

Document활성 EditContext를 가지며, 이는 null일 수 있습니다.

이슈 1

다음 단락은 동작 변경이 [input-events]에 반영되면 제거할 수 있습니다.

EditContext 편집 호스트텍스트 입력 서비스로부터 텍스트 입력을 받으면, 그 입력의 결과로 발화된 beforeinput 이벤트에 대한 기본 동작으로서 사용자 에이전트는 주어진 EditContext 편집 호스트에 대해 EditContext에 대한 입력 처리를 실행해야 합니다.

1.2.3 EditContext 편집 호스트에 대한 차이점

여러 면에서 EditContext 편집 호스트는 다른 유형의 편집 호스트와 동일한 방식으로 동작합니다. 예: contenteditable 요소. 주목할 만한 유사점은 다음과 같습니다:

또한 EditContext 편집 호스트가 다른 유형의 편집 호스트와 다른 점도 있습니다:

  • 편집 중인 Document활성 EditContext가 있을 때, 사용자 에이전트는 EditContext 편집 호스트에서의 사용자 동작(예: 편집 가능한 영역에서의 키보드 입력, 텍스트 삭제 또는 서식 지정 등 ...)의 직접적인 결과로 DOM을 업데이트해서는 안 됩니다.
  • 편집 중인 Document활성 EditContext가 있을 때, 사용자 에이전트는 [uievents]에 명시된 대로 사용자 동작의 직접적인 결과로서 input 이벤트를 EditContext 편집 호스트에 대해 발화해서는 안 됩니다.
  • 편집 중인 Document활성 EditContext가 있을 때, 사용자 에이전트는 사용자 동작의 직접적인 결과로서 조합 이벤트EditContext 편집 호스트에 대해 발화해서는 안 됩니다. 대신, 이들은 EditContext를 업데이트하거나 EditContext를 비활성화하는 과정의 일부로 EditContext에 대해 발화됩니다.
  • 활성 EditContext연결된 요소canvas인 경우, 추가적인 차이점이 있습니다:

    • 사용자 에이전트는 canvas에서 텍스트가 어떻게 배치되는지에 대한 정보가 없으므로 캐럿 내비게이션과 선택을 처리할 수 없고, 저자가 캐럿 내비게이션과 선택을 구현해야 합니다.
    • 사용자 에이전트는 canvas에서 텍스트가 어떻게 배치되는지에 대한 정보가 없으므로 인라인 맞춤법 및 문법 제안을 제공할 수 없고, 저자가 맞춤법 및 문법 제안을 지원하고자 한다면 이를 직접 구현해야 합니다.

1.2.4 EditContext 이벤트

사용자 에이전트는 EditContext에 대해 여러 유형의 이벤트를 발화하여, 저자가 텍스트 입력 서비스로부터의 변경에 대응하여 DOM 상태를 언제 업데이트해야 하는지, 또는 텍스트 입력 서비스의 질의에 언제 응답해야 하는지 알려줍니다. 텍스트 입력 서비스의 타이밍은 플랫폼별로 다르므로, 저자는 이러한 이벤트의 타이밍에 의존하는 것을 피해야 합니다.

  • 사용자 에이전트는 텍스트 입력 서비스가 사용자가 EditContext의 텍스트, 선택, 또는 조합 범위 속성에 변경을 가했음을 나타낼 때 TextUpdateEvent를 발화해야 합니다. 저자가 이 이벤트를 받으면, 사용자가 타이핑하는 내용을 볼 수 있도록 변경 사항을 페이지의 뷰에 다시 렌더링해야 합니다.
  • 사용자 에이전트는 텍스트 입력 서비스가 조합 중인 텍스트에 특정 형식을 적용해야 함을 나타낼 때 TextFormatUpdateEvent를 발화해야 합니다. 저자가 이 이벤트를 받으면, 사용자의 IME 조합을 돕기 위해 서식 변경을 페이지의 뷰에 다시 렌더링해야 합니다.

    참고

    사용자 에이전트는 지문 채취 위험을 완화하기 위해 UnderlineStyle 또는 UnderlineThicknessTextFormatUpdateEvent를 디스패치하기 전에 조정할 수 있습니다. 이는 특히 독특한 스타일 특성을 가진 입력 방법이 사용되는 경우에 관련성이 클 수 있습니다.

  • 사용자 에이전트는 텍스트 입력 서비스텍스트 입력 방법이 사용자 인터페이스를 올바르게 표시할 수 있도록 문자 경계 정보가 필요함을 나타낼 때 CharacterBoundsUpdateEvent를 발화해야 합니다. 저자는 CharacterBoundsUpdateEvent를 받은 후 요청된 문자 경계를 계산하고, updateCharacterBounds를 호출하여 EditContext의 텍스트 상태에서 문자 경계를 업데이트해야 합니다. 가능하다면 저자는 updateCharacterBounds 호출을 CharacterBoundsUpdateEvent 이벤트 핸들러 내에서 동기적으로 수행해야 합니다. 그렇지 못한 경우 비동기적으로 호출하는 것도 허용됩니다. 사용자 에이전트는 updateCharacterBounds를 받으면 문자 경계 정보를 텍스트 입력 서비스로 전달해야 합니다.

    참고

    저자가 updateCharacterBounds 호출을 지연할수록, 사용자가 조합 도중 IME 창이 재배치되면서 시각적인 끊김을 관찰할 가능성이 더 커집니다.

1.2.5 이벤트 루프 변경

HTML 이벤트 루프 처리 모델의 렌더링 업데이트 단계 내에 하위 단계로 새로운 단계가 도입되며, 단계 15(포커스될 수 없게 되는 Document에 대한 포커싱 단계를 실행함) 바로 다음에 위치합니다. 단계는 다음과 같습니다: 각 완전히 활성 Document doc에 대해, doc관련 전역 객체가 주어진 상태에서 전역 작업을 큐에 넣어 DOM 조작 작업 소스에 등록하고, doc에 대해 텍스트 편집 컨텍스트 업데이트 단계를 실행합니다.

1.2.6 예제

이 절은 비규범적입니다.

EditContext를 사용하면, 저자는 아래 예제에 보이듯 요소에 연결EditContext 객체로 문서의 한 영역을 편집 가능으로 표시할 수 있습니다:

아래 예제에서 저자는 canvas를 사용하여 고정폭 글꼴로 렌더링되는 한 줄의 텍스트 입력을 사용자가 할 수 있도록 하는 편집 가능한 영역을 그립니다. 편집 가능한 영역의 텍스트는 저자가 String으로 유지합니다. 편집 가능한 영역의 선택에 대한 텍스트 오프셋은 저자가 selectionStart와 selectionEnd라는 두 개의 Number로 유지합니다. 이 Number들은 각각 선택 시작과 끝의 왼쪽에 있는 UTF-16 코드포인트 개수를 가리킵니다. 현재 선택과 문서의 편집 가능한 영역에 대한 경계 상자를 텍스트 입력 서비스에 전달하기 위해, 저자는 선택과 문서의 편집 가능한 영역에 대한 경계 사각형을 CSS 픽셀 단위로도 계산합니다. 사각형의 오프셋은 canvas 요소의 원점을 기준으로 표현되는데, 이는 저자가 EditContext를 연결한 요소가 바로 그 요소이기 때문입니다. 저자의 텍스트 및 선택 위치 표현 모델이 EditContext API가 기대하는 형태와 일치하므로, 저자는 값이 변경될 때마다 canvas에 연결된 EditContext에 해당 속성들을 간단히 할당할 수 있습니다.

이전 예제를 바탕으로, 사용자 입력에 대응하여 저자는 편집 가능한 요소(이 경우 canvas)와 EditContext의 이벤트를 모두 처리해야 합니다.

DOM에 대한 입력 이벤트는 계속해서 사용자의 의도를 설명합니다.

아래 예제는 TextUpdateEvent, TextFormatUpdateEvent, 그리고 CharacterBoundsUpdateEvent를 처리하여 모델을 업데이트하고 결과를 canvas에 렌더링하는 방법을 보여줍니다.

1.3 다른 편집 프리미티브와의 상호작용

이 절은 비규범적입니다.

저자는 EditContext와 함께 canvas 요소를 사용할 필요가 없습니다. 아래 예제에서 저자는 div를 사용하여 문서의 편집 가능한 영역을 설정하고, 다양한 스타일이 적용된 요소, 이미지 및 텍스트를 사용하여 그 편집 가능한 영역에 내용을 렌더링합니다. 이를 통해 저자는 선택 및 맞춤법 검사와 같은 사용자 에이전트의 다른 내장 편집 프리미티브를 활용할 수 있습니다.

2. 적합성

비규범적으로 표시된 절뿐만 아니라, 이 명세의 모든 저작 지침, 다이어그램, 예제, 참고는 비규범적입니다. 이 명세의 그 밖의 모든 내용은 규범적입니다.

이 명세는 단일 제품, 즉 이 안에 포함된 인터페이스들을 구현하는 사용자 에이전트에 적용되는 적합성 기준을 정의합니다.

알고리즘 또는 특정 단계로 표현된 적합성 요구 사항은 최종 결과가 동등하기만 하면 어떤 방식으로든 구현될 수 있습니다. (특히, 이 명세에 정의된 알고리즘은 따라가기 쉽도록 의도된 것이며, 성능이 좋도록 의도된 것은 아닙니다.)

3. EditContext API

3.1 HTMLElement 인터페이스에 대한 확장

WebIDLpartial interface HTMLElement {
     attribute EditContext? editContext;
};

HTMLElement는 내부 슬롯 [[EditContext]]를 가지며, 이는 EditContext에 대한 참조이고 초기값은 null입니다.

editContext
editContext 게터 단계는 this의 내부 [[EditContext]] 슬롯의 값을 반환하는 것입니다.
editContext 세터는 다음 단계를 따라야 합니다:
입력
editContext
출력
없음
  1. this로컬 이름유효한 섀도우 호스트 이름도 아니고 "canvas"도 아니라면, "NotSupportedError" DOMException던집니다.
  2. editContext가 null이 아니라면:
    1. editContext연결된 요소this와 같다면, 이 단계를 종료합니다.
    2. editContext연결된 요소가 null이 아니라면, "NotSupportedError" DOMException던집니다.
  3. oldEditContextthis의 내부 [[EditContext]] 슬롯의 값으로 둡니다.
  4. oldEditContext가 null이 아니고 oldEditContextthis노드 문서활성 EditContext라면:
    1. oldEditContextEditContext를 비활성화하는 단계를 실행합니다.
    2. oldEditContext연결된 요소this와 같지 않다면, 이 단계를 종료합니다.
    3. editContext가 null이 아니고, editContext연결된 요소가 null이 아니며, editContext연결된 요소this와 같지 않다면, "NotSupportedError" DOMException던집니다.
  5. oldEditContext가 null이 아니라면, oldEditContext연결된 요소를 null로 설정합니다.
  6. editContext가 null이 아니라면, editContext연결된 요소this로 설정합니다.
  7. this의 내부 [[EditContext]] 슬롯을 editContext로 설정합니다.

3.1.1 EditContext에 대한 입력 처리

입력
element, 입력을 받는 HTMLElement
출력
없음
  1. editContextelement노드 문서활성 EditContext로 둡니다.
  2. editContext가 null이면 반환합니다.
  3. editContext텍스트 편집 컨텍스트텍스트 상태텍스트, 텍스트 형식, 선택 시작, 선택 끝, 조합 중, 조합 시작, 그리고 조합 끝이 주어진 상태로 EditContext 업데이트 단계를 실행합니다.

    Note

    텍스트 편집 컨텍스트는 서로 다른 운영체제 간 텍스트 입력의 공통 측면에 대한 추상화이므로, 텍스트 편집 컨텍스트 내 값들의 결정 방법은 이 명세에서 명시적으로 제공되지 않습니다. 이는 서로 다른 운영체제 및 입력 장치에 따라 달라집니다.

3.1.2 EditContext가 처리하는 inputType

inputType이 다음 중 하나이면 EditContext가 처리하는 inputType입니다:
  • insertText
  • insertTranspose
  • deleteWordBackward
  • deleteWordForward
  • deleteContent
  • deleteContentBackward
  • deleteContentForward
Note
EditContext가 처리하는 inputType은 원시 텍스트에만 작동하는 것들입니다. 형식, 클립보드/드래그드롭, 실행 취소, 또는 맞춤법 검사 같은 브라우저 UI에 의존하는 다른 inputTypeEditContext의 상태가 이러한 개념들을 포함하지 않기 때문에 EditContext가 처리할 수 없습니다. 저자가 자신의 애플리케이션이 그러한 inputType들을 처리하길 원한다면, beforeinput 이벤트 핸들러에서 수동으로 처리해야 합니다.

3.1.3 EditContext 업데이트

입력
editContext, EditContext
text, 문자열
textFormats, 텍스트 형식들의 배열( 텍스트 입력 서비스에서 온 것)
selectionStart, 선택 시작의 새 위치
selectionEnd, 선택 끝의 새 위치
isComposing, 업데이트 끝에서 조합이 활성 상태여야 하는지 여부를 나타내는 불리언
replacementRangeStart, 현재 조합의 시작 위치(조합이 없으면 0)
replacementRangeEnd, 현재 조합의 끝 위치(조합이 없으면 0)
출력
없음
  1. isComposing이 true이고, text가 비어 있지 않으며, editContext조합 중이 false이면:
    1. 이벤트를 발화합니다. 이름은 compositionstart이며, editContext에서 CompositionEvent를 사용합니다.
    2. editContext조합 중을 true로 설정합니다.
  2. text가 비어 있다면:
    1. editContext조합 중이 false이면, 반환합니다.
    2. editContext조합 중이 true이고 isComposing이 false이면:
      1. editContext조합 중을 false로 설정합니다.
      2. 이벤트를 발화합니다. 이름은 compositionend이며, editContext에서 CompositionEvent를 사용합니다.
      3. 반환합니다.
  3. editContext조합 중이 true이면:
    1. insertionStartreplacementRangeStart로 둡니다.
    2. insertionEndreplacementRangeEnd로 둡니다.
  4. 그렇지 않으면:
    1. insertionStartselectionStart로 둡니다.
    2. insertionEndselectionEnd로 둡니다.
  5. editContext텍스트에서 insertionStart부터 insertionEnd 범위의 부분 문자열을 text로 교체합니다.
  6. editContext선택 시작selectionStart로 설정합니다.
  7. editContext선택 끝selectionEnd로 설정합니다.
  8. editContext조합 시작insertionStart로 설정합니다.
  9. editContext조합 끝editContext조합 시작text의 길이를 더한 값으로 설정합니다.
  10. editContexttext가 주어진 상태로 텍스트 업데이트 이벤트 디스패치를 수행합니다.
  11. editContext조합 중이 true이면:
    1. editContexttextFormats가 주어진 상태로 텍스트 형식 업데이트 이벤트 디스패치를 수행합니다.
    2. editContext가 주어진 상태로 문자 경계 업데이트 이벤트 디스패치를 수행합니다.
    3. isComposing이 false이면:
      1. editContext조합 중을 false로 설정합니다.
      2. 이벤트를 발화합니다. 이름은 compositionend이며, editContext에서 CompositionEvent를 사용합니다.

3.1.4 텍스트 편집 컨텍스트 업데이트

입력
document, Document
출력
없음
  1. oldActiveEditContextdocument활성 EditContext로 둡니다.
  2. newActiveEditContextdocument가 주어진 상태로 활성 EditContext를 결정하는 단계를 실행한 결과로 둡니다.
  3. oldActiveEditContext가 null이 아니라면, oldActiveEditContext가 주어진 상태로 EditContext를 비활성화하는 단계를 실행합니다.
  4. newActiveEditContext가 null이 아니라면:
    1. 텍스트 편집 컨텍스트텍스트 상태editContext텍스트 상태에 있는 값들과 일치하도록 업데이트합니다.
  5. document활성 EditContextnewActiveEditContext로 설정합니다.
Note

텍스트 편집 컨텍스트텍스트 상태를 업데이트하는 단계는 플랫폼별 텍스트 입력 서비스 위에 만들어진 추상화의 성격에 따라 달라진다는 점에 유의하십시오. 그 세부 사항은 이 명세의 일부가 아닙니다.

3.1.5 텍스트 업데이트 이벤트 디스패치

입력
editContext, EditContext
text, 문자열
출력
없음
  1. 이벤트를 발화합니다. 이름은 "textupdate"이며 editContext에서 TextUpdateEvent를 사용합니다. 이때 texttext로 초기화되고, selectionStart는 |editContext선택 시작으로 초기화되며, selectionEndeditContext선택 끝으로 초기화됩니다.

3.1.6 텍스트 형식 업데이트 이벤트 디스패치

입력
editContext, EditContext
textFormats, 텍스트 형식들의 배열( 텍스트 입력 서비스에서 온 것)
출력
없음
  1. formatsTextFormat의 배열로 두며, 초기에는 비어 있습니다.
  2. textFormats의 각 텍스트 형식 format에 대해:
    1. textFormat을 새로운 TextFormat으로 둡니다. ( rangeStart, rangeEnd, underlineStyle, underlineThickness 포함)
    2. textFormatrangeStartformat범위 시작으로 설정합니다.
    3. textFormatrangeEndformat범위 끝으로 설정합니다.
    4. textFormatunderlineStyleformat밑줄 스타일로 설정합니다.
    5. textFormatunderlineThicknessformat밑줄 두께로 설정합니다.
    6. textFormatformats에 추가합니다.
  3. 이벤트를 발화합니다. 이름은 "textformatupdate"이며 editContext에서 TextFormatUpdateEvent를 사용하고, TextFormatUpdateEvent텍스트 형식 목록formats로 초기화됩니다.

3.1.7 문자 경계 업데이트 이벤트 디스패치

입력
editContext, EditContext
출력
없음
  1. 이벤트를 발화합니다. 이름은 "characterboundsupdate"이며 editContext에서 CharacterBoundsUpdateEvent를 사용합니다. 이때 rangeStarteditContext조합 시작으로 초기화되고, rangeEndeditContext조합 끝으로 초기화됩니다.

3.1.8 EditContext 비활성화

입력
editContext, EditContext
출력
없음
  1. editContext조합 중을 false로 설정합니다.
  2. 이벤트를 발화합니다. 이름은 compositionend이며, editContext에서 CompositionEvent를 사용합니다.

3.1.9 활성 EditContext 결정

입력
document, Document
출력
EditContext, 또는 null.
  1. traversabledocument노드 내비게이블최상위 트래버서블로 둡니다.
  2. traversable이 null이면 null을 반환합니다.
  3. focusedtraversable이 주어진 상태에서 최상위 트래버서블의 현재 포커스된 영역DOM 앵커로 둡니다.
  4. focused가 null이거나 focused섀도우-포함 루트document가 아니라면 null을 반환합니다.

    Note

    최상위 트래버서블을 통해 focusable을 얻는 목적은, 최상위 트래버서블마다 한 번에 하나의 활성 EditContext만 존재하도록 하기 위함입니다. 따라서 시스템 포커스가 다른 문서에 있다면, 이 문서는 활성 EditContext를 가질 수 없습니다.

  5. editContext를 null로 둡니다.
  6. focused가 null이 아니고 focused편집 가능한 동안:
    1. editContextfocused의 내부 [[EditContext]] 슬롯 값으로 설정합니다.
    2. parentfocused부모로 둡니다.
    3. parent가 null이고 focused루트섀도우 루트라면, parentfocused루트호스트로 둡니다.
    4. focusedparent로 설정합니다.
  7. editContext를 반환합니다.
Note

EditContext연결된 요소의 부모가 편집 가능하다면, 해당 EditContext활성 EditContext가 될 수 없습니다. 이는 그 부모가 다른 EditContext로 인해 편집 가능해졌든, contenteditable로 인해 편집 가능해졌든 상관없이 해당됩니다.

3.2 EditContext 인터페이스

WebIDLdictionary EditContextInit {
    DOMString text;
    unsigned long selectionStart;
    unsigned long selectionEnd;
};

[Exposed=Window]
interface EditContext : EventTarget {
    constructor(optional EditContextInit options = {});

    undefined updateText(unsigned long rangeStart, unsigned long rangeEnd,
        DOMString text);
    undefined updateSelection(unsigned long start, unsigned long end);
    undefined updateControlBounds(DOMRect controlBounds);
    undefined updateSelectionBounds(DOMRect selectionBounds);
    undefined updateCharacterBounds(unsigned long rangeStart, sequence<DOMRect> characterBounds);

    sequence<HTMLElement> attachedElements();

    readonly attribute DOMString text;
    readonly attribute unsigned long selectionStart;
    readonly attribute unsigned long selectionEnd;
    readonly attribute unsigned long characterBoundsRangeStart;
    sequence<DOMRect> characterBounds();

    attribute EventHandler ontextupdate;
    attribute EventHandler ontextformatupdate;
    attribute EventHandler oncharacterboundsupdate;
    attribute EventHandler oncompositionstart;
    attribute EventHandler oncompositionend;
};
text
text 게터 단계는 this텍스트를 반환하는 것입니다.
selectionStart
selectionStart 게터 단계는 this선택 시작을 반환하는 것입니다.
selectionEnd
selectionEnd 게터 단계는 this선택 끝을 반환하는 것입니다.
characterBounds
characterBounds 게터 단계는 this코드포인트 사각형을 반환하는 것입니다.
characterBoundsRangeStart
characterBoundsRangeStart 게터 단계는 this코드포인트 사각형 시작 인덱스를 반환하는 것입니다.
updateText() method

이 메서드는 다음 단계를 따라야 합니다:

입력
rangeStart, unsigned long
rangeEnd, unsigned long
newText, DOMString
출력
없음
  1. 텍스트에서 rangeStart부터 rangeEnd 범위의 부분 문자열을 newText로 교체합니다.
    Note
    rangeStart > rangeEnd인 것도 허용됩니다. 인덱스 사이의 부분 문자열은 rangeStart <= rangeEnd일 때와 동일한 방식으로 교체되어야 합니다.
updateSelection() method

이 메서드는 다음 단계를 따라야 합니다:

입력
start, unsigned long
end, unsigned long
출력
없음
  1. 선택 시작start로 설정합니다.
  2. 선택 끝end로 설정합니다.
updateSelectionBounds() method

이 메서드는 다음 단계를 따라야 합니다:

입력
selectionBounds, DOMRect
출력
없음
  1. 선택 경계selectionBounds로 설정합니다.
updateControlBounds() method

이 메서드는 다음 단계를 따라야 합니다:

입력
controlBounds, DOMRect
출력
없음
  1. 컨트롤 경계controlBounds로 설정합니다.
updateCharacterBounds() method

이 메서드는 다음 단계를 따라야 합니다:

입력
rangeStart, unsigned long
characterBounds, DOMRect의 배열
출력
없음
  1. 코드포인트 사각형 시작 인덱스rangeStart로 설정합니다.
  2. 코드포인트 사각형characterBounds로 설정합니다.
attachedElements() method

이 메서드는 EditContext연결된 요소인 항목 하나를 가진 목록을 반환하거나, EditContext연결된 요소가 null이면 빈 목록을 반환합니다.

Note

이 메서드는 EditContext가 언젠가 여러 연결된 요소를 가질 수 있는 능력을 부여받을 경우를 대비한 전방 호환성을 위해, 단일 요소 대신 목록을 반환합니다.

ontextupdate

TextUpdateEvent에 대한 이벤트 핸들러입니다.

oncharacterboundsupdate

CharacterBoundsUpdateEvent에 대한 이벤트 핸들러입니다.

ontextformatupdate

TextFormatUpdateEvent에 대한 이벤트 핸들러입니다.

oncompositionstart

compositionstart 이벤트에 대한 이벤트 핸들러입니다.

oncompositionend

compositionend 이벤트에 대한 이벤트 핸들러입니다.

4. EditContext 이벤트

4.1 TextUpdateEvent

WebIDLdictionary TextUpdateEventInit : EventInit {
    unsigned long updateRangeStart;
    unsigned long updateRangeEnd;
    DOMString text;
    unsigned long selectionStart;
    unsigned long selectionEnd;
    unsigned long compositionStart;
    unsigned long compositionEnd;
};

[Exposed=Window]
interface TextUpdateEvent : Event {
    constructor(DOMString type, optional TextUpdateEventInit options = {});
    readonly attribute unsigned long updateRangeStart;
    readonly attribute unsigned long updateRangeEnd;
    readonly attribute DOMString text;
    readonly attribute unsigned long selectionStart;
    readonly attribute unsigned long selectionEnd;
};
updateRangeStart, of type unsigned long, readonly
교체될 범위의 시작 위치입니다.
updateRangeEnd, of type unsigned long, readonly
교체될 범위의 끝 위치입니다.
text, of type DOMString, readonly
해당 범위에서 기존 문자열을 대체할 새로운 문자열입니다.
selectionStart, of type unsigned long, readonly
텍스트 교체 이후 선택의 시작 위치입니다.
selectionEnd, of type unsigned long, readonly
텍스트 교체 이후 선택의 끝 위치입니다.

4.2 TextFormatUpdateEvent

WebIDLenum UnderlineStyle { "none", "solid", "dotted", "dashed", "wavy" };
enum UnderlineThickness { "none", "thin", "thick" };

dictionary TextFormatInit {
    unsigned long rangeStart;
    unsigned long rangeEnd;
    UnderlineStyle underlineStyle;
    UnderlineThickness underlineThickness;
};

[Exposed=Window]
interface TextFormat {
    constructor(optional TextFormatInit options = {});
    readonly attribute unsigned long rangeStart;
    readonly attribute unsigned long rangeEnd;
    readonly attribute UnderlineStyle underlineStyle;
    readonly attribute UnderlineThickness underlineThickness;
};

dictionary TextFormatUpdateEventInit : EventInit {
    sequence<TextFormat> textFormats;
};

[Exposed=Window]
interface TextFormatUpdateEvent : Event {
    constructor(DOMString type, optional TextFormatUpdateEventInit options = {});
    sequence<TextFormat> getTextFormats();
};
rangeStart, of type unsigned long, readonly
장식되어야 하는 첫 번째 코드포인트 이전의 위치를 나타내는 오프셋입니다.
rangeEnd, of type unsigned long, readonly
장식되어야 하는 마지막 코드포인트 이후의 위치를 나타내는 오프셋입니다.
underlineStyle, of type UnderlineStyle, readonly
장식된 텍스트 범위에 대한 선호 밑줄 스타일입니다.
underlineThickness, of type UnderlineThickness, readonly
장식된 텍스트 범위에 대한 선호 밑줄 두께입니다.
getTextFormats method
this텍스트 형식 목록을 반환합니다.

TextFormatUpdateEvent에는 0개 이상의 텍스트 형식으로 이루어진 목록인 텍스트 형식 목록이 연결되어 있습니다.

4.3 CharacterBoundsUpdateEvent

WebIDLdictionary CharacterBoundsUpdateEventInit : EventInit {
    unsigned long rangeStart;
    unsigned long rangeEnd;
};

[Exposed=Window]
interface CharacterBoundsUpdateEvent : Event {
    constructor(DOMString type, optional CharacterBoundsUpdateEventInit options = {});
    readonly attribute unsigned long rangeStart;
    readonly attribute unsigned long rangeEnd;
};
rangeStart, of type unsigned long, readonly
텍스트 입력 서비스가 문자 경계가 필요로 하는 범위의 시작 위치입니다.
rangeEnd, of type unsigned long, readonly
텍스트 입력 서비스가 문자 경계가 필요로 하는 범위의 끝 위치입니다.

A. IDL 색인

WebIDLpartial interface HTMLElement {
     attribute EditContext? editContext;
};

dictionary EditContextInit {
    DOMString text;
    unsigned long selectionStart;
    unsigned long selectionEnd;
};

[Exposed=Window]
interface EditContext : EventTarget {
    constructor(optional EditContextInit options = {});

    undefined updateText(unsigned long rangeStart, unsigned long rangeEnd,
        DOMString text);
    undefined updateSelection(unsigned long start, unsigned long end);
    undefined updateControlBounds(DOMRect controlBounds);
    undefined updateSelectionBounds(DOMRect selectionBounds);
    undefined updateCharacterBounds(unsigned long rangeStart, sequence<DOMRect> characterBounds);

    sequence<HTMLElement> attachedElements();

    readonly attribute DOMString text;
    readonly attribute unsigned long selectionStart;
    readonly attribute unsigned long selectionEnd;
    readonly attribute unsigned long characterBoundsRangeStart;
    sequence<DOMRect> characterBounds();

    attribute EventHandler ontextupdate;
    attribute EventHandler ontextformatupdate;
    attribute EventHandler oncharacterboundsupdate;
    attribute EventHandler oncompositionstart;
    attribute EventHandler oncompositionend;
};

dictionary TextUpdateEventInit : EventInit {
    unsigned long updateRangeStart;
    unsigned long updateRangeEnd;
    DOMString text;
    unsigned long selectionStart;
    unsigned long selectionEnd;
    unsigned long compositionStart;
    unsigned long compositionEnd;
};

[Exposed=Window]
interface TextUpdateEvent : Event {
    constructor(DOMString type, optional TextUpdateEventInit options = {});
    readonly attribute unsigned long updateRangeStart;
    readonly attribute unsigned long updateRangeEnd;
    readonly attribute DOMString text;
    readonly attribute unsigned long selectionStart;
    readonly attribute unsigned long selectionEnd;
};

enum UnderlineStyle { "none", "solid", "dotted", "dashed", "wavy" };
enum UnderlineThickness { "none", "thin", "thick" };

dictionary TextFormatInit {
    unsigned long rangeStart;
    unsigned long rangeEnd;
    UnderlineStyle underlineStyle;
    UnderlineThickness underlineThickness;
};

[Exposed=Window]
interface TextFormat {
    constructor(optional TextFormatInit options = {});
    readonly attribute unsigned long rangeStart;
    readonly attribute unsigned long rangeEnd;
    readonly attribute UnderlineStyle underlineStyle;
    readonly attribute UnderlineThickness underlineThickness;
};

dictionary TextFormatUpdateEventInit : EventInit {
    sequence<TextFormat> textFormats;
};

[Exposed=Window]
interface TextFormatUpdateEvent : Event {
    constructor(DOMString type, optional TextFormatUpdateEventInit options = {});
    sequence<TextFormat> getTextFormats();
};

dictionary CharacterBoundsUpdateEventInit : EventInit {
    unsigned long rangeStart;
    unsigned long rangeEnd;
};

[Exposed=Window]
interface CharacterBoundsUpdateEvent : Event {
    constructor(DOMString type, optional CharacterBoundsUpdateEventInit options = {});
    readonly attribute unsigned long rangeStart;
    readonly attribute unsigned long rangeEnd;
};

B. 기여자

편집자 주

기여자를 추가하세요

C. 참고문헌

C.1 규범적 참고문헌

[dom]
DOM 표준. Anne van Kesteren. WHATWG. 리빙 표준. URL: https://dom.spec.whatwg.org/
[geometry-1]
Geometry Interfaces Module Level 1. Simon Pieters; Chris Harrelson. W3C. 2018년 12월 4일. W3C 후보 권고안. URL: https://www.w3.org/TR/geometry-1/
[html]
HTML 표준. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 리빙 표준. URL: https://html.spec.whatwg.org/multipage/
[uievents]
UI 이벤트. Gary Kacmarcik; Travis Leithead. W3C. 2024년 9월 7일. W3C 작업 초안. URL: https://www.w3.org/TR/uievents/
[webidl]
Web IDL 표준. Edgar Chen; Timothy Gu. WHATWG. 리빙 표준. URL: https://webidl.spec.whatwg.org/

C.2 비규범적 참고문헌

[input-events]
Input Events Level 1. Johannes Wilm. W3C. 2023년 9월 28일. W3C 작업 초안. URL: https://www.w3.org/TR/input-events-1/