mbanting / metalsmith-prismic

A Metalsmith.io plugin to pull in content from Prismic.io
MIT License
48 stars 19 forks source link

Error when querying documents with 'slice zones' #37

Open danhalliday opened 6 years ago

danhalliday commented 6 years ago

I get the following error when querying for documents whose data model has the 'slice zone' turned on. Not sure where to start with this!

Template:

---
prismic:
  documents:
    query: '[[at(document.type, "page")]]'
    allPages: true
---

<%= prismic.documents.results[0].data.title.json.value %>

Error:

Metalsmith                                        
  starting development - ^C to exit                 

     ···    first build                             
     ···    livereload                              
     ···    http://localhost:3000                   

            Starting up...                          
/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/dist/prismic.io.js:3009
        if (classForType[field.type]) {
                              ^

TypeError: Cannot read property 'type' of undefined
    at initField (/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/dist/prismic.io.js:3009:31)
    at SliceZone (/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/dist/prismic.io.js:2917:28)
    at initField (/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/dist/prismic.io.js:3010:20)
    at Object.parseFragments (/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/dist/prismic.io.js:3050:35)
    at Document (/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/dist/prismic.io.js:1844:51)
    at parseDoc (/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/dist/prismic.io.js:314:20)
    at Array.map (<anonymous>)
    at Object.callback (/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/dist/prismic.io.js:462:53)
    at /my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/dist/prismic.io.js:1296:18
    at IncomingMessage.<anonymous> (/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/dist/prismic.io.js:1264:27)
    at emitNone (events.js:110:20)
    at IncomingMessage.emit (events.js:207:7)
    at endReadableNT (_stream_readable.js:1059:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    at process._tickCallback (internal/process/next_tick.js:180:9)
doublejosh commented 6 years ago

Same issue.

The problem originates in initField(field) while checking for a helper class for the field type. This is within the Prismic JS SDK (not the metalsmith-prismic repo).

When the Fragments:SliceZone helper looks for the fragment type... there is no helper class for {type: "Slice"} in the library. (This function seems to be used for both parent fields and child components).

Looks like the data was structured differently in the past. Slice fragments are broken into non-repeat and repeat object properties, and the code is just looking for a stack of slices.

This will require refactoring on both: SliceZone and Slice objects to accommodate iterating and parsing fragments.

doublejosh commented 6 years ago

I can confirm that site builds (without slices) still work after updating to the prismic js-sdk to 3.6.1 from 1.4.0 ...this is promising for being able to use slices within what seems like a new Prismic structure.

doublejosh commented 6 years ago

After updating to Prismic JS SDK 3.6.1 a new error pops up with slices...

/my/project/path/node_modules/metalsmith-prismic/lib/index.js:244
          if (!fragment.asHtml) {
                       ^

TypeError: Cannot read property 'asHtml' of undefined
    at processSingleFragment (/my/project/path/node_modules/metalsmith-prismic/lib/index.js:244:24)
    at /my/project/path/node_modules/metalsmith-prismic/lib/index.js:328:22
    at Function._.map._.collect (/my/project/path/node_modules/metalsmith-prismic/node_modules/underscore/underscore.js:172:24)
    at processSingleFragment (/my/project/path/node_modules/metalsmith-prismic/lib/index.js:327:46)
    at /my/project/path/node_modules/metalsmith-prismic/lib/index.js:216:20
    at Function._.map._.collect (/my/project/path/node_modules/metalsmith-prismic/node_modules/underscore/underscore.js:172:24)
    at processRetrievedDocument (/my/project/path/node_modules/metalsmith-prismic/lib/index.js:211:32)
    at /my/project/path/node_modules/metalsmith-prismic/lib/index.js:198:20
    at Function._.map._.collect (/my/project/path/node_modules/metalsmith-prismic/node_modules/underscore/underscore.js:172:24)
    at processRetrievedContent (/my/project/path/node_modules/metalsmith-prismic/lib/index.js:197:32)
    at prismicQueryCallback (/my/project/path/node_modules/metalsmith-prismic/lib/index.js:157:29)
    at /my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/lib/api.js:507:23
    at /my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/lib/api.js:497:15
    at ApiCache.set (/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/lib/cache.js:30:12)
    at Object.callback (/my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/lib/api.js:496:19)
    at /my/project/path/node_modules/metalsmith-prismic/node_modules/prismic.io/lib/requests.js:225:10

I thought a manual approach could save the day, but sadly the htmlSerializer function won't work in the config object because it's not included in the metalsmith-prismic-server implementation here...

https://github.com/futurice/metalsmith-prismic-server/blob/master/src/metalsmith.js

doublejosh commented 6 years ago

Here is the problem code (was marked with a //TODO)...

/my/project/path/node_modules/metalsmith-prismic/lib/index.js

} else if (fragment instanceof Prismic.Fragments.SliceZone) {
  // TODO
  childPromises.push(Promise.all(_.map(fragment.value, function(sliceFragment) {
    return processSingleFragment(sliceFragment.value, ctx, queryMetadata).then(function (subFragmentObject) {
      subFragmentObject.sliceType = sliceFragment.sliceType;
      subFragmentObject.sliceLabel = sliceFragment.label;
      return subFragmentObject;
    });
  })).then(function(children) {
    return fragmentObject.children = children;
  }));
}