jfcere / ngx-markdown

Angular markdown component/directive/pipe/service to parse static, dynamic or remote content to HTML with syntax highlight and more...
https://jfcere.github.io/ngx-markdown
MIT License
1.05k stars 179 forks source link

most simplelest code markdown [src]="'./assets/texts/null.md'" doesn't work for angular 17 standalone #518

Closed cadentic closed 3 months ago

cadentic commented 3 months ago

i also tried this method

 async ngOnInit() { const markdownRaw = wait for it.http.get('./assets/docs/index.md', { response type: 'text' }).toPromise(); this.markdown = this.mdService.compile(markdownRaw!); }

but compile and toPromise seems deprecated in the current version.

<div style="padding:100px" markdown [src]="'./assets/texts/null.md'">

this code doesn't work any more error.

ERROR Error [NullInjectorError]: R3InjectorError(Standalone[_CadenticPrivacypolicyComponent])[_MarkdownService -> _MarkdownService -> _MarkdownService -> _HttpClient -> HttpHandler -> HttpHandler]: 
  NullInjectorError: No provider for HttpHandler!
    at NullInjector.get (C:\Users\User\Desktop\cadentic_dot_net_in-main\cadentic_dot_net_in\cadentic_dot_net_in\node_modules\@angular\core\fesm2022\core.mjs:1654:27)        
    at R3Injector.get (C:\Users\User\Desktop\cadentic_dot_net_in-main\cadentic_dot_net_in\cadentic_dot_net_in\node_modules\@angular\core\fesm2022\core.mjs:3093:33)
    at R3Injector.get (C:\Users\User\Desktop\cadentic_dot_net_in-main\cadentic_dot_net_in\cadentic_dot_net_in\node_modules\@angular\core\fesm2022\core.mjs:3093:33)
    at injectInjectorOnly (C:\Users\User\Desktop\cadentic_dot_net_in-main\cadentic_dot_net_in\cadentic_dot_net_in\node_modules\@angular\core\fesm2022\core.mjs:1100:40)      
    at Module.ɵɵinject (C:\Users\User\Desktop\cadentic_dot_net_in-main\cadentic_dot_net_in\cadentic_dot_net_in\node_modules\@angular\core\fesm2022\core.mjs:1106:42)
    at Object.HttpClient_Factory (C:\Users\User\Desktop\cadentic_dot_net_in-main\cadentic_dot_net_in\cadentic_dot_net_in\node_modules\@angular\common\fesm2022\http.mjs:1454:39)
    at eval (C:\Users\User\Desktop\cadentic_dot_net_in-main\cadentic_dot_net_in\cadentic_dot_net_in\node_modules\@angular\core\fesm2022\core.mjs:3219:47)
    at runInInjectorProfilerContext (C:\Users\User\Desktop\cadentic_dot_net_in-main\cadentic_dot_net_in\cadentic_dot_net_in\node_modules\@angular\core\fesm2022\core.mjs:866:9)
    at R3Injector.hydrate (C:\Users\User\Desktop\cadentic_dot_net_in-main\cadentic_dot_net_in\cadentic_dot_net_in\node_modules\@angular\core\fesm2022\core.mjs:3218:21)      
    at R3Injector.get (C:\Users\User\Desktop\cadentic_dot_net_in-main\cadentic_dot_net_in\cadentic_dot_net_in\node_modules\@angular\core\fesm2022\core.mjs:3082:33) {        
  ngTempTokenPath: null,
  ngTokenPath: [
    '_MarkdownService',
    '_MarkdownService',
    '_MarkdownService',
    '_HttpClient',
    'HttpHandler',
    'HttpHandler'
  ]
}

ts

import { Component, OnInit,SecurityContext  } from '@angular/core';
import {MARKED_OPTIONS, MarkdownModule, MarkdownService, MarkedOptions, MarkedRenderer, MermaidAPI } from 'ngx-markdown';
import { ActivatedRoute } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { HttpClientModule } from '@angular/common/http';

// enable default sanitization
MarkdownModule.forRoot()

@Component({
  selector: 'app-cadentic-privacypolicy',
  standalone: true,
  imports: [MarkdownModule,HttpClientModule],
  templateUrl: './cadentic-privacypolicy.component.html',
  styleUrl: './cadentic-privacypolicy.component.scss'
})
export default class CadenticPrivacypolicyComponent  {

}
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideMarkdown } from 'ngx-markdown';
import { HttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes), provideClientHydration(), provideAnimationsAsync(), provideAnimationsAsync(),provideMarkdown(),provideMarkdown({ loader: HttpClient }),]
};

package.json

{
  "name": "CADENTIC®",
  "version": "9.5.0 - Alpha",
  "Author": "home pp",
  "Description": "Static Home Page",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "serve:ssr:cadentic_dot_net_in": "node dist/cadentic_dot_net_in/server/server.mjs"
  },
  "private": true,
  "dependencies": {
    "@angular-devkit/build-angular": "^17.3.0",
    "@angular-eslint/eslint-plugin": "17.4.0",
    "@angular-eslint/eslint-plugin-template": "17.4.0",
    "@angular-eslint/schematics": "17.4.0",
    "@angular-eslint/template-parser": "17.4.0",
    "@angular/animations": "^17.3.0",
    "@angular/cdk": "^17.3.0",
    "@angular/common": "^17.3.0",
    "@angular/compiler": "^17.3.0",
    "@angular/core": "^17.3.0",
    "@angular/forms": "^17.3.0",
    "@angular/material": "^17.3.6",
    "@angular/platform-browser": "^17.3.0",
    "@angular/platform-browser-dynamic": "^17.3.0",
    "@angular/platform-server": "^17.3.0",
    "@angular/router": "^17.3.0",
    "@angular/ssr": "^17.3.0",
    "@ibm/plex": "^6.4.0",
    "@material-tailwind/html": "^2.2.2",
    "@ngrx/effects": "^17.2.0",
    "@types/marked": "^6.0.0",
    "@types/quill": "^2.0.14",
    "angular-google-tag-manager": "^1.9.0",
    "chart.js": "3.3.2",
    "clipboard": "^2.0.11",
    "codelyzer": "^0.0.28",
    "del": "^7.1.0",
    "domino": "^2.1.6",
    "emoji-toolkit": "^8.0.0",
    "express": "^4.18.2",
    "gulp": "^4.0.2",
    "gulp-concat": "^2.6.1",
    "gulp-flatten": "^0.4.0",
    "gulp-rename": "^2.0.0",
    "gulp-uglify": "^3.0.2",
    "gulp-uglifycss": "^1.1.0",
    "katex": "^0.16.10",
    "marked": "^12.0.2",
    "mermaid": "^10.9.0",
    "ng-katex": "^2.0.3",
    "ngx-markdown": "^17.2.1",
    "primeflex": "^3.3.1",
    "primeicons": "^7.0.0",
    "primeng": "^17.12.0",
    "prismjs": "^1.29.0",
    "quill": "^2.0.1",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.14.3"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^17.3.3",
    "@angular/cli": "^17.3.3",
    "@angular/compiler-cli": "^17.3.0",
    "@cloudflare/workers-types": "^4.20240423.0",
    "@tailwindcss/aspect-ratio": "^0.4.2",
    "@tailwindcss/container-queries": "^0.1.1",
    "@tailwindcss/forms": "^0.5.7",
    "@tailwindcss/typography": "^0.5.13",
    "@types/express": "^4.17.17",
    "@types/jasmine": "~5.1.0",
    "@types/node": "^18.18.0",
    "autoprefixer": "^10.4.19",
    "jasmine-core": "~5.1.0",
    "karma": "~6.4.0",
    "karma-chrome-launcher": "~3.2.0",
    "karma-coverage": "~2.2.0",
    "karma-jasmine": "~5.1.0",
    "karma-jasmine-html-reporter": "~2.1.0",
    "postcss": "^8.4.38",
    "tailwindcss": "^3.4.3",
    "typescript": "~5.4.2",
    "wrangler": "^3.50.2"
  }
}

what is the best way to work with makrdown for latest versions?

jfcere commented 3 months ago

Hi @cadentic,

You are using provideMarkdown twice in the appConfig and are not providing the HttpClient.

Make sure to use the provideHttpClient() provider fonction and use provideMarkdown({ loader: HttpClient }) afterward.

You can refer to the demo configuration below:

https://github.com/jfcere/ngx-markdown/blob/2074c8e14202f392c9bc0fbeec34f8a2cae1e270/demo/src/app/app.config.ts#L12-L38

cadentic commented 3 months ago
export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes), provideClientHydration(), provideAnimationsAsync(), provideAnimationsAsync(), 
    provideAnimations(), 
    provideHttpClient(), 
    provideRouter( 
      routes, 
      withInMemoryScrolling({ 
        anchorScrolling: 'enabled', 
        scrollPositionRestoration: 'enabled', 
      }), 
    ),provideMarkdown({ loader: HttpClient }),]
};

some.componant.html

<markdown [src]="'./assets/texts/privacyPolicy.md'" ngPreserveWhitespaces ></markdown> 

resolved my issue

<markdown marmaid katex [src]="'./assets/texts/privacyPolicy.md'" ngPreserveWhitespaces ></markdown> 

but it throws a runtime error

NG02801: Angular detected that `HttpClient` is not configured to use `fetch` APIs. It's strongly recommended to enable `fetch` for applications that use Server-Side Rendering for better performance and compatibility. To enable `fetch`, add the `withFetch()` to the `provideHttpClient()` call at the root of the application.

thx @jfcere

jfcere commented 3 months ago

I suggest to read the error and Google it...

Here I did it for you: https://stackoverflow.com/questions/77512654/angular-detected-that-httpclient-is-not-configured-to-use-fetch-apis-angul

NG02801 is not an error but an warning that encourage the developers to enable the fetch implementation of the HttpClient.

To do this, just call provideHttpClient(withFetch()) in your app.config.ts.

Closing the issue.