@craftercms/ice

中文文档
4.3.1发布于 2026/07/08GNU LGPL 3.0TypeScriptESM + CJS近 30 天下载 2532

Crafter CMS in-context editing library

原始使用文档
文档目录14 节
  1. Usage
  2. Via npm
  3. Via html script imports
  4. Package Index
  5. fetchIsAuthoring
  6. getIceAttributes
  7. getDropZoneAttributes
  8. addAuthoringSupport
  9. repaintPencils
  10. reportNavigation
  11. Example
  12. @craftercms/ice/react
  13. useICE
  14. useDropZone

npm (scoped)

@craftercms/ice

Contains JavaScript utilities to use Crafter CMS' in-context editing in your apps and sites

Note: All methods of this package work with Content Instance as data structure they understand (the model param). Use in conjunction with parseDescriptor and preParseSearchResults from @craftercms/content to obtain such data structure.

Usage

All of Crafter CMS packages can be used either via npm or in plain html/javascript via regular script imports.

Via npm

  • yarn add @craftercms/ice or npm install @craftercms/ice
  • import or require the functions you wish.

Via html script imports

  • Download the bundle and import them in your page.
  • The bundles declare a global variable named craftercms. You can access all craftercms' packages and functions under this root.
  • The ice package depends on rxjs, make sure to import rxjs too before the ice script.

Tip: Once you've imported the scripts, type craftercms on your browser's dev tools console to inspect the package(s)

Vanilla html/js example

<div id="myFeature"></div>
<script src="https://unpkg.com/rxjs"></script>
<script src="https://unpkg.com/@craftercms/utils"></script>
<script src="https://unpkg.com/@craftercms/classes"></script>
<script src="https://unpkg.com/@craftercms/content"></script>
<script src="https://unpkg.com/@craftercms/ice"></script>
<script>
 (function ({ content, ice }, { operators }) {

   content.getItem(
     '/site/website/index.xml',
     { baseUrl: 'http://localhost:8080', site: 'editorial' }
   ).pipe(
     operators.map(content.parseDescriptor)
   ).subscribe((model) => {
     const attrs = ice.getICEAttributes({ model, parentModelId: '/site/website/index.xml' });
     const elem = document.querySelector('#myFeature');
     Object.entries(attrs).forEach(([attr, value]) => {
       elem.setAttribute(attr, value);
     });
     Object.entries(model).forEach(([fieldId, value]) => {
       if (fieldId !== 'craftercms') {
         const el = document.createElement('div');
         el.innerText = `${fieldId}: ${value}`;
         elem.appendChild(el);
       }
     });
   });

 })(craftercms, rxjs);
</script>

Package Index

The examples below assume usage in the style of using via npm. If you're using the bundles, directly importing as a script in the browser, these functions will be under the global variable named craftercms.ice (i.e. window.craftercms.ice).

fetchIsAuthoring

Interrogates the current origin server to determine if the site/app is running in Crafter CMS authoring environment (Preview). Positive reply (true) means is authoring; assume you need to add pencils and import other authoring tools. False means is delivery and all authoring tools should be disabled.

Example

import { fetchIsAuthoring } from '@craftercms/ice';

fetchIsAuthoring().then((isAuthoring) => {
  console.log(`You're currently in ${isAuthoring ? 'authoring' : 'delivery'}.`);
});

getIceAttributes

Use this function to obtain the attributes that you need to add to your HTML element(s) to put pencils for In Context Editing.

Example

  import { from, forkJoin } from 'rxjs';
  import { map } from 'rxjs/operators';
  import { getICEAttributes, fetchIsAuthoring, repaintPencils } from '@craftercms/ice';
  import { getItem, parseDescriptor } from '@craftercms/content';

  forkJoin({
    isAuthoring: from(fetchIsAuthoring()),
    model: getItem('/site/website/index.xml', { site: 'editorial' }).pipe(map(parseDescriptor))
  }).subscribe(({ isAuthoring, model }) => {
  
    const page = document.querySelector('#main');
    if (page) {
      const homepageEditPencil = getICEAttributes({ model, isAuthoring });
      Object.entries(homepageEditPencil).forEach(([attr, value]) => {
        page.setAttribute(attr, value);
      });
      repaintPencils();
    }
  
  });

getDropZoneAttributes

Use this function to obtain the attributes that you need to add to your HTML element(s) to mark them as an item selector drop zone.

Example

  import { from, forkJoin } from 'rxjs';
  import { map } from 'rxjs/operators';
  import { getICEAttributes, getDropZoneAttributes, fetchIsAuthoring, repaintPencils } from '@craftercms/ice';
  import { getItem, parseDescriptor } from '@craftercms/content';

  forkJoin({
    isAuthoring: from(fetchIsAuthoring()),
    model: getItem('/site/website/index.xml', { site: 'editorial' }).pipe(map(parseDescriptor))
  }).subscribe(({ isAuthoring, model }) => {
  
    const features = document.querySelector('.features');
    if (features) {

      const homepageFeaturesDropZone = getDropZoneAttributes({ model, isAuthoring, zoneName: 'features_o' });
      Object.entries(homepageFeaturesDropZone).forEach(([attr, value]) => {
        features.setAttribute(attr, value);
      });

      const items = features.querySelectorAll('article');
      items.forEach((item) => {
        const pencil = getICEAttributes({ model, isAuthoring });
        Object.entries(pencil).forEach(([attr, value]) => {
          item.setAttribute(attr, value);
        });
      });
        
      repaintPencils();

    }

  });

addAuthoringSupport

Use this method to include the necessary scripts to enable Crafter CMS authoring support (i.e. pencils, drag & drop, etc.) on your site/app. This function does not check whether you're in authoring or delivery. You should check that prior to invoking.

Example

import React, { useEffect } from 'react';
import { isAuthoring } from '../utils';
import { addAuthoringSupport } from '@craftercms/ice';

function App() {
  useEffect(() => {
    if (isAuthoring()) {
      // This is a react example but you may use addAuthoringSupport outside of react
      addAuthoringSupport().then(() => {
        // Feel free to discard the promise if you don't need 
        console.log('Authoring tools have loaded and are ready to use.');
      });
    }
  }, []);
  return (
    {/* ... */}
  );
}

repaintPencils

Re-renders all pencils

Example

import { repaintPencils } from '@craftercms/ice';

new Carousel({
  element: '#myElement',
  // ...other settings
  onSlideChange: () => {
    // Update pencils so current slide pencil is visible and prev slide is gone.
    repaintPencils();
  }
});

reportNavigation

Report up to Crafter Studio that navigation has occurred.

Useful primarily for SPAs when there's no page reload, but the page context changes.

Example

import { reportNavigation } from '@craftercms/ice';

function DynamicRoute(props) {
  const { match, location } = props;
  let url = match.path.includes(':')
    ? match.path.substring(0, match.path.indexOf(':') -1)
    : match.url;
  useEffect(() => {
    reportNavigation(url);
  }, [url]);
  return (
    ...
  );
}

@craftercms/ice/react

React bindings for pencils and drop zones. Requires React 16.8.0 or above (hooks release). Not available for class components, use the plain methods described above part of this same package.

useICE

Use this function to obtain the attributes that you need to add to your HTML element(s) to put pencils for In Context Editing.

Make sure to use the parseDescriptor function from @craftercms/content as that's the structure these hooks understand.

Example

  import React, { useEffect, useState } from 'react';
  import { from, forkJoin } from 'rxjs';
  import { map } from 'rxjs/operators';
  import { fetchIsAuthoring } from '@craftercms/ice';
  import { useICE } from '@craftercms/ice/react';
  import { getItem, parseDescriptor } from '@craftercms/content';
  
  function App() {
    const [state, setState] = useState();
    useEffect(() => {
      forkJoin({
        isAuthoring: from(fetchIsAuthoring()),
        model: getItem('/site/website/index.xml', { site: 'editorial' }).pipe(map(parseDescriptor))
      }).subscribe(({ isAuthoring, model }) => {
        setState({ isAuthoring, model });
      });
    }, []);
    return (
      state ? <HomePage /> : 'Loading...'
    );
  }
  
  function HomePage(props) {
    const { isAuthoring, model } = props;
    const { props: pencil } = useICE({ isAuthoring, model });
    return  (
      <div {...pencil}>
        {/* ... */}
      </div>
    );
  }
  

useDropZone

Use this function to obtain the attributes that you need to add to your HTML element(s) to mark them as an item selector drop zone.

Make sure to use the parseDescriptor function from @craftercms/content as that's the structure these hooks understand.

  import React, { useEffect, useState } from 'react';
  import { from, forkJoin } from 'rxjs';
  import { map } from 'rxjs/operators';
  import { fetchIsAuthoring } from '@craftercms/ice';
  import { useICE, useDropZone } from '@craftercms/ice/react';
  import { getItem, parseDescriptor } from '@craftercms/content';
  
  function App() {
    const [state, setState] = useState();
    useEffect(() => {
      forkJoin({
        isAuthoring: from(fetchIsAuthoring()),
        model: getItem('/site/website/index.xml', { site: 'editorial' }).pipe(map(parseDescriptor))
      }).subscribe(({ isAuthoring, model }) => {
        setState({ isAuthoring, model });
      });
    }, []);
    return (
      state ? <HomePage /> : 'Loading...'
    );
  }
  
  function HomePage(props) {
    const { isAuthoring, model } = props;
    const { props: pencil } = useICE({ isAuthoring, model });
    const { props: dz } = useDropZone({ isAuthoring, model, fieldId: 'features_o' });
    return  (
      <div {...pencil}>
        <section className="features" {...dz}>
          {
            model.features_o.map((feature) => <Feature model={feature} isAuthoring={isAuthoring} />)
          }
        </section>
      </div>
    );
  }
  
  function Feature(props) {
    const { isAuthoring, model } = props;
    const { props: pencil } = useICE({ isAuthoring, model });
    return  (
      <article {...pencil}>
        <h2>{model.title_s}</h2>
        <p>{model.body_s}</p>
      </article>
    );
  }

版本与发布记录

@craftercms/ice 共发布 34 个版本,首次发布于 2020/02/27;过去 12 个月发布了 1 个版本。

版本发布日期距今
4.3.1latest2026/07/084 个月前
4.2.2-support.1latest-v4.2.22025/03/281.6 年前
4.3.02025/02/211.7 年前
4.2.22025/01/211.8 年前
4.2.12024/12/161.9 年前
4.1.9support-4.1.x2024/11/262 年前

关于 @craftercms/ice 的常见问题

@craftercms/ice 是什么?

Crafter CMS in-context editing library

如何安装 @craftercms/ice?

在项目目录运行 npm install @craftercms/ice,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(^18.0.0 || ^19.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@craftercms/ice 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@craftercms/ice 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@craftercms/ice 可以商用吗?

@craftercms/ice 使用 GNU LGPL 3.0 许可。声明的许可为 GNU LGPL 3.0,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@craftercms/ice 的下载量有多少?

根据 npm 官方下载统计,@craftercms/ice 在 2026/10/11 – 2026/11/09 这 30 天内被下载 2,532 次,日均约 84 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@craftercms/ice 还在维护吗?

最新版本 4.3.1 发布于 2026/07/08(4 个月前);至今共发布 34 个版本,其中过去 12 个月发布了 1 个;首次发布于 2020/02/27。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。