CONNECT-platform / codedoc

Create beautiful modern documentation websites.
https://codedoc.cc
MIT License
427 stars 12 forks source link

Adding Utterances via custom component #30

Closed TysonMN closed 4 years ago

TysonMN commented 4 years ago

I would like to add support for comments to my blog via Utterances.

I think the way I am supposed to do it is with a custom component.

Utterances is enabled on a particular page by adding the following HTML.

<script src="https://utteranc.es/client.js"
        repo="[ENTER REPO HERE]"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script>

I think I have followed all the instructions for adding a custom component. My problem is that TypeScript doesn't think repo is a valid attribute of a script element.

TSError: ⨯ Unable to compile TypeScript: .codedoc/components/utterances/index.tsx(11,18): error TS2322: Type '{ src: string; repo: string; "issue-term": string; label: string; theme: string; crossorigin: string; async: true; }' is not assignable to type 'ScriptAttributes'. Property 'repo' does not exist on type 'ScriptAttributes'.

Conceptually, I know that I want to add tell the TypeScript type system to allow these attributes for this tag, but I don't know how to do that. I think it should be something similar to these top search results on SO, but I am not familiar enough with this to know how to apply these solutions for a site hosted by coding.blog.

Here is the branch that contains my attempt to get this working.

How can I enable Utterances on a page of a site hosted by coding.blog?

(My apologies if this is a standard tsx problem and the solution has nothing to do with coding.blog.)

loreanvictor commented 4 years ago

no worries, this is not a standard tsx problem. this is due to type-checking provided by connective-html, which is rather restrictive (it only allows standard attributes).

You can by-pass that type-checking by creating an attributes object and then referencing it, i.e.:

const opts = {
  'custom-attr-1': 'bla bla',
  'custom-attr-2': 'ladida',
}

return <script src="link-to-script" {...opts}/>;

which in your case would be:

import { ThemedComponentThis } from '@connectv/jss-theme';
import { RendererLike } from '@connectv/html';

export function Comments(
  this: ThemedComponentThis,
  renderer: RendererLike<any, any>,
  content: any,
) {
  const utteranceOpts = {
    'repo': 'bender2k14/tyson-williams-blog',
    'issue-term': 'pathname',
    'label': '💬comments',
    'theme': 'github-light',
    'crossorigin': 'anonymous'
  };

  return <script src="https://utteranc.es/client.js" {...utteranceOpts} async />
}

P.S. also if you don't want to style your component, you do not need ThemedComponentThis and this attributes as well.

loreanvictor commented 4 years ago

Also @bender2k14 if you manage to get this working, it would be nice to create a plugin out of it that would allow people to easily re-use this. You can read about how to write a plugin here. Perhaps this example would also be helpful.

TysonMN commented 4 years ago

(My apologies if this is a standard tsx problem and the solution has nothing to do with coding.blog.)

no worries, this is not a standard tsx problem.

Ok. If I happen to ask some noob web-programming question though, feel free to just give me a vague pointer to the general solution idea. I have web programmer friends that I can pester for more details in those cases so that you can stay focused on the CONNECT-platform.

I ran into one more issue but was able to solve it myself :)

Compared to the example Component Code, the code that you gave above for my case is missing the options: CardOptions argument. That caused this build error, which confused me.

Using ts-node version 8.10.2, typescript version 3.9.5
# Serving docs on http://localhost:3000
# building ........ src\markdown\404.md
# built:: ......... dist\404.html
# building ........ src\markdown\archive.md
# built:: ......... dist\archive.html
# building ........ src\markdown\index.md
# built:: ......... dist\index.html
# building ........ src\markdown\sample-blog-post.md
TypeError: renderer.create is not a function
    at Object.Utterances (C:\Code\Blogs\tyson-williams-blog\.codedoc\components\utterances\index.tsx:22:10)
    at ComponentPlugin.create (C:\Code\Blogs\tyson-williams-blog\.codedoc\node_modules\@connectv\html\src\renderer\plugin\component\component.ts:39:25)
    at C:\Code\Blogs\tyson-williams-blog\.codedoc\node_modules\@connectv\html\src\renderer\extensible-renderer.ts:45:77
    at Array.some (<anonymous>)
    at ExtensibleRenderer.create (C:\Code\Blogs\tyson-williams-blog\.codedoc\node_modules\@connectv\html\src\renderer\extensible-renderer.ts:45:18)
    at Object.<anonymous> (C:\Code\Blogs\tyson-williams-blog\.codedoc\node_modules\@connectv\marked\src\quote-comp.tsx:20:25)
    at ComponentPlugin.create (C:\Code\Blogs\tyson-williams-blog\.codedoc\node_modules\@connectv\html\src\renderer\plugin\component\component.ts:39:25)
    at C:\Code\Blogs\tyson-williams-blog\.codedoc\node_modules\@connectv\html\src\renderer\extensible-renderer.ts:45:77
    at Array.some (<anonymous>)
    at ExtensibleRenderer.create (C:\Code\Blogs\tyson-williams-blog\.codedoc\node_modules\@connectv\html\src\renderer\extensible-renderer.ts:45:18)
[ERROR] 20:48:32 TypeError: renderer.create is not a function

I eventually figured out the problem by starting from the example Component Code (or nearly so) and then slowing changing it into what you suggested.

After I had already got it working, I noticed that the code example for the Custom Inline Component contains _: any as its second argument.

Is it necessary for the second argument to exist in order to contain the attributes given in the definition / first line of a use of the component in the markdown?

loreanvictor commented 4 years ago

Yes I forgot about that. The second argument (or first if you drop this argument, which you can if you don't need it) is always the attributes passed to the component. This is JSX/TSX standard transpilation rule, not specific to CODEDOC's markdown components (they are also TSX components so that they can be re-used in other JSX/TSX code).

TysonMN commented 4 years ago

Maybe the documentation about custom components could state that this argument is required (and maybe even give the error message that will occur is this rule is not followed). It could also recommended the idea of using _: any if the argument is not needed.

There is another issue. If I directly open my sample blog post, then the comments are displayed. But if I first open my home page and then navigate to the sample blog post, the comments are not displayed. A workaround is to refresh the page.

Does this behavior happen for you @loreanvictor as well?

TysonMN commented 4 years ago

Another potentially related issue.

When I try to pass in a theme like this...

> :DarkLight
> > :InLight
> >
> > > :Utterances theme=github-light
>
> > :InDark
> >
> > > :Utterances theme=github-light

...the comments don't appear in dark mode. See my sample blog post 2.

P.S. I passed in github-light in both cases on purpose since I know that works for my sample blog post in both light and dark modes.

loreanvictor commented 4 years ago

Maybe the documentation about custom components could state that this argument is required (and maybe even give the error message that will occur is this rule is not followed). It could also recommended the idea of using _: any if the argument is not needed.

It's hard to detect this issue since there is a second argument being passed to the function, its just that the function (the component) expects a renderer while an options parameter is being passed:

As for documentation though, yes generally connective html and connective sdh are seriously lacking in documentation ATM.

loreanvictor commented 4 years ago

There is another issue. If I directly open my sample blog post, then the comments are displayed. But if I first open my home page and then navigate to the sample blog post, the comments are not displayed. A workaround is to refresh the page.

Does this behavior happen for you @loreanvictor as well?

Yes. This is a bug with smooth loading mechanism of CODEDOC. Subsequent pages are loaded in the background and then the content (and other important parts) are replaced, to create a smooth and fast navigation experience. However, the container body is not replaced properly right now, which means scripts inside subsequently loaded containers are not executed normally. Inline scripts are manually executed, but right now there is no solution for remote scripts.

@bender2k14 could you open an issue for this particular matter? I have some solutions in mind, but need to test them in terms of performance first, so cannot do a quick fix ATM.

loreanvictor commented 4 years ago

Another potentially related issue.

When I try to pass in a theme like this...

> :DarkLight
> > :InLight
> >
> > > :Utterances theme=github-light
>
> > :InDark
> >
> > > :Utterances theme=github-light

...the comments don't appear in dark mode. See my sample blog post 2.

P.S. I passed in github-light in both cases on purpose since I know that works for my sample blog post in both light and dark modes.

This is a styling bug from the DarkLight component. Evidently the dark container relies on its internal content to scale its width, and the Utterance iframe does not specify any particular width, resulting in 0 width for the container.

TysonMN commented 4 years ago

Thanks again for all the help getting this to work. I will close this now.