contentstack_utils 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 759c06ba41beb4747785a6d55ac266954fd55a22a118c4cc82e9589b2f44c137
4
- data.tar.gz: 1d12fcfce0cc480300d3f07786757e0ec37d6a0b31b36352fcc53b4a5b466ede
3
+ metadata.gz: 45608729d00c39aa34058014c55b5704af78a59d1296b3c2edfe28469d85787d
4
+ data.tar.gz: 5fefcde66ac69b48c7185dd9625dcf71b7b4fbd9921578ba6cf728f28d5ca938
5
5
  SHA512:
6
- metadata.gz: 47522ef3975f83f27fa6a8d3a7b0414637e3aac7b96ea7aa605fa82294b5b28eeae874980bbe2c95e4e5f7aac237eafe82b85a21ecfdb006a205e77186bae205
7
- data.tar.gz: 501bf8584aa0ca41b10b8f55aa3565a1363e46fc7f082f58db3574dd04efeb1f29152b857d2bfc701953597c0409195428a31dd755a38d10b013a901a4b9e8ee
6
+ metadata.gz: 10901b878dd07194d11ff7c712c47c4ccd3dfe5d549f988d69bb30298d917f18bd1f8f93638f0b527fb60d5bc236d37f992224570b9ac70ae8a97aaaf32350c4
7
+ data.tar.gz: 6488de4c8ed0da29acc7fc1c2396dc6f645608a6cca60dc60973719baa5fc0cdb50ca8efc1395de8c1aa58edead695c4f4cbeca8c35cf8538b39a365439a297c
data/.gitignore CHANGED
@@ -1,4 +1,4 @@
1
- contentstack-*
1
+ contentstack_utils-*
2
2
  build_doc.sh
3
3
  test
4
4
  doc
@@ -7,4 +7,5 @@ coverage
7
7
  \.yardoc
8
8
  .DS_Store
9
9
  .bundle/
10
- */rspec_results.html
10
+ **/rspec_results.html
11
+ .dccache
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.0](https://github.com/contentstack/contentstack-utils-ruby/tree/v1.1.0) (2021-08-10)
4
+ - GQL Json rte to Html content support added
5
+
6
+ ## [1.0.2](https://github.com/contentstack/contentstack-utils-ruby/tree/v1.0.2) (2021-07-16)
7
+ - JSON RTE support added
3
8
  ## [1.0.1](https://github.com/contentstack/contentstack-utils-ruby/tree/v1.0.1) (2021-06-02)
4
9
  - Gemspec Dependency update
5
10
 
data/CODEOWNERS ADDED
@@ -0,0 +1 @@
1
+ * @contentstack/security-admin @contentstack/sdk-admin
data/Gemfile.lock CHANGED
@@ -1,36 +1,36 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- contentstack_utils (1.0.1)
4
+ contentstack_utils (1.1.0)
5
5
  activesupport (>= 3.2, < 6.2)
6
- nokogiri (~> 1.11.0)
6
+ nokogiri (~> 1.11, >= 1.11.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (6.1.3.2)
11
+ activesupport (6.1.5)
12
12
  concurrent-ruby (~> 1.0, >= 1.0.2)
13
13
  i18n (>= 1.6, < 2)
14
14
  minitest (>= 5.1)
15
15
  tzinfo (~> 2.0)
16
16
  zeitwerk (~> 2.3)
17
- addressable (2.7.0)
17
+ addressable (2.8.0)
18
18
  public_suffix (>= 2.0.2, < 5.0)
19
- concurrent-ruby (1.1.8)
19
+ concurrent-ruby (1.1.10)
20
20
  crack (0.4.5)
21
21
  rexml
22
22
  diff-lcs (1.4.4)
23
23
  docile (1.4.0)
24
24
  hashdiff (1.0.1)
25
- i18n (1.8.10)
25
+ i18n (1.10.0)
26
26
  concurrent-ruby (~> 1.0)
27
- mini_portile2 (2.5.3)
28
- minitest (5.14.4)
29
- nokogiri (1.11.6)
30
- mini_portile2 (~> 2.5.0)
27
+ mini_portile2 (2.8.0)
28
+ minitest (5.15.0)
29
+ nokogiri (1.13.4)
30
+ mini_portile2 (~> 2.8.0)
31
31
  racc (~> 1.4)
32
- public_suffix (4.0.6)
33
- racc (1.5.2)
32
+ public_suffix (4.0.7)
33
+ racc (1.6.0)
34
34
  rake (13.0.3)
35
35
  rexml (3.2.5)
36
36
  rspec (3.10.0)
@@ -59,7 +59,7 @@ GEM
59
59
  crack (>= 0.3.2)
60
60
  hashdiff (>= 0.4.0, < 2.0.0)
61
61
  yard (0.9.26)
62
- zeitwerk (2.4.2)
62
+ zeitwerk (2.5.4)
63
63
 
64
64
  PLATFORMS
65
65
  ruby
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2012-2021 Contentstack. All Rights Reserved
3
+ Copyright (c) 2012-2022 Contentstack. All Rights Reserved
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -86,3 +86,12 @@ require 'contentstack'
86
86
  Contentstack.render_content(@entry.rte_field_uid, ContentstackUtils::Model::Option.new(@entry))
87
87
  end
88
88
  ```
89
+ ### GQL Json RTE to HTML
90
+ To parse JSON RTE content from GQL response to HTML content use `ContentstackUtils::GQL.json_to_html` function as below:
91
+
92
+ ```ruby
93
+ require 'contentstack_utils'
94
+
95
+ result = ContentstackUtils::GQL.json_to_html(entry['single_rte'], ContentstackUtils::Model::Options.new())
96
+
97
+ ```
data/SECURITY.md ADDED
@@ -0,0 +1,27 @@
1
+ ## Security
2
+
3
+ Contentstack takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations.
4
+
5
+ If you believe you have found a security vulnerability in any Contentstack-owned repository, please report it to us as described below.
6
+
7
+ ## Reporting Security Issues
8
+
9
+ **Please do not report security vulnerabilities through public GitHub issues.**
10
+
11
+ Send email to [security@contentstack.com](mailto:security@contentstack.com).
12
+
13
+ You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.
14
+
15
+ Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
16
+
17
+ * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
18
+ * Full paths of source file(s) related to the manifestation of the issue
19
+ * The location of the affected source code (tag/branch/commit or direct URL)
20
+ * Any special configuration required to reproduce the issue
21
+ * Step-by-step instructions to reproduce the issue
22
+ * Proof-of-concept or exploit code (if possible)
23
+ * Impact of the issue, including how an attacker might exploit the issue
24
+
25
+ This information will help us triage your report more quickly.
26
+
27
+ [https://www.contentstack.com/trust/](https://www.contentstack.com/trust/)
@@ -3,29 +3,46 @@ module ContentstackUtils
3
3
  module Model
4
4
  class Metadata
5
5
  def initialize( element )
6
- @itemType = element.attribute('type')
7
- @styleType = element.attribute('sys-style-type')
8
- @itemUid ||= element.attribute('data-sys-entry-uid') || element.attribute('data-sys-asset-uid')
9
- @contentTypeUid = element.attribute('data-sys-content-type-uid')
10
- @text = element.text
11
- @element = element
12
- @attributes = element.attributes
6
+ if element.instance_of? Nokogiri::XML::Element
7
+ @itemType = element.attribute('type') ? element.attribute('type').value : nil
8
+ @styleType = element.attribute('sys-style-type') ? element.attribute('sys-style-type').value : nil
9
+ @itemUid ||= (element.attribute('data-sys-entry-uid') ? element.attribute('data-sys-entry-uid').value : nil) || (element.attribute('data-sys-asset-uid') ? element.attribute('data-sys-asset-uid').value : nil)
10
+ @contentTypeUid = element.attribute('data-sys-content-type-uid') ? element.attribute('data-sys-content-type-uid').value : nil
11
+ @text = element.text
12
+ @element = element
13
+ @attributes = element
14
+ else
15
+ @itemType = element["attrs"]['type']
16
+ @styleType = element["attrs"]['display-type']
17
+ @itemUid ||= element["attrs"]['entry-uid'] || element["attrs"]['asset-uid']
18
+ @contentTypeUid = element["attrs"]['content-type-uid']
19
+ if element["children"] && element["children"].length() > 0
20
+ child = element["children"]
21
+ for item in child do
22
+ if item["type"] == nil && item["text"]
23
+ @text = item["text"]
24
+ end
25
+ end
26
+ end
27
+ @element = element
28
+ @attributes = element["attrs"]
29
+ end
13
30
  end
14
31
 
15
32
  def item_type
16
- @itemType ? @itemType.value : nil
33
+ @itemType ? @itemType : nil
17
34
  end
18
35
 
19
36
  def style_type
20
- @styleType ? @styleType.value : nil
37
+ @styleType ? @styleType : nil
21
38
  end
22
39
 
23
40
  def item_uid
24
- @itemUid ? @itemUid.value : nil
41
+ @itemUid ? @itemUid : nil
25
42
  end
26
43
 
27
44
  def content_type_uid
28
- @contentTypeUid ? @contentTypeUid.value : nil
45
+ @contentTypeUid ? @contentTypeUid : nil
29
46
  end
30
47
 
31
48
  def text
@@ -39,6 +56,14 @@ module ContentstackUtils
39
56
  def attributes
40
57
  @attributes
41
58
  end
59
+
60
+ def get_attribute_value(string)
61
+ if @attributes.instance_of? Nokogiri::XML::Element
62
+ @attributes.attribute(string) ? @attributes.attribute(string).value : nil
63
+ else
64
+ @attributes[string]
65
+ end
66
+ end
42
67
  end
43
68
  end
44
69
  end
@@ -5,7 +5,7 @@ module ContentstackUtils
5
5
  module Model
6
6
  class Options < Interface::Rendarable
7
7
 
8
- def initialize(entry)
8
+ def initialize(entry = nil)
9
9
  @entry = entry
10
10
  end
11
11
 
@@ -17,15 +17,94 @@ module ContentstackUtils
17
17
  renderString = ''
18
18
  case metadata.style_type
19
19
  when 'block'
20
- renderString = "<div><p>#{embeddedObject['title'] || embeddedObject['uid']}</p><p>Content type: <span>#{embeddedObject['_content_type_uid']}</span></p></div>"
20
+ renderString = "<div><p>#{embeddedObject['title'] || embeddedObject['uid']}</p><p>Content type: <span>#{embeddedObject['_content_type_uid'] || embeddedObject['system']['content_type_uid']}</span></p></div>"
21
21
  when 'inline'
22
22
  renderString = "<span>#{embeddedObject["title"] || embeddedObject["uid"]}</span>";
23
23
  when 'link'
24
- renderString = "<a href='#{(metadata.attributes["href"] ? metadata.attributes["href"].value : nil) || embeddedObject["url"] || embeddedObject["title"] || embeddedObject["uid"]}'>#{(metadata.text && metadata.text != '' ? metadata.text : (embeddedObject["title"] || embeddedObject["uid"]))}</a>";
24
+ metadata.get_attribute_value("href")
25
+ renderString = "<a href='#{metadata.get_attribute_value("href") || embeddedObject["url"] || embeddedObject["title"] || embeddedObject["uid"]}'>#{(metadata.text && metadata.text != '' ? metadata.text : (embeddedObject["title"] || embeddedObject["uid"]))}</a>";
25
26
  when 'display'
26
- renderString = "<img src='#{(metadata.attributes["href"] ? metadata.attributes["href"].value : nil)|| embeddedObject["url"]}' alt='#{(metadata.attributes["alt"] ? metadata.attributes["alt"].value : (embeddedObject["title"] || embeddedObject["filename"] || embeddedObject["uid"]))}' />";
27
+ renderString = "<img src='#{metadata.get_attribute_value("src")|| embeddedObject["url"]}' alt='#{(metadata.attributes["alt"] ? metadata.attributes["alt"].value : (embeddedObject["title"] || embeddedObject["filename"] || embeddedObject["uid"]))}' />";
27
28
  when 'download'
28
- renderString = "<a href='#{(metadata.attributes["href"] ? metadata.attributes["href"].value : nil) || embeddedObject["url"]}'>#{(metadata.text && metadata.text != '' ? metadata.text : (embeddedObject["filename"] || embeddedObject["title"] || embeddedObject["uid"]))}</a>";
29
+ renderString = "<a href='#{metadata.get_attribute_value("href") || embeddedObject["url"]}'>#{(metadata.text && metadata.text != '' ? metadata.text : (embeddedObject["filename"] || embeddedObject["title"] || embeddedObject["uid"]))}</a>";
30
+ end
31
+ renderString
32
+ end
33
+
34
+ def render_mark(mark_type, text)
35
+ renderString = text
36
+ case mark_type
37
+ when 'bold'
38
+ renderString = "<strong>#{text}</strong>"
39
+ when 'italic'
40
+ renderString = "<em>#{text}</em>"
41
+ when 'underline'
42
+ renderString = "<u>#{text}</u>"
43
+ when 'strikethrough'
44
+ renderString = "<strike>#{text}</strike>"
45
+ when 'inlineCode'
46
+ renderString = "<span>#{text}</span>"
47
+ when 'subscript'
48
+ renderString = "<sub>#{text}</sub>"
49
+ when 'superscript'
50
+ renderString = "<sup>#{text}</sup>"
51
+ end
52
+ renderString
53
+ end
54
+
55
+ def render_node(node_type, node, inner_html)
56
+ renderString = ""
57
+ case node_type
58
+ when 'doc'
59
+ renderString = ""
60
+ when 'p'
61
+ renderString = "<p>#{inner_html}</p>"
62
+ when 'a'
63
+ renderString = "<a href='#{node["attrs"]["href"] || node["attrs"]["url"] || ""}'>#{inner_html}</a>"
64
+ when 'img'
65
+ renderString = "<img src='#{node["attrs"]["src"] || node["attrs"]["url"] || ""}' />#{inner_html}"
66
+ when 'embed'
67
+ renderString = "<iframe src='#{node["attrs"]["src"] || node["attrs"]["url"] || ""}'></iframe>"
68
+ when 'h1'
69
+ renderString = "<h1>#{inner_html}</h1>"
70
+ when 'h2'
71
+ renderString = "<h2>#{inner_html}</h2>"
72
+ when 'h3'
73
+ renderString = "<h3>#{inner_html}</h3>"
74
+ when 'h4'
75
+ renderString = "<h4>#{inner_html}</h4>"
76
+ when 'h5'
77
+ renderString = "<h5>#{inner_html}</h5>"
78
+ when 'h6'
79
+ renderString = "<h6>#{inner_html}</h6>"
80
+ when 'ol'
81
+ renderString = "<ol>#{inner_html}</ol>"
82
+ when 'ul'
83
+ renderString = "<ul>#{inner_html}</ul>"
84
+ when 'li'
85
+ renderString = "<li>#{inner_html}</li>"
86
+ when 'hr'
87
+ renderString = "<hr />"
88
+ when 'table'
89
+ renderString = "<table>#{inner_html}</table>"
90
+ when 'thead'
91
+ renderString = "<thead>#{inner_html}</thead>"
92
+ when 'tbody'
93
+ renderString = "<tbody>#{inner_html}</tbody>"
94
+ when 'tfoot'
95
+ renderString = "<tfoot>#{inner_html}</tfoot>"
96
+ when 'tr'
97
+ renderString = "<tr>#{inner_html}</tr>"
98
+ when 'th'
99
+ renderString = "<th>#{inner_html}</th>"
100
+ when 'td'
101
+ renderString = "<td>#{inner_html}</td>"
102
+ when 'blockquote'
103
+ renderString = "<blockquote>#{inner_html}</blockquote>"
104
+ when 'code'
105
+ renderString = "<code>#{inner_html}</code>"
106
+ when 'reference'
107
+ renderString = ""
29
108
  end
30
109
  renderString
31
110
  end
@@ -16,6 +16,82 @@ module ContentstackUtils
16
16
  end
17
17
  end
18
18
 
19
+ def self.json_to_html(content, options)
20
+ reference = -> (metadata){
21
+ result = ""
22
+ if options.entry != nil
23
+ object = findObject(metadata, options.entry)
24
+ if object!= nil && object.length() > 0
25
+ result = options.render_option(object[0], metadata)
26
+ end
27
+ end
28
+ result
29
+ }
30
+ if (content.instance_of? Array)
31
+ result = []
32
+ content.each do |n|
33
+ result.push(json_doc_to_html(n, options, reference) )
34
+ end
35
+ result
36
+ elsif content.instance_of? Hash
37
+ json_doc_to_html(content, options, reference)
38
+ end
39
+ end
40
+
41
+ def self.json_doc_to_html(node, options, callback)
42
+ result = ""
43
+ if node["children"] && node["children"].length() > 0
44
+ result = node_children_to_html(node["children"], options, callback)
45
+ end
46
+ result
47
+ end
48
+
49
+ private_class_method def self.node_children_to_html(nodes, options, callback)
50
+ nodes.map {|node| node_to_html(node, options, callback)}.join("")
51
+ end
52
+
53
+ private_class_method def self.node_to_html(node, options, callback)
54
+ html_result = ""
55
+ if node["type"] == nil && node["text"]
56
+ html_result = text_to_htms(node, options)
57
+ elsif node["type"]
58
+ if node["type"] == "reference"
59
+ metadata = Model::Metadata.new(node)
60
+ html_result = callback.call(metadata)
61
+ else
62
+ inner_html = json_doc_to_html(node, options, callback)
63
+ html_result = options.render_node(node["type"], node, inner_html)
64
+ end
65
+ end
66
+ html_result
67
+ end
68
+
69
+ private_class_method def self.text_to_htms(node, options)
70
+ text = node["text"]
71
+ if node["superscript"]
72
+ text = options.render_mark("superscript", text)
73
+ end
74
+ if node["subscript"]
75
+ text = options.render_mark("subscript", text)
76
+ end
77
+ if node["inlineCode"]
78
+ text = options.render_mark("inlineCode", text)
79
+ end
80
+ if node["strikethrough"]
81
+ text = options.render_mark("strikethrough", text)
82
+ end
83
+ if node["underline"]
84
+ text = options.render_mark("underline", text)
85
+ end
86
+ if node["italic"]
87
+ text = options.render_mark("italic", text)
88
+ end
89
+ if node["bold"]
90
+ text = options.render_mark("bold", text)
91
+ end
92
+ text
93
+ end
94
+
19
95
  private_class_method def self.render_string(string, options)
20
96
  xml_doc = Nokogiri::HTML(appendFrame(string))
21
97
  result = xml_doc.xpath('//documentfragmentcontainer').inner_html
@@ -51,4 +127,37 @@ module ContentstackUtils
51
127
  end
52
128
  return nil
53
129
  end
130
+
131
+ module GQL
132
+ include ContentstackUtils
133
+ def self.json_to_html(content, options)
134
+ embeddedItems = []
135
+ if content.has_key? 'embedded_itemsConnection'
136
+ embeddedItems = content['embedded_itemsConnection']['edges'] || []
137
+ end
138
+ reference = -> (metadata){
139
+ result = ""
140
+ if embeddedItems != nil
141
+ object = embeddedItems.select { |embedObject| embedObject['node']["system"]["uid"] == metadata.item_uid }
142
+ if object != nil && object.length() > 0
143
+ result = options.render_option(object[0]["node"], metadata)
144
+ end
145
+ end
146
+ result
147
+ }
148
+
149
+ if content.has_key? 'json'
150
+ json = content['json']
151
+ if (json.instance_of? Array)
152
+ result = []
153
+ json.each do |n|
154
+ result.push(ContentstackUtils.json_doc_to_html(n, options, reference))
155
+ end
156
+ result
157
+ elsif json.instance_of? Hash
158
+ ContentstackUtils.json_doc_to_html(json, options, reference)
159
+ end
160
+ end
161
+ end
162
+ end
54
163
  end
@@ -1,3 +1,3 @@
1
1
  module ContentstackUtils
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.1"
3
3
  end
@@ -51,5 +51,45 @@ RSpec.describe ContentstackUtils::Model::Metadata do
51
51
  expect(metadata.text).to eq 'TEST'
52
52
  end
53
53
  end
54
+
55
+ it 'Asset Json To metadata' do
56
+ doc = getJson(AssetReferenceJson)
57
+ metadata = ContentstackUtils::Model::Metadata.new(doc["children"][0])
58
+ expect(metadata.item_type).to eq "asset"
59
+ expect(metadata.style_type).to eq "display"
60
+ expect(metadata.item_uid).to eq "asset_uid_1"
61
+ expect(metadata.content_type_uid).to eq 'sys_assets'
62
+ expect(metadata.text).to eq ''
63
+ end
64
+
65
+ it 'Entry Block Json To metadata' do
66
+ doc = getJson(EntryReferenceBlockJson)
67
+ metadata = ContentstackUtils::Model::Metadata.new(doc["children"][0])
68
+ expect(metadata.item_type).to eq "entry"
69
+ expect(metadata.style_type).to eq "block"
70
+ expect(metadata.item_uid).to eq "entry_uid_1"
71
+ expect(metadata.content_type_uid).to eq 'content_block'
72
+ expect(metadata.text).to eq ''
73
+ end
74
+
75
+ it 'Entry Link Json To metadata' do
76
+ doc = getJson(EntryReferenceLinkJson)
77
+ metadata = ContentstackUtils::Model::Metadata.new(doc["children"][0])
78
+ expect(metadata.item_type).to eq "entry"
79
+ expect(metadata.style_type).to eq "link"
80
+ expect(metadata.item_uid).to eq "entry_uid_2"
81
+ expect(metadata.content_type_uid).to eq 'embeddedrte'
82
+ expect(metadata.text).to eq "/copy-of-entry-final-02"
83
+ end
84
+
85
+ it 'Entry Inline Json To metadata' do
86
+ doc = getJson(EntryReferenceInlineJson)
87
+ metadata = ContentstackUtils::Model::Metadata.new(doc["children"][0])
88
+ expect(metadata.item_type).to eq "entry"
89
+ expect(metadata.style_type).to eq "inline"
90
+ expect(metadata.item_uid).to eq "entry_uid_3"
91
+ expect(metadata.content_type_uid).to eq 'embeddedrte'
92
+ expect(metadata.text).to eq ''
93
+ end
54
94
  end
55
95
  end