Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions shopify-dev-utils/convertToGlobalDataStructure.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,78 @@
module.exports.convertToGlobalDataStructure = function convertToGlobalDataStructure(gqlData) {
// return gqlData;
const firstProduct = gqlData.products.edges[0].node;
const product = {
id: firstProduct.id,
title: firstProduct.title,
handle: firstProduct.handle,
description: firstProduct.description,
content: firstProduct.description,
published_at: firstProduct.publishedAt,
created_at: firstProduct.createdAt,
vendor: firstProduct.vendor,
type: firstProduct.productType,
tags: firstProduct.tags,
available: firstProduct.availableForSale,
price: firstProduct.priceRange.maxVariantPrice, // preserve the entire obj for money-* filters
price_min: firstProduct.priceRange.minVariantPrice,
price_max: firstProduct.priceRange.maxVariantPrice,
price_varies:
+firstProduct.priceRange.maxVariantPrice.amount !==
+firstProduct.priceRange.minVariantPrice,
compare_at_price: firstProduct.compareAtPriceRange.maxVariantPrice, // preserve the entire obj for money-* filters,
compare_at_price_min: firstProduct.compareAtPriceRange.minVariantPrice,
compare_at_price_max: firstProduct.compareAtPriceRange.maxVariantPrice,
compare_at_price_varies:
+firstProduct.compareAtPriceRange.maxVariantPrice.amount !==
+firstProduct.compareAtPriceRange.minVariantPrice,
images: firstProduct.images.edges.map(({ node }) => node.originalSrc),
featured_image:
firstProduct.images.edges.length > 0 ? firstProduct.images.edges[0].node : '',
media: firstProduct.images.edges.map(({ node }, index) => {
const image = {
aspect_ratio: node.height / node.width,
height: node.height,
width: node.width,
src: node.originalSrc,
};
return {
id: node.id,
alt: node.altText,
position: index + 1,
media_type: 'image',
preview_image: image,
...image,
};
}),
options: firstProduct.options.map(({ name }) => name),
options_by_name: firstProduct.options.reduce((result, option) => {
result[option.name] = option;
return result;
}, {}),
variants: firstProduct.variants.edges.map(({ node }) => {
return {
id: node.id,
title: node.title,
public_title: null,
options: node.selectedOptions.map((option) => option.value),
option1: (node.selectedOptions[0] && node.selectedOptions[0].value) || null,
option2: (node.selectedOptions[1] && node.selectedOptions[1].value) || null,
option3: (node.selectedOptions[2] && node.selectedOptions[2].value) || null,
sku: node.sku,
requires_shipping: node.requiresShipping,
taxable: true,
featured_image: node.image,
available: node.availableForSale,
name: firstProduct.title,
weight: node.weight,
price: node.priceV2,
compare_at_price: node.compareAtPriceV2,
inventory_management: 'shopify',
barcode: '',
};
}),
};

return {
shop: {
name: gqlData.shop.name,
Expand Down Expand Up @@ -34,5 +107,9 @@ module.exports.convertToGlobalDataStructure = function convertToGlobalDataStruct
: null,
})),
})),
product: {
...product,
selected_or_first_available_variant: product.variants[0] || null,
},
};
};
14 changes: 14 additions & 0 deletions shopify-dev-utils/filters/img_url.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const path = require('path');

module.exports.imgUrl = function imgUrl(image, size) {
if (!image || !image.originalSrc) {
return '';
}

const [imgPath, query] = image.originalSrc.split('?');
const imageParts = path.parse(imgPath);

return `${imageParts.dir}/${imageParts.name}${size !== 'master' ? '_' + size : ''}${
imageParts.ext
}?${query}`;
};
4 changes: 2 additions & 2 deletions shopify-dev-utils/liquidDev.entry.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const context = require.context(
'../src',
true,
/(collection|footer|featured-product|featured-collection|header|message)\.liquid$/
/(global-css|product|collection|footer|featured-product|featured-collection|header|message)\.liquid$/
);

const cache = {};
Expand Down Expand Up @@ -29,7 +29,7 @@ if (module.hot) {
const newContext = require.context(
'../src',
true,
/(collection|footer|featured-product|featured-collection|header|message)\.liquid$/
/(global-css|product|collection|footer|featured-product|featured-collection|header|message)\.liquid$/
);
const changes = [];
newContext.keys().forEach(function (key) {
Expand Down
4 changes: 4 additions & 0 deletions shopify-dev-utils/liquidDev.loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ const { defaultPagination } = require('./filters/default_pagination');
const { scriptTag } = require('./filters/script_tag');
const { stylesheetTag } = require('./filters/stylesheet_tag');
const { assetUrl } = require('./filters/asset_url');
const { imgUrl } = require('./filters/img_url');
const { getStoreGlobalData } = require('./storeData');
const { liquidSectionTags } = require('./section-tags/index');
const { Paginate } = require('./tags/paginate');
const { Style } = require('./tags/style');

let engine;
let loadPromise;
Expand Down Expand Up @@ -44,8 +46,10 @@ function initEngine() {
engine.registerFilter('within', within);
engine.registerFilter('money_with_currency', moneyWithCurrency);
engine.registerFilter('money_without_trailing_zeros', moneyWithoutTrailingZeros);
engine.registerFilter('img_url', imgUrl);

engine.registerTag('paginate', Paginate);
engine.registerTag('style', Style);
engine.plugin(liquidSectionTags());

resolve();
Expand Down
13 changes: 7 additions & 6 deletions shopify-dev-utils/section-tags/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
exports.liquidSectionTags = void 0;
const javascript_1 = require("./javascript");
const schema_1 = require("./schema");
const section_1 = require("./section");
const stylesheet_1 = require("./stylesheet");
const javascript_1 = require('./javascript');
const schema_1 = require('./schema');
const section_1 = require('./section');
const stylesheet_1 = require('./stylesheet');

function liquidSectionTags() {
return function () {
this.registerTag('section', section_1.Section);
Expand Down
1 change: 1 addition & 0 deletions shopify-dev-utils/storeData.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ async function getStoreGlobalData() {
},
},
collection: data.collections[0],
product: data.product,
};
}

Expand Down
92 changes: 89 additions & 3 deletions shopify-dev-utils/storefrontApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ const Axios = require('axios');

class StorefrontApi {
constructor({ baseURL, token }) {
console.log(`https://${baseURL}/api/2020-10/graphql`);
this.axios = Axios.create({
baseURL: `https://${baseURL}/api/2020-10/graphql`,
baseURL: `https://${baseURL}/api/2021-01/graphql.json`,
headers: {
Accept: 'application/json',
'Content-Type': 'application/graphql',
'X-Shopify-Storefront-Access-Token': token,
},
});
}

// GQL query can be tested https://shopify.dev/graphiql/storefront-graphiql
async getStoreData() {
return this.axios
.post(
Expand Down Expand Up @@ -69,6 +68,93 @@ class StorefrontApi {
}
}
}
products(first: 10) {
edges {
node {
id
handle
createdAt
publishedAt
vendor
tags
description
descriptionHtml
title
tags
priceRange {
maxVariantPrice {
amount
currencyCode
}
minVariantPrice {
amount
currencyCode
}
}
compareAtPriceRange {
maxVariantPrice {
amount
currencyCode
}
minVariantPrice {
amount
currencyCode
}
}
options {
id
name
values
}
variants(first: 10) {
edges {
node {
id
title
sku
priceV2 {
amount
currencyCode
}
compareAtPriceV2 {
amount
currencyCode
}
selectedOptions {
name
value
}
availableForSale
quantityAvailable
requiresShipping
weight
image {
id
height
altText
width
originalSrc
}
}
}
}
productType
images(first: 10) {
edges {
node {
id
altText
height
width
originalSrc

}
}
}
availableForSale
}
}
}
}
`
)
Expand Down
2 changes: 2 additions & 0 deletions shopify-dev-utils/tags/style.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { TagImplOptions } from 'liquidjs/dist/template/tag/tag-impl-options';
export declare const Style: TagImplOptions;
24 changes: 24 additions & 0 deletions shopify-dev-utils/tags/style.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Style = void 0;
exports.Style = {
parse: function (tagToken, remainTokens) {
this.tokens = [];
const stream = this.liquid.parser.parseStream(remainTokens);
stream
.on('token', (token) => {
if (token.name === 'endstyle')
stream.stop();
else
this.tokens.push(token);
})
.on('end', () => {
throw new Error(`tag ${tagToken.getText()} not closed`);
});
stream.start();
},
render: function () {
const text = this.tokens.map((token) => token.getText()).join('');
return `<style data-shopify="">${text}</style>`;
}
};
27 changes: 5 additions & 22 deletions src/components/sections/product/product.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,15 @@
<p class="leading-relaxed">{{ product.content }}</p>
<form method="post" enctype="multipart/form-data" id="AddToCartForm">
<div class="flex mt-6 items-center">
<div class="flex ml-6 items-center">
<span class="mr-3">Size</span>
<div class="relative">
<select
class="rounded border appearance-none border-gray-400 py-2 focus:outline-none focus:border-red-500 text-base pl-3 pr-10"
id="option2">
{% for color_option in product.options_by_name['Size'].values %}
<option>{{ color_option }}</option>
{% endfor %}
</select>
<span
class="absolute right-0 top-0 h-full w-10 text-center text-gray-600 pointer-events-none flex items-center justify-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
class="w-4 h-4" viewBox="0 0 24 24">
<path d="M6 9l6 6 6-6"></path>
</svg>
</span>
</div>
</div>
{% for option in product.options %}
<div class="flex ml-6 items-center">
<span class="mr-3">Color</span>
<span class="mr-3">{{ option }}</span>
<div class="relative">
<select
class="rounded border appearance-none border-gray-400 py-2 focus:outline-none focus:border-red-500 text-base pl-3 pr-10"
id="option1">
{% for color_option in product.options_by_name['Color'].values %}
<option>{{ color_option }}</option>
{% for value in product.options_by_name[option].values %}
<option>{{ value }}</option>
{% endfor %}
</select>
<span
Expand All @@ -50,6 +32,7 @@
</span>
</div>
</div>
{% endfor %}
</div>
<div class="mt-3 pb-5 border-b-2 border-gray-200 mb-5">
{% include 'input-counter' %}
Expand Down
Loading