Pnpjs: Get page details when people web part on the page

Created on 22 Jun 2018  路  11Comments  路  Source: pnp/pnpjs

Category

  • [ ] Enhancement
  • [x] Bug
  • [ ] Question
  • [ ] Documentation gap/issue

Version

Please specify what version of the library you are using: [ ^1.1.2-0 ]

Expected / Desired Behavior / Question

Able to fetch a page using the latest release. Attempting to re-test a previous bug logged, see below, with latest release

https://github.com/pnp/pnpjs/issues/125

Observed Behavior

Am getting an error, see below

Unexpected token ? in JSON at position 372

Steps to Reproduce

Create a new page and add people web part to the page. Execute code to fetch the page. After executing code below you get the error above

const pageLayoutDetails = await ClientSidePage.fromFile(
this.props.spRest.web.getFileByServerRelativeUrl(
this.props.pageLocation));

code investigate

Most helpful comment

@koltyakov ...Thanks...this seems to be working..

Let me test this throughly and let you guys know

Yes i can now confirm that this is working :-)

All 11 comments

Also just got "Unexpected token | in JSON at position 226".

@patrick-rodgers ..Except connectors which i was not able to try all, these are the webparts that are causing trouble

  1. Emded
  2. File viewer
  3. Document Libray preview
  4. List Preview
  5. Sites
  6. stream video
  7. goup calendar
  8. people
  9. twitter
  10. microsoft power apps

As a temporary workaround and a broken JSON stringified format testing:

// In Chrome SP Editor, wright on the page with webparts causing issues
import { ClientSidePage, sp } from '@pnp/sp';

ClientSidePage.escapedStringToJson = (escapedString: string) => {
    escapedString = escapedString
        .replace(/"/g, "\"")
        .replace(/:/g, ":")
        .replace(/{/g, "{")
        .replace(/}/g, "}")
        .replace(/\\\./g, '.')
        .replace(/\\\[/g, '[')
        .replace(/\\\]/g, ']')
        // Additional replacements
        .replace(/\\\\/g, '\\')
        .replace(/\\\?/g, '?')
        .replace(/\\\(/g, '(')
        .replace(/\\\)/g, ')')
        .replace(/\\\|/g, '|')
        .replace(/\\\+/g, '+');
    // console.log(escapedString); // uncomment if error
    return JSON.parse(escapedString);
};

const pageUri = window.location.pathname;
const file = sp.web.getFileByServerRelativeUrl(pageUri);
ClientSidePage.fromFile(file)
    .then(console.log).catch(console.log);

I added these additional replacements while testing some of the webparts mentioned about. Thinking about how to unescape these strings robustly for JSON.parse always work.

@koltyakov ...sorry i didnt understand the workaround .
Can you add some more details

Currently, when getting a modern page details, web parts definition strings to JSON parsing is happening. These strings are in escaped form (not a valid JSON string) which can't be parsed to JSON without unescaping. The existing logic for unescaping is to replace quotes, curly braces, and colons. Which looks to be not enough. After a brief look, I see that \\, \?, \], \[ (to name a few) should be replaced too. The replace logic is happening in ClientSidePage.escapedStringToJson, which can be redefinedbefore calling ClientSidePage.fromFile and end up with a temporary solution capable in pages parsing.

I'm not ready to add any changes to ClientSidePage.escapedStringToJson right away. Need to think out a rubust unescaping which would work for browser and Node.js as well. Yet we will definitely fix this one sooner.

@koltyakov I'm actively waiting on the next release but this issue has caused some issues. Will this be fixed in the next release which i believe is start of July?

@raymondlittle100, @harshdamaniahd, guys,

Could you try this on your webparts scenarios:

import { ClientSidePage, sp } from '@pnp/sp';

ClientSidePage.escapedStringToJson = (escapedString: string) => {
    const unespace = (escaped: string): string => {
        const mapDict = [
            [/"/g, '"'], [/:/g, ':'], [/{/g, '{'], [/}/g, '}'],
            [/\\\\/g, '\\'], [/\\\?/g, '?'], [/\\\./g, '.'], [/\\\[/g, '['], [/\\\]/g, ']'],
            [/\\\(/g, '('], [/\\\)/g, ')'], [/\\\|/g, '|'], [/\\\+/g, '+']
        ];
        return mapDict.reduce((r, m) => r.replace(m[0], m[1] as string), escaped);
    };
    escapedString = unespace(escapedString);
    // console.log(escapedString); // uncomment if error
    return JSON.parse(escapedString);
};

const pageUri = window.location.pathname; // Provide your page URI
const file = sp.web.getFileByServerRelativeUrl(pageUri);
ClientSidePage.fromFile(file)
    .then(console.log).catch(console.log);

I've placed almost all webparts on the page from the @harshdamaniahd's list and it worked for me.

Not sure that this is the implementation we'll merge, as @patrick-rodgers mentioned the bug week ago or something and probably working on it with some other more generic and universal unescape algorithm.

@koltyakov ...Thanks...this seems to be working..

Let me test this throughly and let you guys know

Yes i can now confirm that this is working :-)

Confirming that this is working for all webparts

Created the PR with corresponding changes. Hopefully, this should be a part of the next release and what's more hope this covers all the combinations of the webparts stringified bodies.

@koltyakov brilliant thanks. Another example of the great works you guys do

Was this page helpful?
0 / 5 - 0 ratings