mcpField
T
text-editing

text-editing

github.com/rshankrasデザイン・UI83877 回インストール14 週間前に更新
リポジトリ

text-editing について

SwiftUIでのテキスト表示とリッチテキスト編集を扱うスキルです。Text、AttributedString、選択範囲の書式設定、Markdownの制約を解説します。

主な機能

  1. 01SwiftUIのテキストスタイル
  2. 02AttributedStringの書式設定
  3. 03選択範囲のリッチ編集
  4. 04カスタム書式制約
  5. 05インラインMarkdownの解説

活用シーン

  1. 01SwiftUIビューの読み取り専用テキストを装飾
  2. 02テキストエディタに書式設定コントロールを追加
  3. 03iOS 18 APIで選択テキストを整形

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/rshankras/claude-code-apple-skills --skill text-editing

インストール後、Claude Code で/text-editingを入力して読み込まれたか確認します。

詳細

スタイル付きテキストの編集

SwiftUI でスタイル付きテキストを表示し、リッチテキストエディタを構築するためのパターンを紹介します。Text のスタイリング、AttributedString、選択範囲に応じた書式設定を行う TextEditor、カスタム書式定義について説明します。

このスキルが有効になる場面

次のような場合にこのスキルを使用してください。

  • スタイル付きまたは書式設定されたテキストを表示したい
  • 太字・斜体・下線のコントロールを備えたリッチテキスト編集が必要
  • AttributedString または TextEditor について質問する
  • テキスト書式設定ツールバーを作成したい
  • Text ビューでの Markdown のレンダリングについて質問する
  • カスタムテキスト属性または書式設定の制約が必要
  • 選択範囲に応じてテキストを書式設定したい

判断ツリー

What text feature do you need?
|
+- Display styled read-only text
|  +- Simple styling (one style) -> Text Styling section below
|  +- Mixed styles in one string -> AttributedString section below
|  +- Markdown content -> Markdown section below
|
+- Edit plain text
|  +- TextEditor(text: $stringBinding)
|
+- Edit rich/styled text
|  +- Basic rich editor -> Rich Text Editing section below
|  +- With formatting toolbar -> Formatting Controls section below
|  +- With custom constraints -> Custom Formatting section below

API の利用可能状況

API最小バージョン備考
Text with modifiersiOS 13.font()、.bold()、.italic()
TextEditor(text:)iOS 14通常の文字列バインディング
.foregroundStyle()iOS 15.foregroundColor() より推奨
AttributedStringiOS 15リッチテキストモデル
.bold(condition)iOS 16条件付きの太字・斜体
.underline(pattern:)iOS 16破線、点線のパターン
TextEditor(text:selection:)iOS 18AttributedString と選択範囲
AttributedTextSelectioniOS 18選択範囲に応じた書式設定
text.transformAttributes(in:)iOS 18選択範囲内の属性を変更
AttributedTextFormattingDefinitioniOS 18カスタム書式制約
@Environment(\.fontResolutionContext)iOS 18フォントのプロパティを解決

よくある間違いトップ 5

#間違い修正方法
1新規プロジェクトで .foregroundColor() を使う.foregroundStyle() を使います。グラデーションと ShapeStyle に対応しています
2テキストに value: を指定せず .animation(.spring()) を使うiOS 15 で非推奨になりました。必ず value: パラメーターを渡してください
3Text で完全な Markdown が使えると思い込むText がサポートするのはインライン Markdown のみです。太字、斜体、[リンク]に対応します。リスト、表、コードブロック、画像には対応していません
4body の評価ごとに AttributedString のインスタンスを新しく作成する複雑な AttributedString オブジェクトは @State にキャッシュするか、body の外の計算プロパティに保存してください
5リッチテキストに TextEditor(text: $string) を使うAttributedString のバインディングを使って TextEditor(text: $attributedString, selection: $selection) を使用してください(iOS 18 以降)

テキストスタイリングのクイックリファレンス

// Font
Text("Hello").font(.headline)
Text("Custom").font(.system(size: 24, design: .rounded))

// Weight
Text("Bold").fontWeight(.bold)

// Color — prefer foregroundStyle over foregroundColor
Text("Styled").foregroundStyle(.red)
Text("Gradient").foregroundStyle(
    .linearGradient(colors: [.yellow, .blue], startPoint: .top, endPoint: .bottom)
)

// Decorations
Text("Bold").bold()
Text("Conditional").bold(someCondition)
Text("Underline").underline(true, pattern: .dash, color: .blue)
Text("Strike").strikethrough(true, pattern: .dot, color: .red)

// Layout
Text("Centered").multilineTextAlignment(.center)
Text("Spaced").lineSpacing(10)
Text("Truncated").lineLimit(2).truncationMode(.tail)

AttributedString

// Create and style ranges
var text = AttributedString("Red and Blue")
if let redRange = text.range(of: "Red") {
    text[redRange].foregroundColor = .red
    text[redRange].font = .headline
}
if let blueRange = text.range(of: "Blue") {
    text[blueRange].foregroundColor = .blue
    text[blueRange].underlineStyle = .single
}

// Display
Text(text)
使用可能な属性
属性型例
.fontFont.headline
.foregroundColorColor.red
.backgroundColorColor.yellow
.underlineStyleUnderlineStyle.single
.underlineColorColor.blue
.strikethroughStyleUnderlineStyle.single
.strikethroughColorColor.red
.inlinePresentationIntentInlinePresentationIntent.stronglyEmphasized(太字)、.emphasized(斜体)

リッチテキスト編集(iOS 18 以降)

struct RichTextEditorView: View {
    @State private var text = AttributedString("Select text to format")
    @State private var selection = AttributedTextSelection()

    @Environment(\.fontResolutionContext) private var fontResolutionContext

    var body: some View {
        VStack {
            TextEditor(text: $text, selection: $selection)
                .frame(height: 200)

            HStack {
                Button(action: toggleBold) {
                    Image(systemName: "bold")
                }
                Button(action: toggleItalic) {
                    Image(systemName: "italic")
                }
                Button(action: toggleUnderline) {
                    Image(systemName: "underline")
                }
            }
        }
    }

    private func toggleBold() {
        text.transformAttributes(in: &selection) {
            let font = $0.font ?? .default
            let resolved = font.resolve(in: fontResolutionContext)
            $0.font = font.bold(!resolved.isBold)
        }
    }

    private func toggleItalic() {
        text.transformAttributes(in: &selection) {
            let font = $0.font ?? .default
            let resolved = font.resolve(in: fontResolutionContext)
            $0.font = font.italic(!resolved.isItalic)
        }
    }

    private func toggleUnderline() {
        text.transformAttributes(in: &selection) {
            if $0.underlineStyle != nil {
                $0.underlineStyle = nil
            } else {
                $0.underlineStyle = .single
            }
        }
    }
}
選択範囲の属性を読み取る
// Get current attributes at the selection/cursor
let attributes = selection.typingAttributes(in: text)
let currentColor = attributes.foregroundColor ?? .primary

カスタム書式定義(iOS 18 以降)

エディタで使用できる書式設定オプションを制限します。

struct MyTextFormatting: AttributedTextFormattingDefinition {
    typealias Scope = AttributeScopes.SwiftUIAttributes

    static let fontWeight = ValueConstraint(
        \.font,
        constraint: { font in
            guard let font = font else { return nil }
            let weight = font.resolve().weight
            return font.weight(weight == .bold ? .regular : .bold)
        }
    )
}

// Apply to TextEditor
TextEditor(text: $text, selection: $selection)
    .textFormattingDefinition(MyTextFormatting.self)

Text での Markdown

// Inline markdown support
Text("This is **bold** and *italic* text")
Text("Visit [Apple](https://www.apple.com)")
Text("Code: `inline code`")
Markdown の制限事項

Text がサポートするのはインライン Markdown のみです。

  • ✅ 太字(**text**)、斜体(*text*)、リンク、インラインコード
  • ❌ 改行、ブロック書式、リスト、表、コードブロック、画像、引用ブロック

レビューチェックリスト

テキスト表示
  • 非推奨の .foregroundColor() ではなく .foregroundStyle() を使用している
  • 切り捨てられるテキストには .lineLimit() と .help() のツールチップ、または .textSelection(.enabled) を併用している
  • ダイナミックタイプに対応している — 固定サイズではなく、システムフォントスタイルを使用している
  • 色がダークモードに適応する — システムカラーまたはセマンティックスタイルを使用している
AttributedString
  • 複雑な AttributedString を body 内で再作成せず、@State にキャッシュしている
  • 範囲検索に安全な if let range = text.range(of:) パターンを使用している
  • 適切な属性を使用している(意味上の太字・斜体には .inlinePresentationIntent を使用)
TextEditor
  • リッチテキストでは TextEditor(text: $attributedString, selection: $selection) を使用します(iOS 18 以降)
  • 書式設定ツールバーでは text.transformAttributes(in: &selection) パターンを使用します
  • 切り替えロジックでは @Environment(\.fontResolutionContext) を使用してフォントを解決します
  • 書式設定ボタンにアクセシビリティラベルを設定します
ローカライズ
  • ユーザー向けの文字列には LocalizedStringKey を使用します
  • ローカライズされた文字列内の Markdown には Text(LocalizedStringKey("**Bold** text")) を使用します

参考資料

コメント