Update
This commit is contained in:
@@ -2413,26 +2413,40 @@ To check out examples in demo classes, expand the collapsible sections below.
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
``` abap
|
``` abap
|
||||||
CLASS zcl_some_class DEFINITION PUBLIC FINAL CREATE PUBLIC.
|
CLASS zcl_some_class DEFINITION
|
||||||
|
PUBLIC
|
||||||
|
FINAL
|
||||||
|
CREATE PUBLIC .
|
||||||
|
|
||||||
PUBLIC SECTION.
|
PUBLIC SECTION.
|
||||||
INTERFACES if_oo_adt_classrun.
|
INTERFACES if_oo_adt_classrun.
|
||||||
|
PROTECTED SECTION.
|
||||||
PRIVATE SECTION.
|
PRIVATE SECTION.
|
||||||
|
"Markdown URLs
|
||||||
CONSTANTS url_cs TYPE string VALUE `https://api.github.com/repos/SAP-samples/abap-cheat-sheets/git/trees/main`.
|
CONSTANTS url_cs TYPE string VALUE `https://api.github.com/repos/SAP-samples/abap-cheat-sheets/git/trees/main`.
|
||||||
CONSTANTS url_gh TYPE string VALUE `https://raw.githubusercontent.com/SAP-samples/abap-cheat-sheets/main/`.
|
CONSTANTS url_gh TYPE string VALUE `https://raw.githubusercontent.com/SAP-samples/abap-cheat-sheets/main/`.
|
||||||
CONSTANTS url_api TYPE string VALUE `https://api.github.com/markdown`.
|
"Here go email addresses
|
||||||
DATA url TYPE string.
|
CONSTANTS sender_addr TYPE cl_bcs_mail_message=>ty_address VALUE '...@...'.
|
||||||
|
CONSTANTS recipient_addr TYPE cl_bcs_mail_message=>ty_address VALUE '...@...'.
|
||||||
|
|
||||||
TYPES: BEGIN OF s,
|
TYPES: BEGIN OF s,
|
||||||
file_name TYPE string,
|
file_name TYPE string,
|
||||||
title TYPE string,
|
markdown TYPE string,
|
||||||
code_snippets TYPE string_table,
|
error TYPE abap_boolean,
|
||||||
error TYPE abap_boolean,
|
|
||||||
END OF s.
|
END OF s.
|
||||||
DATA tab TYPE TABLE OF s WITH EMPTY KEY.
|
DATA tab TYPE TABLE OF s WITH EMPTY KEY.
|
||||||
DATA snippets TYPE string_table.
|
DATA url TYPE string.
|
||||||
DATA html TYPE string.
|
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CLASS zcl_some_class IMPLEMENTATION.
|
CLASS zcl_some_class IMPLEMENTATION.
|
||||||
|
|
||||||
|
|
||||||
METHOD if_oo_adt_classrun~main.
|
METHOD if_oo_adt_classrun~main.
|
||||||
|
|
||||||
|
"----------- Retrieving all Markdown file names in the ABAP cheat sheet GitHub repository -----------
|
||||||
|
|
||||||
TRY.
|
TRY.
|
||||||
"Creating a client object using a destination
|
"Creating a client object using a destination
|
||||||
"In the example, the HTTP destination is created using a plain URL.
|
"In the example, the HTTP destination is created using a plain URL.
|
||||||
@@ -2441,9 +2455,19 @@ CLASS zcl_some_class IMPLEMENTATION.
|
|||||||
"Sending an HTTP GET request and returning the response
|
"Sending an HTTP GET request and returning the response
|
||||||
"In the example, the HTTP body is retrieved as string data.
|
"In the example, the HTTP body is retrieved as string data.
|
||||||
DATA(response) = http_client->execute( if_web_http_client=>get )->get_text( ).
|
DATA(response) = http_client->execute( if_web_http_client=>get )->get_text( ).
|
||||||
|
IF response CS `API rate limit exceeded`.
|
||||||
|
out->write( `API rate limit exceeded` ).
|
||||||
|
RETURN.
|
||||||
|
ENDIF.
|
||||||
|
|
||||||
CATCH cx_root INTO DATA(err).
|
CATCH cx_root INTO DATA(err).
|
||||||
out->write( err->get_text( ) ).
|
out->write( err->get_text( ) ).
|
||||||
|
RETURN.
|
||||||
ENDTRY.
|
ENDTRY.
|
||||||
|
|
||||||
|
|
||||||
|
"----------- Retrieving Markdown content from ABAP cheat sheet GitHub repository -----------
|
||||||
|
|
||||||
IF err IS INITIAL.
|
IF err IS INITIAL.
|
||||||
"Markdown file names are contained in the returned string in a specific
|
"Markdown file names are contained in the returned string in a specific
|
||||||
"pattern. In the following code, the markdown file names are extracted
|
"pattern. In the following code, the markdown file names are extracted
|
||||||
@@ -2465,7 +2489,7 @@ CLASS zcl_some_class IMPLEMENTATION.
|
|||||||
ENDLOOP.
|
ENDLOOP.
|
||||||
SORT tab BY file_name ASCENDING.
|
SORT tab BY file_name ASCENDING.
|
||||||
|
|
||||||
"In the following loop, the raw markdown content is retrieved using an HTTP GET request, also
|
"In the following loop, the Markdown content is retrieved using an HTTP GET request, also
|
||||||
"by creating a client object and using a destination (another plain URL). The URL is constructed
|
"by creating a client object and using a destination (another plain URL). The URL is constructed
|
||||||
"using the constant value plus the markdown file that was retrieved before.
|
"using the constant value plus the markdown file that was retrieved before.
|
||||||
LOOP AT tab REFERENCE INTO DATA(cs).
|
LOOP AT tab REFERENCE INTO DATA(cs).
|
||||||
@@ -2473,143 +2497,59 @@ CLASS zcl_some_class IMPLEMENTATION.
|
|||||||
TRY.
|
TRY.
|
||||||
http_client = cl_web_http_client_manager=>create_by_http_destination( i_destination = cl_http_destination_provider=>create_by_url( i_url = url ) ).
|
http_client = cl_web_http_client_manager=>create_by_http_destination( i_destination = cl_http_destination_provider=>create_by_url( i_url = url ) ).
|
||||||
DATA(raw_md) = http_client->execute( if_web_http_client=>get )->get_text( ).
|
DATA(raw_md) = http_client->execute( if_web_http_client=>get )->get_text( ).
|
||||||
"Putting the long string that was retrieved in an internal table of type string
|
cs->markdown = raw_md.
|
||||||
"for further processing (extracting the code snippets).
|
CATCH cx_root.
|
||||||
SPLIT raw_md AT |\n| INTO TABLE snippets.
|
|
||||||
DATA(flag) = ''.
|
|
||||||
"In the loop, all content from the markdown that is not part of a code
|
|
||||||
"snippet (indicated by the triple ```) is deleted.
|
|
||||||
"The replacements with dummy content in the loop are only done so that
|
|
||||||
"the POST request further down can work with the provided content
|
|
||||||
"(i.e. avoiding issues with characters such as "; they are inserted later again).
|
|
||||||
LOOP AT snippets REFERENCE INTO DATA(line).
|
|
||||||
DATA(tabix) = sy-tabix.
|
|
||||||
FIND PCRE '^\s*```' IN line->*.
|
|
||||||
IF sy-subrc = 0 AND flag = ''.
|
|
||||||
line->* = `%%%--START--%%%%`.
|
|
||||||
flag = 'X'.
|
|
||||||
ELSEIF sy-subrc = 0 AND flag = 'X'.
|
|
||||||
line->* = `%%%--END--%%%%`.
|
|
||||||
flag = ''.
|
|
||||||
ELSEIF flag <> 'X'.
|
|
||||||
DELETE snippets INDEX tabix.
|
|
||||||
ELSE.
|
|
||||||
FIND PCRE `^\s*"` IN line->*.
|
|
||||||
IF sy-subrc = 0.
|
|
||||||
DATA(comment1) = 'X'.
|
|
||||||
ENDIF.
|
|
||||||
FIND PCRE `^\*` IN line->*.
|
|
||||||
IF sy-subrc = 0.
|
|
||||||
DATA(comment2) = 'X'.
|
|
||||||
ENDIF.
|
|
||||||
FIND `***********************************************************************`
|
|
||||||
IN line->*.
|
|
||||||
IF sy-subrc = 0.
|
|
||||||
DATA(divider) = 'X'.
|
|
||||||
ENDIF.
|
|
||||||
IF comment1 = 'X' OR comment2 = 'X' OR divider = 'X'.
|
|
||||||
DELETE snippets INDEX tabix.
|
|
||||||
CLEAR: comment1, comment2, divider.
|
|
||||||
ELSE.
|
|
||||||
REPLACE ALL OCCURRENCES OF `"` IN line->* WITH `§§§§§`.
|
|
||||||
REPLACE ALL OCCURRENCES OF `\` IN line->* WITH `%%%%%`.
|
|
||||||
ENDIF.
|
|
||||||
ENDIF.
|
|
||||||
ENDLOOP.
|
|
||||||
"Adding the code snippets to the information table
|
|
||||||
cs->code_snippets = snippets.
|
|
||||||
CLEAR snippets.
|
|
||||||
CATCH cx_root INTO err.
|
|
||||||
cs->error = abap_true.
|
cs->error = abap_true.
|
||||||
ENDTRY.
|
ENDTRY.
|
||||||
DELETE ADJACENT DUPLICATES FROM cs->code_snippets COMPARING table_line.
|
|
||||||
ENDLOOP.
|
ENDLOOP.
|
||||||
"Creating the final html to be displayed
|
|
||||||
LOOP AT tab REFERENCE INTO cs WHERE code_snippets IS NOT INITIAL AND error = abap_false.
|
"----------- Creating a zip file containing all ABAP cheat sheet Markdown documents -----------
|
||||||
LOOP AT cs->code_snippets REFERENCE INTO DATA(code).
|
|
||||||
tabix = sy-tabix.
|
DATA(zip) = NEW cl_abap_zip( ).
|
||||||
IF code->* = `%%%--START--%%%%`.
|
|
||||||
code->* = |```|.
|
"Iteratively adding the ABAP cheat sheet Markdown documents to the zip file
|
||||||
ENDIF.
|
LOOP AT tab REFERENCE INTO cs WHERE error = abap_false.
|
||||||
IF code->* = `%%%--END--%%%%`.
|
cs->file_name = cs->file_name.
|
||||||
code->* = |```|.
|
|
||||||
INSERT `*****************` && |\\n|
|
|
||||||
INTO cs->code_snippets INDEX tabix + 1.
|
|
||||||
ENDIF.
|
|
||||||
code->* = code->* && |\\n|.
|
|
||||||
ENDLOOP.
|
|
||||||
"For the POST request, concatenating the string table to a single string.
|
|
||||||
DATA(code_string) = concat_lines_of( table = cs->code_snippets ).
|
|
||||||
TRY.
|
TRY.
|
||||||
"Another creation of a client object using a destination
|
DATA(conv_xstring) = cl_abap_conv_codepage=>create_out( codepage = `UTF-8` )->convert( cs->markdown ).
|
||||||
"This example deals with a POST request.
|
CATCH cx_sy_conversion_codepage.
|
||||||
http_client = cl_web_http_client_manager=>create_by_http_destination( i_destination = cl_http_destination_provider=>create_by_url( i_url = url_api ) ).
|
|
||||||
DATA(request) = http_client->get_http_request( ).
|
|
||||||
request->set_text( `{"text":"` && code_string && `"}` ).
|
|
||||||
request->set_header_fields( VALUE #( ( name = 'Accept' value = 'application/vnd.github+json' ) ) ).
|
|
||||||
DATA(post) = http_client->execute( if_web_http_client=>post ).
|
|
||||||
DATA(status) = post->get_status( ).
|
|
||||||
IF status-code <> 200.
|
|
||||||
cs->error = abap_true.
|
|
||||||
DATA(status_error) = |Post request error: { status-code } / { status-reason }|.
|
|
||||||
ELSE.
|
|
||||||
"Retrieving the created html code
|
|
||||||
DATA(html_code) = post->get_text( ).
|
|
||||||
REPLACE ALL OCCURRENCES OF `§§§§§` IN html_code WITH `"`.
|
|
||||||
REPLACE ALL OCCURRENCES OF `%%%%%` IN html_code WITH `\`.
|
|
||||||
REPLACE ALL OCCURRENCES OF PCRE `(<code>)(\w.*)` IN html_code WITH `$1 $2`.
|
|
||||||
ENDIF.
|
|
||||||
CATCH cx_root INTO DATA(error).
|
|
||||||
cs->error = abap_true.
|
|
||||||
ENDTRY.
|
ENDTRY.
|
||||||
"Preparing the title for expandable sections
|
|
||||||
DATA(title) = cs->file_name.
|
"Adding the xstring content as file content to zip
|
||||||
REPLACE ALL OCCURRENCES OF `_` IN title WITH ` `.
|
zip->add( name = cs->file_name
|
||||||
REPLACE PCRE `^..` IN title WITH ``.
|
content = conv_xstring ).
|
||||||
REPLACE `.md` IN title WITH ``.
|
|
||||||
"Assembling expandable sections
|
|
||||||
html = html &&
|
|
||||||
`<br><details>` &&
|
|
||||||
` <summary>` && title && `</summary>` &&
|
|
||||||
COND #( WHEN cs->error = abap_false THEN html_code ELSE COND #( WHEN error IS INITIAL THEN status_error ELSE error->get_text( ) ) ) &&
|
|
||||||
`</details>`.
|
|
||||||
ENDLOOP.
|
ENDLOOP.
|
||||||
"Providing the html skeleton and inserting the assembled expandable sections from above
|
|
||||||
DATA(final_html) =
|
"Saving the zip file
|
||||||
`<!DOCTYPE html>` &&
|
DATA(zipped_file) = zip->save( ).
|
||||||
`<html>` &&
|
|
||||||
`<head>` &&
|
"----------- Creating a ZIP file containing all ABAP cheat sheet Markdown documents -----------
|
||||||
`<title>ABAP Cheat Sheet Code Snippets</title>` &&
|
|
||||||
`<style>` &&
|
"Sending email
|
||||||
` body {background-color: #F8F8F8;}` &&
|
TRY.
|
||||||
` h1 {color: blue; font-family: verdana;}` &&
|
"Creating a new mail instance
|
||||||
` pre {background: #f4f4f4;border: 1px solid #ddd;border-left: 3px solid #0070f2;color: #36454F;` &&
|
DATA(mail) = cl_bcs_mail_message=>create_instance( ).
|
||||||
` page-break-inside: avoid;font-size: 14px;line-height: 1.3;max-width: 100%;overflow: auto;padding: 1em 1.5em;` &&
|
"Settings
|
||||||
` display: block;word-wrap: break-word;} ` &&
|
mail->set_sender( sender_addr ).
|
||||||
`</style>` &&
|
mail->add_recipient( recipient_addr ).
|
||||||
`</head>` &&
|
mail->set_subject( 'Test Mail' ).
|
||||||
`<body>` &&
|
"Main document
|
||||||
`<h1>ABAP Cheat Sheet Code Snippets</h1>` &&
|
mail->set_main( cl_bcs_mail_textpart=>create_instance(
|
||||||
`<a href="https://github.com/SAP-samples/abap-cheat-sheets">https://github.com/SAP-samples/abap-cheat-sheets</a><br><br>` &&
|
iv_content = '<h3>Test Mail</h3><p>Please find ABAP cheat sheet markdown files attached.<br>Cheers</p>'
|
||||||
html &&
|
iv_content_type = 'text/html' ) ).
|
||||||
`<script>` &&
|
"Adding an attachment
|
||||||
` const snippets = document.querySelectorAll("code");` &&
|
mail->add_attachment( cl_bcs_mail_binarypart=>create_instance(
|
||||||
` snippets.forEach(elem => {` &&
|
iv_content = zipped_file
|
||||||
` var abap = elem.innerHTML;` &&
|
iv_content_type = 'application/x-zip-compressed'
|
||||||
` abap = abap.replace(/(\b[A-Z]{2,}\b)/g, "<strong>$1</strong>");` &&
|
iv_filename = 'abap_cheat_sheets.zip' ) ).
|
||||||
` elem.innerHTML = abap;` &&
|
|
||||||
` });` &&
|
"Sending mail synchronously, displaying the status for each recipient
|
||||||
`</script>` &&
|
mail->send( IMPORTING et_status = DATA(status_table) ).
|
||||||
`</body>` &&
|
out->write( status_table ).
|
||||||
`</html>`.
|
CATCH cx_bcs_mail INTO DATA(error_mail).
|
||||||
"Displaying the html result in the ADT console
|
out->write( |Mail sending error: { error_mail->get_text( ) }| ).
|
||||||
"Note: Before running the class, clear the ADT console.
|
ENDTRY.
|
||||||
"When the html code is displayed in the ADT console, you can, for example,
|
|
||||||
"create a file named ABAP_cheat_sheet_code.html on your local machine.
|
|
||||||
"Open the file in an editor, copy & paste the entire ADT console content and
|
|
||||||
"save the local file. In doing so, you have various code snippets at your
|
|
||||||
"disposal offline.
|
|
||||||
out->write( final_html ).
|
|
||||||
ENDIF.
|
ENDIF.
|
||||||
ENDMETHOD.
|
ENDMETHOD.
|
||||||
ENDCLASS.
|
ENDCLASS.
|
||||||
@@ -3293,7 +3233,7 @@ ENDCLASS.
|
|||||||
<td> <code>CL_ABAP_ZIP</code> </td>
|
<td> <code>CL_ABAP_ZIP</code> </td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
The following example creates a zip file and adds three txt files with sample content.
|
The following example creates a zip file and adds three txt files with sample content.
|
||||||
|
|
||||||
```abap
|
```abap
|
||||||
"Create zip file
|
"Create zip file
|
||||||
|
|||||||
Reference in New Issue
Block a user